public JavaType convertAsmType(org.objectweb.asm.Type asmType) { return convertAsmType(asmType, 0); }
@Override public void visitInnerClass(String name, @Nullable String outerName, @Nullable String innerName, int flags) { if (isNotSynthetic(flags)) { // TODO what about flags? if (innerName == null) { // anonymous class } else if (outerName == null) { // named class declared within method } else if (className.equals(outerName)) { defineInnerClass(name, flags); } else if (className.equals(name)) { defineOuterClass(outerName, innerName, flags); } else { // FIXME(Godin): for example if loading started from "C1.C2.C3" in case of // class C1 { class C2 { class C3 { } } } // then name="C1$C2", outerName="C1" and innerName="C3" } } }
/** * Invoked when current class classified as inner class. * Owner of inner classes - is some outer class, * which is either already completed, and thus already has this inner class as member, * either will be completed by {@link org.sonar.java.resolve.BytecodeCompleter}, and thus will have this inner class as member (see {@link #defineInnerClass(String, int)}). */ private void defineOuterClass(String outerName, String innerName, int flags) { JavaSymbol.TypeJavaSymbol outerClassSymbol = getClassSymbol(outerName, flags); Preconditions.checkState(outerClassSymbol.completer == null || outerClassSymbol.completer instanceof BytecodeCompleter); classSymbol.name = innerName; classSymbol.owner = outerClassSymbol; }
@Override public void visitInnerClass(String name, @Nullable String outerName, @Nullable String innerName, int flags) { if (!BytecodeCompleter.isSynthetic(flags)) { // TODO what about flags? if (innerName == null) { // anonymous class } else if (outerName == null) { // named class declared within method } else if (className.equals(outerName)) { defineInnerClass(name, flags); } else if (className.equals(name)) { defineOuterClass(outerName, innerName, flags); } else { // FIXME(Godin): for example if loading started from "C1.C2.C3" in case of // class C1 { class C2 { class C3 { } } } // then name="C1$C2", outerName="C1" and innerName="C3" } } }
Preconditions.checkNotNull(name); Preconditions.checkNotNull(desc); if (isNotSynthetic(flags)) { if((flags & Opcodes.ACC_BRIDGE) != 0) { LOG.warn("bridge method {} not marked as synthetic in class {}", name, className); convertAsmTypes(org.objectweb.asm.Type.getArgumentTypes(desc)), convertAsmType(org.objectweb.asm.Type.getReturnType(desc)), getCompletedClassSymbolsType(exceptions), classSymbol );
@Override public MethodVisitor visitMethod(int flags, String name, String desc, @Nullable String signature, @Nullable String[] exceptions) { Preconditions.checkNotNull(name); Preconditions.checkNotNull(desc); if (!BytecodeCompleter.isSynthetic(flags)) { Preconditions.checkState((flags & Opcodes.ACC_BRIDGE) == 0, "bridge method not marked as synthetic in class " + className); // TODO(Godin): according to JVMS 4.7.24 - parameter can be marked as synthetic JavaType.MethodJavaType type = new JavaType.MethodJavaType( convertAsmTypes(org.objectweb.asm.Type.getArgumentTypes(desc)), convertAsmType(org.objectweb.asm.Type.getReturnType(desc)), getCompletedClassSymbolsType(exceptions), classSymbol ); final JavaSymbol.MethodJavaSymbol methodSymbol = new JavaSymbol.MethodJavaSymbol(bytecodeCompleter.filterBytecodeFlags(flags), name, type, classSymbol); classSymbol.members.enter(methodSymbol); if (signature != null) { new SignatureReader(signature).accept(new ReadMethodSignature(methodSymbol)); } methodSymbol.parameters = new OrderedScope(methodSymbol); for (int i = 0; i < type.argTypes.size(); i += 1) { methodSymbol.parameters.enter(new JavaSymbol.VariableJavaSymbol(0, "arg" + i, methodSymbol)); } // checks for annotations on the method and its parameters return new BytecodeMethodVisitor(methodSymbol, this); } return null; }
@Override public void visit(int version, int flags, String name, @Nullable String signature, @Nullable String superName, @Nullable String[] interfaces) { Preconditions.checkState(name.endsWith(classSymbol.name), "Name : '%s' should ends with %s", name, classSymbol.name); Preconditions.checkState(name.endsWith("package-info") || isNotSynthetic(flags), "%s is synthetic", name); className = name; if (signature != null) { SignatureReader signatureReader = new SignatureReader(signature); signatureReader.accept(new TypeParameterDeclaration(classSymbol)); ReadGenericSignature readGenericSignature = new ReadGenericSignature(); signatureReader.accept(readGenericSignature); ((ClassJavaType) classSymbol.type).interfaces = readGenericSignature.interfaces(); } else { if (superName == null) { Preconditions.checkState("java/lang/Object".equals(className), "superName must be null only for java/lang/Object, but not for %s", className); // TODO(Godin): what about interfaces and annotations } else { ((ClassJavaType) classSymbol.type).supertype = getClassSymbol(superName).type; } ((ClassJavaType) classSymbol.type).interfaces = getCompletedClassSymbolsType(interfaces); } //if class has already access flags set (inner class) then do not reset those. //The important access flags are the one defined in the outer class. if ((classSymbol.flags & Flags.ACCESS_FLAGS) != 0) { classSymbol.flags |= Flags.filterAccessBytecodeFlags(flags & ~Flags.ACCESS_FLAGS); } else { classSymbol.flags |= Flags.filterAccessBytecodeFlags(flags); } classSymbol.members = new Scope(classSymbol); }
switch (asmType.getSort()) { case org.objectweb.asm.Type.OBJECT: result = getClassSymbol(asmType.getInternalName(), flags).type; break; case org.objectweb.asm.Type.BYTE: break; case org.objectweb.asm.Type.ARRAY: result = buildArrayType(convertAsmType(asmType.getElementType()), asmType.getDimensions()); break; case org.objectweb.asm.Type.VOID:
@Override public void visit(int version, int flags, String name, @Nullable String signature, @Nullable String superName, @Nullable String[] interfaces) { Preconditions.checkState(name.endsWith(classSymbol.name), "Name : '" + name + "' should ends with " + classSymbol.name); Preconditions.checkState(!BytecodeCompleter.isSynthetic(flags), name + " is synthetic"); className = name; if (signature != null) { SignatureReader signatureReader = new SignatureReader(signature); ReadGenericSignature readGenericSignature = new ReadGenericSignature(); signatureReader.accept(readGenericSignature); ((JavaType.ClassJavaType) classSymbol.type).interfaces = readGenericSignature.interfaces(); } else { if (superName == null) { Preconditions.checkState("java/lang/Object".equals(className), "superName must be null only for java/lang/Object, but not for " + className); // TODO(Godin): what about interfaces and annotations } else { ((JavaType.ClassJavaType) classSymbol.type).supertype = getClassSymbol(superName).type; } ((JavaType.ClassJavaType) classSymbol.type).interfaces = getCompletedClassSymbolsType(interfaces); } //if class has already access flags set (inner class) then do not reset those. //The important access flags are the one defined in the outer class. if ((classSymbol.flags & Flags.ACCESS_FLAGS) != 0) { classSymbol.flags |= bytecodeCompleter.filterBytecodeFlags(flags & ~Flags.ACCESS_FLAGS); } else { classSymbol.flags |= bytecodeCompleter.filterBytecodeFlags(flags); } classSymbol.members = new Scope(classSymbol); }
switch (asmType.getSort()) { case org.objectweb.asm.Type.OBJECT: result = getClassSymbol(asmType.getInternalName()).type; break; case org.objectweb.asm.Type.BYTE: break; case org.objectweb.asm.Type.ARRAY: result = new JavaType.ArrayJavaType(convertAsmType(asmType.getElementType()), symbols.arrayClass); break; case org.objectweb.asm.Type.VOID:
@Override public void complete(JavaSymbol symbol) { LOG.debug("Completing symbol : " + symbol.name); //complete outer class to set flags for inner class properly. if (symbol.owner.isKind(JavaSymbol.TYP)) { symbol.owner.complete(); } String bytecodeName = formFullName(symbol); JavaSymbol.TypeJavaSymbol classSymbol = getClassSymbol(bytecodeName); Preconditions.checkState(classSymbol == symbol); InputStream inputStream = null; ClassReader classReader = null; try { inputStream = inputStreamFor(bytecodeName); if(inputStream != null) { classReader = new ClassReader(inputStream); } } catch (IOException e) { throw Throwables.propagate(e); } finally { Closeables.closeQuietly(inputStream); } if (classReader != null) { classReader.accept( new BytecodeVisitor(this, symbols, (JavaSymbol.TypeJavaSymbol) symbol, parametrizedTypeCache), ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); } }
@Override public FieldVisitor visitField(int flags, String name, String desc, @Nullable String signature, @Nullable Object value) { Preconditions.checkNotNull(name); Preconditions.checkNotNull(desc); if (isNotSynthetic(flags)) { //Flags from asm lib are defined in Opcodes class and map to flags defined in Flags class int filteredFlags = Flags.filterAccessBytecodeFlags(flags); JavaType type = convertAsmType(Type.getType(desc)); JavaSymbol.VariableJavaSymbol symbol = new JavaSymbol.VariableJavaSymbol(filteredFlags, name, type, classSymbol, value); classSymbol.members.enter(symbol); if (signature != null) { ReadType typeReader = new ReadType(); new SignatureReader(signature).accept(typeReader); symbol.type = typeReader.typeRead; } // checks for annotations on the field return new BytecodeFieldVisitor(symbol, this); } return null; }
Preconditions.checkNotNull(name); Preconditions.checkNotNull(desc); if (isNotSynthetic(flags)) { if((flags & Opcodes.ACC_BRIDGE) != 0) { LOG.warn("bridge method {} not marked as synthetic in class {}", name, className); convertAsmTypes(org.objectweb.asm.Type.getArgumentTypes(desc)), convertAsmType(org.objectweb.asm.Type.getReturnType(desc)), getCompletedClassSymbolsType(exceptions), classSymbol );
@Override public MethodVisitor visitMethod(int flags, String name, String desc, @Nullable String signature, @Nullable String[] exceptions) { Preconditions.checkNotNull(name); Preconditions.checkNotNull(desc); if (!BytecodeCompleter.isSynthetic(flags)) { Preconditions.checkState((flags & Opcodes.ACC_BRIDGE) == 0, "bridge method not marked as synthetic in class " + className); // TODO(Godin): according to JVMS 4.7.24 - parameter can be marked as synthetic JavaType.MethodJavaType type = new JavaType.MethodJavaType( convertAsmTypes(org.objectweb.asm.Type.getArgumentTypes(desc)), convertAsmType(org.objectweb.asm.Type.getReturnType(desc)), getCompletedClassSymbolsType(exceptions), classSymbol ); final JavaSymbol.MethodJavaSymbol methodSymbol = new JavaSymbol.MethodJavaSymbol(bytecodeCompleter.filterBytecodeFlags(flags), name, type, classSymbol); classSymbol.members.enter(methodSymbol); if (signature != null) { SignatureReader signatureReader = new SignatureReader(signature); signatureReader.accept(new TypeParameterDeclaration(methodSymbol)); signatureReader.accept(new ReadMethodSignature(methodSymbol)); } methodSymbol.parameters = new Scope(methodSymbol); for (int i = 0; i < type.argTypes.size(); i += 1) { methodSymbol.parameters.enter(new JavaSymbol.VariableJavaSymbol(0, "arg" + i, methodSymbol)); } // checks for annotations on the method and its parameters return new BytecodeMethodVisitor(methodSymbol, this); } return null; }
@Override public void visit(int version, int flags, String name, @Nullable String signature, @Nullable String superName, @Nullable String[] interfaces) { Preconditions.checkState(name.endsWith(classSymbol.name), "Name : '%s' should ends with %s", name, classSymbol.name); Preconditions.checkState(name.endsWith("package-info") || isNotSynthetic(flags), "%s is synthetic", name); className = name; if (signature != null) { SignatureReader signatureReader = new SignatureReader(signature); signatureReader.accept(new TypeParameterDeclaration(classSymbol)); ReadGenericSignature readGenericSignature = new ReadGenericSignature(); signatureReader.accept(readGenericSignature); ((ClassJavaType) classSymbol.type).interfaces = readGenericSignature.interfaces(); } else { if (superName == null) { Preconditions.checkState("java/lang/Object".equals(className), "superName must be null only for java/lang/Object, but not for %s", className); // TODO(Godin): what about interfaces and annotations } else { ((ClassJavaType) classSymbol.type).supertype = getClassSymbol(superName).type; } ((ClassJavaType) classSymbol.type).interfaces = getCompletedClassSymbolsType(interfaces); } //if class has already access flags set (inner class) then do not reset those. //The important access flags are the one defined in the outer class. if ((classSymbol.flags & Flags.ACCESS_FLAGS) != 0) { classSymbol.flags |= Flags.filterAccessBytecodeFlags(flags & ~Flags.ACCESS_FLAGS); } else { classSymbol.flags |= Flags.filterAccessBytecodeFlags(flags); } classSymbol.members = new Scope(classSymbol); }
switch (asmType.getSort()) { case org.objectweb.asm.Type.OBJECT: result = getClassSymbol(asmType.getInternalName(), flags).type; break; case org.objectweb.asm.Type.BYTE: break; case org.objectweb.asm.Type.ARRAY: result = buildArrayType(convertAsmType(asmType.getElementType()), asmType.getDimensions()); break; case org.objectweb.asm.Type.VOID:
@Override public void visitInnerClass(String name, @Nullable String outerName, @Nullable String innerName, int flags) { if (!BytecodeCompleter.isSynthetic(flags)) { // TODO what about flags? if (innerName == null) { // anonymous class } else if (outerName == null) { // named class declared within method } else if (className.equals(outerName)) { defineInnerClass(name, flags); } else if (className.equals(name)) { defineOuterClass(outerName, innerName, flags); } else { // FIXME(Godin): for example if loading started from "C1.C2.C3" in case of // class C1 { class C2 { class C3 { } } } // then name="C1$C2", outerName="C1" and innerName="C3" } } }
@Override public void visit(int version, int flags, String name, @Nullable String signature, @Nullable String superName, @Nullable String[] interfaces) { Preconditions.checkState(name.endsWith(classSymbol.name), "Name : '" + name + "' should ends with " + classSymbol.name); Preconditions.checkState(!BytecodeCompleter.isSynthetic(flags), name + " is synthetic"); className = name; if (signature != null) { SignatureReader signatureReader = new SignatureReader(signature); signatureReader.accept(new TypeParameterDeclaration(classSymbol)); ReadGenericSignature readGenericSignature = new ReadGenericSignature(); signatureReader.accept(readGenericSignature); ((JavaType.ClassJavaType) classSymbol.type).interfaces = readGenericSignature.interfaces(); } else { if (superName == null) { Preconditions.checkState("java/lang/Object".equals(className), "superName must be null only for java/lang/Object, but not for " + className); // TODO(Godin): what about interfaces and annotations } else { ((JavaType.ClassJavaType) classSymbol.type).supertype = getClassSymbol(superName).type; } ((JavaType.ClassJavaType) classSymbol.type).interfaces = getCompletedClassSymbolsType(interfaces); } //if class has already access flags set (inner class) then do not reset those. //The important access flags are the one defined in the outer class. if ((classSymbol.flags & Flags.ACCESS_FLAGS) != 0) { classSymbol.flags |= bytecodeCompleter.filterBytecodeFlags(flags & ~Flags.ACCESS_FLAGS); } else { classSymbol.flags |= bytecodeCompleter.filterBytecodeFlags(flags); } classSymbol.members = new Scope(classSymbol); }
switch (asmType.getSort()) { case org.objectweb.asm.Type.OBJECT: result = getClassSymbol(asmType.getInternalName()).type; break; case org.objectweb.asm.Type.BYTE: break; case org.objectweb.asm.Type.ARRAY: result = new JavaType.ArrayJavaType(convertAsmType(asmType.getElementType()), symbols.arrayClass); break; case org.objectweb.asm.Type.VOID:
@Override public void complete(JavaSymbol symbol) { LOG.debug("Completing symbol : " + symbol.name); //complete outer class to set flags for inner class properly. if (symbol.owner.isKind(JavaSymbol.TYP)) { symbol.owner.complete(); } String bytecodeName = formFullName(symbol); JavaSymbol.TypeJavaSymbol classSymbol = getClassSymbol(bytecodeName); Preconditions.checkState(classSymbol == symbol); InputStream inputStream = null; ClassReader classReader = null; try { inputStream = inputStreamFor(bytecodeName); if(inputStream != null) { classReader = new ClassReader(inputStream); } } catch (IOException e) { throw Throwables.propagate(e); } finally { Closeables.closeQuietly(inputStream); } if (classReader != null) { classReader.accept( new BytecodeVisitor(this, symbols, (JavaSymbol.TypeJavaSymbol) symbol, parametrizedTypeCache), ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); } }