/** * @param kind subset of {@link JavaSymbol#TYP}, {@link JavaSymbol#PCK} */ public JavaSymbol findIdentInPackage(JavaSymbol site, String name, int kind) { String fullname = bytecodeCompleter.formFullName(name, site); JavaSymbol bestSoFar = symbolNotFound; //Try to find a type matching the name. if ((kind & JavaSymbol.TYP) != 0) { JavaSymbol sym = bytecodeCompleter.loadClass(fullname); if (sym.kind < bestSoFar.kind) { bestSoFar = sym; } } //We did not find the class so identifier must be a package. if ((kind & JavaSymbol.PCK) != 0 && bestSoFar.kind >= symbolNotFound.kind) { bestSoFar = bytecodeCompleter.enterPackage(fullname); } return bestSoFar; }
JavaSymbol.TypeJavaSymbol getClassSymbol(String bytecodeName, int flags) { return getClassSymbol(null, bytecodeName, flags); } public JavaSymbol.TypeJavaSymbol getClassSymbol(@Nullable JavaSymbol.TypeJavaSymbol classSymbolOwner, String bytecodeName, int flags) {
public JavaSymbol.TypeJavaSymbol registerClass(JavaSymbol.TypeJavaSymbol classSymbol) { return bytecodeCompleter.registerClass(classSymbol); }
@Override public List<JavaSymbol> lookup(String name) { List<JavaSymbol> symbolsList = Lists.newArrayList(); for (JavaSymbol site : symbols.values()) { JavaSymbol symbol = bytecodeCompleter.loadClass(bytecodeCompleter.formFullName(name, site)); if (symbol.kind < JavaSymbol.ERRONEOUS) { symbolsList.add(symbol); } } return symbolsList; } }
voidType = initType(JavaType.VOID, "void"); bytecodeCompleter.init(this); JavaSymbol.PackageJavaSymbol javalang = bytecodeCompleter.enterPackage("java.lang"); objectType = bytecodeCompleter.loadClass("java.lang.Object").type; classType = bytecodeCompleter.loadClass("java.lang.Class").type; stringType = bytecodeCompleter.loadClass("java.lang.String").type; cloneableType = bytecodeCompleter.loadClass("java.lang.Cloneable").type; serializableType = bytecodeCompleter.loadClass("java.io.Serializable").type; annotationType = bytecodeCompleter.loadClass("java.lang.annotation.Annotation").type; enumType = bytecodeCompleter.loadClass("java.lang.Enum").type; boxedTypes.put(byteType, bytecodeCompleter.loadClass("java.lang.Byte").type); boxedTypes.put(charType, bytecodeCompleter.loadClass("java.lang.Character").type); boxedTypes.put(shortType, bytecodeCompleter.loadClass("java.lang.Short").type); boxedTypes.put(intType, bytecodeCompleter.loadClass("java.lang.Integer").type); boxedTypes.put(longType, bytecodeCompleter.loadClass("java.lang.Long").type); boxedTypes.put(floatType, bytecodeCompleter.loadClass("java.lang.Float").type); boxedTypes.put(doubleType, bytecodeCompleter.loadClass("java.lang.Double").type); boxedTypes.put(booleanType, bytecodeCompleter.loadClass("java.lang.Boolean").type); bytecodeCompleter.registerClass(syntheticAnnotation); enterOperators();
JavaSymbol.TypeJavaSymbol getClassSymbol(String bytecodeName, int flags) { String flatName = Convert.flatName(bytecodeName); JavaSymbol.TypeJavaSymbol symbol = classes.get(flatName); if (symbol == null) { String shortName = Convert.shortName(flatName); String packageName = Convert.packagePart(flatName); String enclosingClassName = Convert.enclosingClassName(shortName); if (StringUtils.isNotEmpty(enclosingClassName)) { //handle innerClasses symbol = new JavaSymbol.TypeJavaSymbol(filterBytecodeFlags(flags), Convert.innerClassName(shortName), getClassSymbol(Convert.fullName(packageName, enclosingClassName))); } else { symbol = new JavaSymbol.TypeJavaSymbol(filterBytecodeFlags(flags), shortName, enterPackage(packageName)); } symbol.members = new Scope(symbol); symbol.typeParameters = new Scope(symbol); // (Godin): IOException will happen without this condition in case of missing class: if (getClassLoader().getResource(Convert.bytecodeName(flatName) + ".class") != null) { symbol.completer = this; } else { LOG.error("Class not found: " + bytecodeName); ((JavaType.ClassJavaType) symbol.type).interfaces = ImmutableList.of(); ((JavaType.ClassJavaType) symbol.type).supertype = Symbols.unknownType; } classes.put(flatName, symbol); } return symbol; }
@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); } }
voidType = initType(JavaType.VOID, "void"); bytecodeCompleter.init(this); JavaSymbol.PackageJavaSymbol javalang = bytecodeCompleter.enterPackage("java.lang"); objectType = bytecodeCompleter.loadClass("java.lang.Object").type; classType = bytecodeCompleter.loadClass("java.lang.Class").type; stringType = bytecodeCompleter.loadClass("java.lang.String").type; cloneableType = bytecodeCompleter.loadClass("java.lang.Cloneable").type; serializableType = bytecodeCompleter.loadClass("java.io.Serializable").type; annotationType = bytecodeCompleter.loadClass("java.lang.annotation.Annotation").type; enumType = bytecodeCompleter.loadClass("java.lang.Enum").type; boxedTypes.put(byteType, bytecodeCompleter.loadClass("java.lang.Byte").type); boxedTypes.put(charType, bytecodeCompleter.loadClass("java.lang.Character").type); boxedTypes.put(shortType, bytecodeCompleter.loadClass("java.lang.Short").type); boxedTypes.put(intType, bytecodeCompleter.loadClass("java.lang.Integer").type); boxedTypes.put(longType, bytecodeCompleter.loadClass("java.lang.Long").type); boxedTypes.put(floatType, bytecodeCompleter.loadClass("java.lang.Float").type); boxedTypes.put(doubleType, bytecodeCompleter.loadClass("java.lang.Double").type); boxedTypes.put(booleanType, bytecodeCompleter.loadClass("java.lang.Boolean").type);
@Nullable private JavaSymbol.TypeJavaSymbol getEnclosingClass(String shortName, String packageName) { JavaSymbol.TypeJavaSymbol owner = null; String enclosingClassName = Convert.enclosingClassName(shortName); if (StringUtils.isNotEmpty(enclosingClassName)) { enclosingClassName = Convert.fullName(packageName, enclosingClassName); InputStream inputStream = null; try { inputStream = inputStreamFor(enclosingClassName); while (inputStream == null && enclosingClassName.endsWith("$")) { enclosingClassName = enclosingClassName.substring(0, enclosingClassName.length() - 1); inputStream = inputStreamFor(enclosingClassName); } } finally { Closeables.closeQuietly(inputStream); } owner = getClassSymbol(enclosingClassName); } return owner; }
@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); }
public String formFullName(JavaSymbol symbol) { return formFullName(symbol.name, symbol.owner); }
@Override public void complete(JavaSymbol symbol) { String bytecodeName = formFullName(symbol); if(symbol.isPackageSymbol()) { bytecodeName = bytecodeName + ".package-info"; } JavaSymbol.TypeJavaSymbol classSymbol = getClassSymbol(bytecodeName); if(symbol.isPackageSymbol()) { ((JavaSymbol.PackageJavaSymbol) symbol).packageInfo = classSymbol; } Preconditions.checkState(symbol.isPackageSymbol() || classSymbol == symbol); byte[] bytes = classLoader.getBytesForClass(bytecodeName); if (bytes != null) { ClassReader classReader = new ClassReader(bytes); classReader.accept( new BytecodeVisitor(this, symbols, classSymbol, parametrizedTypeCache), ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); } }
/** * If at this point there is no owner of current class, then this is a top-level class, * because outer classes always will be completed before inner classes - see {@link #defineOuterClass(String, String, int)}. * Owner of top-level classes - is a package. */ @Override public void visitEnd() { if (classSymbol.owner == null) { String flatName = className.replace('/', '.'); classSymbol.name = flatName.substring(flatName.lastIndexOf('.') + 1); classSymbol.owner = bytecodeCompleter.enterPackage(flatName); JavaSymbol.PackageJavaSymbol owner = (JavaSymbol.PackageJavaSymbol) classSymbol.owner; if (owner.members == null) { // package was without classes so far owner.members = new Scope(owner); } owner.members.enter(classSymbol); } }
JavaSymbol.TypeJavaSymbol owner = classSymbolOwner; if(owner == null) { owner = getEnclosingClass(shortName, packageName); symbol = new JavaSymbol.TypeJavaSymbol(classFlags, name, owner, bytecodeName); } else { symbol = new JavaSymbol.TypeJavaSymbol(classFlags, shortName, enterPackage(packageName)); } else { if (!bytecodeName.endsWith("package-info") && isNotAnnotation(flags)) { classesNotFound.add(bytecodeName);
public static SemanticModel createFor(CompilationUnitTree tree, SquidClassLoader classLoader) { ParametrizedTypeCache parametrizedTypeCache = new ParametrizedTypeCache(); BytecodeCompleter bytecodeCompleter = new BytecodeCompleter(classLoader, parametrizedTypeCache); Symbols symbols = new Symbols(bytecodeCompleter); SemanticModel semanticModel = new SemanticModel(bytecodeCompleter); try { Resolve resolve = new Resolve(symbols, bytecodeCompleter, parametrizedTypeCache); TypeAndReferenceSolver typeAndReferenceSolver = new TypeAndReferenceSolver(semanticModel, symbols, resolve, parametrizedTypeCache); new FirstPass(semanticModel, symbols, resolve, parametrizedTypeCache, typeAndReferenceSolver).visitCompilationUnit(tree); typeAndReferenceSolver.visitCompilationUnit(tree); new LabelsVisitor(semanticModel).visitCompilationUnit(tree); } finally { handleMissingTypes(tree); } return semanticModel; }
public Type getClassType(String fullyQualifiedName) { return bytecodeCompleter.loadClass(fullyQualifiedName).type(); }
/** * Invoked when current class classified as outer class of some inner class. * Adds inner class as member. */ private void defineInnerClass(String bytecodeName, int flags) { JavaSymbol.TypeJavaSymbol innerClass = getClassSymbol(classSymbol, bytecodeName, flags); innerClass.flags |= bytecodeCompleter.filterBytecodeFlags(flags); Preconditions.checkState(innerClass.owner == classSymbol, "Innerclass: " + innerClass.owner.getName() + " and classSymbol: " + classSymbol.getName() + " are not the same."); classSymbol.members.enter(innerClass); }
public void done(){ bytecodeCompleter.done(); }
@Override public List<JavaSymbol> lookup(String name) { List<JavaSymbol> symbolsList = Lists.newArrayList(); for (JavaSymbol site : symbols.values()) { JavaSymbol symbol = bytecodeCompleter.loadClass(bytecodeCompleter.formFullName(name, site)); if (symbol.kind < JavaSymbol.ERRONEOUS) { symbolsList.add(symbol); } } return symbolsList; } }
voidType = initType(JavaType.VOID, "void"); bytecodeCompleter.init(this); JavaSymbol.PackageJavaSymbol javalang = bytecodeCompleter.enterPackage("java.lang"); objectType = bytecodeCompleter.loadClass("java.lang.Object").type; classType = bytecodeCompleter.loadClass("java.lang.Class").type; stringType = bytecodeCompleter.loadClass("java.lang.String").type; cloneableType = bytecodeCompleter.loadClass("java.lang.Cloneable").type; serializableType = bytecodeCompleter.loadClass("java.io.Serializable").type; annotationType = bytecodeCompleter.loadClass("java.lang.annotation.Annotation").type; enumType = bytecodeCompleter.loadClass("java.lang.Enum").type; boxedTypes.put(byteType, bytecodeCompleter.loadClass("java.lang.Byte").type); boxedTypes.put(charType, bytecodeCompleter.loadClass("java.lang.Character").type); boxedTypes.put(shortType, bytecodeCompleter.loadClass("java.lang.Short").type); boxedTypes.put(intType, bytecodeCompleter.loadClass("java.lang.Integer").type); boxedTypes.put(longType, bytecodeCompleter.loadClass("java.lang.Long").type); boxedTypes.put(floatType, bytecodeCompleter.loadClass("java.lang.Float").type); boxedTypes.put(doubleType, bytecodeCompleter.loadClass("java.lang.Double").type); boxedTypes.put(booleanType, bytecodeCompleter.loadClass("java.lang.Boolean").type); bytecodeCompleter.registerClass(syntheticAnnotation); enterOperators();