public void remove(AnnotationHolder annotation) { AnnotationHolder existingAnnot = get(annotation.getType()); if (existingAnnot != annotation) { throw new IllegalArgumentException("There is no such annotation"); } annotations.remove(annotation.getType()); }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { AnnotationReader delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName()); if (delegateAnnot != null) { method.setProgram(null); method.getModifiers().add(ElementModifier.NATIVE); } } } }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { AnnotationReader delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName()); if (delegateAnnot != null) { method.setProgram(null); method.getModifiers().add(ElementModifier.NATIVE); } } } }
static void makeSync(MethodHolder method) { if (method.getAnnotations().get(Sync.class.getName()) == null) { AnnotationHolder annot = new AnnotationHolder(Sync.class.getName()); method.getAnnotations().add(annot); } }
private void parseAnnotations(AnnotationContainer annotations, List<AnnotationNode> visibleAnnotations, List<AnnotationNode> invisibleAnnotations) { List<Object> annotNodes = new ArrayList<>(); if (visibleAnnotations != null) { annotNodes.addAll(visibleAnnotations); } if (invisibleAnnotations != null) { annotNodes.addAll(invisibleAnnotations); } for (Object obj : annotNodes) { AnnotationNode annotNode = (AnnotationNode) obj; String desc = annotNode.desc; if (desc.startsWith("L") && desc.endsWith(";")) { desc = desc.substring(1, desc.length() - 1); } desc = desc.replace('/', '.'); if (annotations.get(desc) != null) { continue; } AnnotationHolder annot = new AnnotationHolder(referenceCache.getCached(desc)); parseAnnotationValues(annot, annotNode.values); annotations.add(annot); } }
private boolean validate(MethodHolder method, Diagnostics diagnostics) { AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName()); if (providerAnnot == null) { return false; } if (!method.hasModifier(ElementModifier.NATIVE)) { diagnostics.error(new CallLocation(method.getReference()), "Method {{m0}} is marked with " + "{{c1}} annotation, but it is not native", method.getReference(), MetadataProvider.class.getName()); return false; } return true; } }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { if (method.getAnnotations().get(JavaScriptBody.class.getName()) != null) { AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( JavaScriptBodyGenerator.class.getName()))); method.getAnnotations().add(genAnnot); method.setProgram(null); method.getModifiers().add(ElementModifier.NATIVE); } } } }
private String[] getExpectedExceptions(MethodHolder method) { AnnotationHolder annot = method.getAnnotations().get(JUNIT4_TEST); if (annot == null) { return new String[0]; } AnnotationValue expected = annot.getValue("expected"); if (expected == null) { return new String[0]; } ValueType result = expected.getJavaClass(); return new String[] { ((ValueType.Object) result).getClassName() }; }
private boolean tryDelegateToMethod(ClassHolder cls, MethodHolder method) { AnnotationHolder delegateToAnnot = method.getAnnotations().get(DelegateTo.class.getName()); if (delegateToAnnot == null) { return false; } String methodName = delegateToAnnot.getValue("value").getString(); for (MethodHolder candidate : cls.getMethods()) { if (candidate.getName().equals(methodName)) { generateMethodForwardDeclaration(method); delegateToMethod(method, candidate); return true; } } return false; }
void createJSMethods(ClassHolder cls) { for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { MethodReference methodRef = method.getReference(); if (method.getAnnotations().get(JSBody.class.getName()) == null) { continue; } requireJSBody(diagnostics, method); if (!repository.methodMap.containsKey(method.getReference())) { continue; } MethodReference proxyRef = repository.methodMap.get(methodRef); MethodHolder proxyMethod = new MethodHolder(proxyRef.getDescriptor()); proxyMethod.getModifiers().add(ElementModifier.NATIVE); proxyMethod.getModifiers().add(ElementModifier.STATIC); boolean inline = repository.inlineMethods.contains(methodRef); AnnotationHolder generatorAnnot = new AnnotationHolder(inline ? DynamicInjector.class.getName() : DynamicGenerator.class.getName()); proxyMethod.getAnnotations().add(generatorAnnot); cls.addMethod(proxyMethod); Set<MethodReference> callbacks = repository.callbackMethods.get(proxyRef); if (callbacks != null) { for (MethodReference callback : callbacks) { generateCallbackCaller(cls, callback); } } } }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { int index = 0; for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName()); if (providerAnnot != null) { transformMetadataMethod(cls, method, context.getDiagnostics(), context.getHierarchy(), index++); } providerAnnot = method.getAnnotations().get(ClassScopedMetadataProvider.class.getName()); if (providerAnnot != null) { ValueType[] params = method.getParameterTypes(); if (params.length != 1 && params[0].isObject(PlatformClass.class.getName())) { context.getDiagnostics().error(new CallLocation(method.getReference()), "Method {{m0}} marked with {{c1}} must take exactly one parameter of type {{c2}}", method.getReference(), ClassScopedMetadataProvider.class.getName(), PlatformClass.class.getName()); } AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( ClassScopedMetadataProviderNativeGenerator.class.getName()))); method.getAnnotations().add(genAnnot); } } }
private void addFunctorField(ClassHolder cls, MethodReference method) { if (cls.getAnnotations().get(FunctorImpl.class.getName()) != null) { return; } FieldHolder field = new FieldHolder("$$jso_functor$$"); field.setLevel(AccessLevel.PUBLIC); field.setType(ValueType.parse(JSObject.class)); cls.addField(field); AnnotationHolder annot = new AnnotationHolder(FunctorImpl.class.getName()); annot.getValues().put("value", new AnnotationValue(method.getDescriptor().toString())); cls.getAnnotations().add(annot); }
public NativeMethodNode decompileNative(MethodHolder method) { Generator generator = generators.get(method.getReference()); if (generator == null && !isBootstrap()) { AnnotationHolder annotHolder = method.getAnnotations().get(GeneratedBy.class.getName()); if (annotHolder == null) { throw new DecompilationException("Method " + method.getOwnerName() + "." + method.getDescriptor() + " is native, but no " + GeneratedBy.class.getName() + " annotation found"); } ValueType annotValue = annotHolder.getValues().get("value").getJavaClass(); String generatorClassName = ((ValueType.Object) annotValue).getClassName(); try { Class<?> generatorClass = Class.forName(generatorClassName, true, classLoader); generator = (Generator) generatorClass.newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new DecompilationException("Error instantiating generator " + generatorClassName + " for native method " + method.getOwnerName() + "." + method.getDescriptor()); } } NativeMethodNode methodNode = new NativeMethodNode(method.getReference()); methodNode.getModifiers().addAll(method.getModifiers()); methodNode.setGenerator(generator); methodNode.setAsync(asyncMethods.contains(method.getReference())); return methodNode; }
public ClassNode decompile(ClassHolder cls) { ClassNode clsNode = new ClassNode(cls.getName(), cls.getParent()); for (FieldHolder field : cls.getFields()) { FieldNode fieldNode = new FieldNode(field.getReference(), field.getType()); fieldNode.getModifiers().addAll(field.getModifiers()); fieldNode.setInitialValue(field.getInitialValue()); clsNode.getFields().add(fieldNode); } for (MethodHolder method : cls.getMethods()) { if (method.getModifiers().contains(ElementModifier.ABSTRACT)) { continue; } if ((!isBootstrap() && method.getAnnotations().get(InjectedBy.class.getName()) != null) || methodsToSkip.contains(method.getReference())) { continue; } MethodNode methodNode = decompile(method); clsNode.getMethods().add(methodNode); } clsNode.getInterfaces().addAll(cls.getInterfaces()); clsNode.getModifiers().addAll(cls.getModifiers()); clsNode.setAccessLevel(cls.getLevel()); return clsNode; }
renamedCls.setLevel(cls.getLevel()); String parent = cls.getParent(); AnnotationHolder superclassAnnot = cls.getAnnotations().get(Superclass.class.getName()); if (superclassAnnot != null) { parent = superclassAnnot.getValues().get("value").getString(); if (method.getAnnotations().get(Remove.class.getName()) != null) { continue;
public MethodHolder rename(MethodHolder method) { String methodName = method.getName(); AnnotationHolder renameAnnot = method.getAnnotations().get(Rename.class.getName()); if (renameAnnot != null) { methodName = renameAnnot.getValues().get("value").getString(); } ValueType[] signature = method.getSignature(); for (int i = 0; i < signature.length; ++i) { signature[i] = rename(signature[i]); } MethodHolder renamedMethod = new MethodHolder(methodName, signature); renamedMethod.getModifiers().addAll(method.getModifiers()); renamedMethod.setLevel(method.getLevel()); renamedMethod.setProgram(method.getProgram()); rename(method.getAnnotations(), renamedMethod.getAnnotations()); rename(renamedMethod.getProgram()); return renamedMethod; }
@Override public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) { for (MethodHolder method : cls.getMethods()) { if (method.hasModifier(ElementModifier.NATIVE) && method.getAnnotations().get(Async.class.getName()) != null && method.getAnnotations().get(GeneratedBy.class.getName()) == null) { ValueType[] signature = new ValueType[method.parameterCount() + 2]; for (int i = 0; i < method.parameterCount(); ++i) { signature[i] = method.parameterType(i); } signature[method.parameterCount()] = ValueType.parse(AsyncCallback.class); signature[method.parameterCount() + 1] = ValueType.VOID; MethodDescriptor asyncDesc = new MethodDescriptor(method.getName(), signature); MethodHolder asyncMethod = cls.getMethod(asyncDesc); if (asyncMethod != null) { if (asyncMethod.hasModifier(ElementModifier.STATIC) != method.hasModifier(ElementModifier.STATIC)) { context.getDiagnostics().error(new CallLocation(method.getReference()), "Methods {{m0}} and {{m1}} must both be either static or non-static", method.getReference(), asyncMethod.getReference()); } } } } } }
public WasmFunction generate(MethodReference methodReference, MethodHolder bodyMethod) { ClassHolder cls = classSource.get(methodReference.getClassName()); MethodHolder method = cls.getMethod(methodReference.getDescriptor()); RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod); WasmFunction function = context.getFunction(names.forMethod(methodReference)); int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0; for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) { VariableNode variable = methodAst.getVariables().get(i); WasmType type = variable.getType() != null ? WasmGeneratorUtil.mapType(variable.getType()) : WasmType.INT32; function.add(new WasmLocal(type, variable.getName())); } WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, binaryWriter, function, firstVariable); methodAst.getBody().acceptVisitor(visitor); if (visitor.result instanceof WasmBlock) { ((WasmBlock) visitor.result).setType(function.getResult()); } function.getBody().add(visitor.result); AnnotationReader exportAnnot = method.getAnnotations().get(Export.class.getName()); if (exportAnnot != null) { function.setExportName(exportAnnot.getValue("name").getString()); } return function; }
AnnotationHolder delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName()); if (delegateAnnot != null) { String methodName = delegateAnnot.getValue("value").getString();