-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[jnigen] Parse Kotlin's metadata + Remove
suspend_fun_to_async
flag…
… in config (#308) * Parse Kotlin's metadata in API Summarizer * Remove `suspend_fun_to_async` from config now that `isSuspend` reliably detect `suspend fun`s.
- Loading branch information
1 parent
b137e33
commit 1e922cc
Showing
24 changed files
with
599 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
...ava/com/github/dart_lang/jnigen/apisummarizer/disasm/KotlinMetadataAnnotationVisitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
package com.github.dart_lang.jnigen.apisummarizer.disasm; | ||
|
||
import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl; | ||
import com.github.dart_lang.jnigen.apisummarizer.elements.KotlinClass; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import kotlinx.metadata.jvm.KotlinClassHeader; | ||
import kotlinx.metadata.jvm.KotlinClassMetadata; | ||
import org.objectweb.asm.AnnotationVisitor; | ||
|
||
/** | ||
* The format of Kotlin's metadata can be found here: | ||
* https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/ | ||
*/ | ||
public class KotlinMetadataAnnotationVisitor extends AnnotationVisitor { | ||
private ClassDecl decl; | ||
|
||
private int kind; | ||
private int[] metadataVersion; | ||
private List<String> data1 = new ArrayList<>(); | ||
private List<String> data2 = new ArrayList<>(); | ||
private String extraString; | ||
private String packageName; | ||
private int extraInt; | ||
|
||
public KotlinMetadataAnnotationVisitor(ClassDecl decl) { | ||
super(AsmConstants.API); | ||
this.decl = decl; | ||
} | ||
|
||
@Override | ||
public void visit(String name, Object value) { | ||
switch (name) { | ||
case "k": | ||
kind = (int) value; | ||
return; | ||
case "mv": | ||
metadataVersion = (int[]) value; | ||
return; | ||
case "xs": | ||
extraString = (String) value; | ||
return; | ||
case "pn": | ||
packageName = (String) value; | ||
return; | ||
case "xi": | ||
extraInt = (int) value; | ||
} | ||
} | ||
|
||
@Override | ||
public AnnotationVisitor visitArray(String name) { | ||
List<String> arr; | ||
switch (name) { | ||
case "d1": | ||
arr = data1; | ||
break; | ||
case "d2": | ||
arr = data2; | ||
break; | ||
default: | ||
return super.visitArray(name); | ||
} | ||
return new AnnotationVisitor(AsmConstants.API) { | ||
@Override | ||
public void visit(String name, Object value) { | ||
arr.add((String) value); | ||
super.visit(name, value); | ||
} | ||
}; | ||
} | ||
|
||
@Override | ||
public void visitEnd() { | ||
var header = | ||
new KotlinClassHeader( | ||
kind, | ||
metadataVersion, | ||
data1.toArray(String[]::new), | ||
data2.toArray(String[]::new), | ||
extraString, | ||
packageName, | ||
extraInt); | ||
var metadata = KotlinClassMetadata.read(header); | ||
if (metadata instanceof KotlinClassMetadata.Class) { | ||
decl.kotlinClass = | ||
KotlinClass.fromKmClass(((KotlinClassMetadata.Class) metadata).toKmClass()); | ||
} else if (metadata instanceof KotlinClassMetadata.FileFacade) { | ||
// TODO(#301): Handle file facades. | ||
} else if (metadata instanceof KotlinClassMetadata.SyntheticClass) { | ||
// Ignore synthetic classes such as lambdas. | ||
} else if (metadata instanceof KotlinClassMetadata.MultiFileClassFacade) { | ||
// Ignore multi-file classes | ||
} else if (metadata instanceof KotlinClassMetadata.MultiFileClassPart) { | ||
// Ignore multi-file classes | ||
} else if (metadata instanceof KotlinClassMetadata.Unknown) { | ||
// Unsupported | ||
} | ||
super.visitEnd(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
...en/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinClass.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
package com.github.dart_lang.jnigen.apisummarizer.elements; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import kotlinx.metadata.KmClass; | ||
import kotlinx.metadata.jvm.JvmExtensionsKt; | ||
|
||
public class KotlinClass { | ||
public String name; | ||
public String moduleName; | ||
public List<KotlinFunction> functions; | ||
public List<KotlinProperty> properties; | ||
public List<KotlinConstructor> constructors; | ||
public List<KotlinTypeParameter> typeParameters; | ||
public List<KotlinType> contextReceiverTypes; | ||
public List<KotlinType> superTypes; | ||
public List<String> nestedClasses; | ||
public List<String> enumEntries; | ||
public List<String> sealedClasses; | ||
public String companionObject; | ||
public String inlineClassUnderlyingPropertyName; | ||
public KotlinType inlineClassUnderlyingType; | ||
public int flags; | ||
public int jvmFlags; | ||
|
||
public static KotlinClass fromKmClass(KmClass c) { | ||
var klass = new KotlinClass(); | ||
klass.name = c.getName(); | ||
klass.moduleName = JvmExtensionsKt.getModuleName(c); | ||
klass.functions = | ||
c.getFunctions().stream().map(KotlinFunction::fromKmFunction).collect(Collectors.toList()); | ||
klass.properties = | ||
c.getProperties().stream().map(KotlinProperty::fromKmProperty).collect(Collectors.toList()); | ||
klass.constructors = | ||
c.getConstructors().stream() | ||
.map(KotlinConstructor::fromKmConstructor) | ||
.collect(Collectors.toList()); | ||
klass.typeParameters = | ||
c.getTypeParameters().stream() | ||
.map(KotlinTypeParameter::fromKmTypeParameter) | ||
.collect(Collectors.toList()); | ||
klass.contextReceiverTypes = | ||
c.getContextReceiverTypes().stream() | ||
.map(KotlinType::fromKmType) | ||
.collect(Collectors.toList()); | ||
klass.superTypes = | ||
c.getSupertypes().stream().map(KotlinType::fromKmType).collect(Collectors.toList()); | ||
klass.enumEntries = c.getEnumEntries(); | ||
klass.flags = c.getFlags(); | ||
klass.jvmFlags = JvmExtensionsKt.getJvmFlags(c); | ||
klass.nestedClasses = c.getNestedClasses(); | ||
klass.companionObject = c.getCompanionObject(); | ||
klass.inlineClassUnderlyingPropertyName = c.getInlineClassUnderlyingPropertyName(); | ||
klass.inlineClassUnderlyingType = KotlinType.fromKmType(c.getInlineClassUnderlyingType()); | ||
klass.sealedClasses = c.getSealedSubclasses(); | ||
return klass; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
...a/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinConstructor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
package com.github.dart_lang.jnigen.apisummarizer.elements; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import kotlinx.metadata.KmConstructor; | ||
import kotlinx.metadata.jvm.JvmExtensionsKt; | ||
|
||
public class KotlinConstructor { | ||
public String name; | ||
public String descriptor; | ||
public List<KotlinValueParameter> valueParameters; | ||
public int flags; | ||
|
||
public static KotlinConstructor fromKmConstructor(KmConstructor c) { | ||
var ctor = new KotlinConstructor(); | ||
ctor.flags = c.getFlags(); | ||
var signature = JvmExtensionsKt.getSignature(c); | ||
ctor.name = signature == null ? null : signature.getName(); | ||
ctor.descriptor = signature == null ? null : signature.getDesc(); | ||
ctor.valueParameters = | ||
c.getValueParameters().stream() | ||
.map(KotlinValueParameter::fromKmValueParameter) | ||
.collect(Collectors.toList()); | ||
return ctor; | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
...java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
package com.github.dart_lang.jnigen.apisummarizer.elements; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import kotlinx.metadata.Flag; | ||
import kotlinx.metadata.KmFunction; | ||
import kotlinx.metadata.jvm.JvmExtensionsKt; | ||
|
||
public class KotlinFunction { | ||
/** Name in the byte code. */ | ||
public String name; | ||
|
||
public String descriptor; | ||
|
||
/** Name in the Kotlin's metadata. */ | ||
public String kotlinName; | ||
|
||
public List<KotlinValueParameter> valueParameters; | ||
public KotlinType returnType; | ||
public KotlinType receiverParameterType; | ||
public List<KotlinType> contextReceiverTypes; | ||
public List<KotlinTypeParameter> typeParameters; | ||
public int flags; | ||
public boolean isSuspend; | ||
|
||
public static KotlinFunction fromKmFunction(KmFunction f) { | ||
var fun = new KotlinFunction(); | ||
var signature = JvmExtensionsKt.getSignature(f); | ||
fun.descriptor = signature == null ? null : signature.getDesc(); | ||
fun.name = signature == null ? null : signature.getName(); | ||
fun.kotlinName = f.getName(); | ||
fun.flags = f.getFlags(); | ||
// Processing the information needed from the flags. | ||
fun.isSuspend = Flag.Function.IS_SUSPEND.invoke(fun.flags); | ||
fun.valueParameters = | ||
f.getValueParameters().stream() | ||
.map(KotlinValueParameter::fromKmValueParameter) | ||
.collect(Collectors.toList()); | ||
fun.returnType = KotlinType.fromKmType(f.getReturnType()); | ||
fun.receiverParameterType = KotlinType.fromKmType(f.getReceiverParameterType()); | ||
fun.contextReceiverTypes = | ||
f.getContextReceiverTypes().stream() | ||
.map(KotlinType::fromKmType) | ||
.collect(Collectors.toList()); | ||
fun.typeParameters = | ||
f.getTypeParameters().stream() | ||
.map(KotlinTypeParameter::fromKmTypeParameter) | ||
.collect(Collectors.toList()); | ||
return fun; | ||
} | ||
} |
Oops, something went wrong.