예제 #1
0
 private JavaSymbol findMemberType(
     Env env, JavaSymbol.TypeJavaSymbol site, String name, JavaSymbol.TypeJavaSymbol c) {
   JavaSymbol bestSoFar = symbolNotFound;
   for (JavaSymbol symbol : c.members().lookup(name)) {
     if (symbol.kind == JavaSymbol.TYP) {
       return isAccessible(env, site, symbol)
           ? symbol
           : new AccessErrorJavaSymbol(symbol, Symbols.unknownType);
     }
   }
   if (c.getSuperclass() != null) {
     JavaSymbol symbol = findMemberType(env, site, name, c.getSuperclass().symbol);
     if (symbol.kind < bestSoFar.kind) {
       bestSoFar = symbol;
     }
   }
   if (c.getInterfaces() == null) {
     // Invariant to check that interfaces are not set only when we are looking into the symbol we
     // are currently completing.
     // required for generics
     Preconditions.checkState(
         c.completing, "interfaces of a symbol not currently completing are not set.");
     Preconditions.checkState(c == site);
   } else {
     for (JavaType interfaceType : c.getInterfaces()) {
       JavaSymbol symbol = findMemberType(env, site, name, interfaceType.symbol);
       if (symbol.kind < bestSoFar.kind) {
         bestSoFar = symbol;
       }
     }
   }
   return bestSoFar;
 }
예제 #2
0
 /** Is symbol inherited in given class? */
 @VisibleForTesting
 static boolean isInheritedIn(JavaSymbol symbol, JavaSymbol.TypeJavaSymbol clazz) {
   switch (symbol.flags() & Flags.ACCESS_FLAGS) {
     case Flags.PUBLIC:
       return true;
     case Flags.PRIVATE:
       return symbol.owner() == clazz;
     case Flags.PROTECTED:
       // TODO see Javac
       return true;
     case 0:
       // TODO see Javac
       JavaSymbol.PackageJavaSymbol thisPackage = symbol.packge();
       for (JavaSymbol.TypeJavaSymbol sup = clazz;
           sup != null && sup != symbol.owner();
           sup = superclassSymbol(sup)) {
         if (sup.packge() != thisPackage) {
           return false;
         }
       }
       return true;
     default:
       throw new IllegalStateException();
   }
 }
예제 #3
0
 /** Finds field with given name. */
 private Resolution findField(
     Env env, JavaSymbol.TypeJavaSymbol site, String name, JavaSymbol.TypeJavaSymbol c) {
   Resolution bestSoFar = unresolved();
   Resolution resolution = new Resolution();
   for (JavaSymbol symbol : c.members().lookup(name)) {
     if (symbol.kind == JavaSymbol.VAR) {
       if (isAccessible(env, site, symbol)) {
         resolution.symbol = symbol;
         resolution.type = resolveTypeSubstitution(symbol.type, c.type);
         return resolution;
       } else {
         return Resolution.resolution(new AccessErrorJavaSymbol(symbol, Symbols.unknownType));
       }
     }
   }
   if (c.getSuperclass() != null) {
     resolution = findField(env, site, name, c.getSuperclass().symbol);
     if (resolution.symbol.kind < bestSoFar.symbol.kind) {
       resolution.type = resolveTypeSubstitution(resolution.symbol.type, c.getSuperclass());
       bestSoFar = resolution;
     }
   }
   for (JavaType interfaceType : c.getInterfaces()) {
     resolution = findField(env, site, name, interfaceType.symbol);
     if (resolution.symbol.kind < bestSoFar.symbol.kind) {
       bestSoFar = resolution;
     }
   }
   return bestSoFar;
 }
예제 #4
0
 /** Registers builtin types as symbols, so that they can be found as an usual identifiers. */
 private JavaType initType(int tag, String name) {
   JavaSymbol.TypeJavaSymbol symbol =
       new JavaSymbol.TypeJavaSymbol(Flags.PUBLIC, name, rootPackage);
   symbol.members = new Scope(symbol);
   predefClass.members.enter(symbol);
   ((JavaType.ClassJavaType) symbol.type).interfaces = ImmutableList.of();
   symbol.type.tag = tag;
   return symbol.type;
 }
예제 #5
0
 /**
  * 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.flags =
       flags | bytecodeCompleter.filterBytecodeFlags(classSymbol.flags & ~Flags.ACCESS_FLAGS);
   classSymbol.owner = outerClassSymbol;
 }
예제 #6
0
 /**
  * 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);
 }
예제 #7
0
 /**
  * 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);
   }
 }
예제 #8
0
 @Override
 public void visitFormalTypeParameter(String name) {
   JavaSymbol.TypeVariableJavaSymbol typeVariableSymbol =
       new JavaSymbol.TypeVariableJavaSymbol(name, symbol);
   ((TypeVariableJavaType) typeVariableSymbol.type).bounds = Lists.newArrayList();
   if (symbol.isTypeSymbol()) {
     JavaSymbol.TypeJavaSymbol typeJavaSymbol = (JavaSymbol.TypeJavaSymbol) symbol;
     typeJavaSymbol.typeParameters.enter(typeVariableSymbol);
     typeJavaSymbol.addTypeParameter((TypeVariableJavaType) typeVariableSymbol.type);
   } else if (symbol.isMethodSymbol()) {
     JavaSymbol.MethodJavaSymbol methodSymbol = (JavaSymbol.MethodJavaSymbol) symbol;
     methodSymbol.typeParameters.enter(typeVariableSymbol);
     methodSymbol.addTypeParameter((TypeVariableJavaType) typeVariableSymbol.type);
   }
 }
예제 #9
0
 @Override
 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
   JavaType annotationType = convertAsmType(org.objectweb.asm.Type.getType(desc));
   AnnotationInstanceResolve annotationInstance =
       new AnnotationInstanceResolve(annotationType.getSymbol());
   classSymbol.metadata().addAnnotation(annotationInstance);
   return new BytecodeAnnotationVisitor(annotationInstance, this);
 }
예제 #10
0
 @Override
 public void visitEnd() {
   if (!typeArguments.isEmpty()) {
     JavaSymbol.TypeJavaSymbol readSymbol = typeRead.symbol;
     readSymbol.complete();
     // Mismatch between type variable and type arguments means we are lacking some pieces of
     // bytecode to resolve substitution properly.
     if (typeArguments.size() == readSymbol.typeVariableTypes.size()) {
       TypeSubstitution substitution = new TypeSubstitution();
       int i = 0;
       for (JavaType typeArgument : typeArguments) {
         substitution.add(readSymbol.typeVariableTypes.get(i), typeArgument);
         i++;
       }
       typeRead = parametrizedTypeCache.getParametrizedTypeType(readSymbol, substitution);
     }
   }
 }
예제 #11
0
 @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);
     ((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 {
       ((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 |= bytecodeCompleter.filterBytecodeFlags(flags & ~Flags.ACCESS_FLAGS);
   } else {
     classSymbol.flags |= bytecodeCompleter.filterBytecodeFlags(flags);
   }
   classSymbol.members = new Scope(classSymbol);
 }
예제 #12
0
 /** Is class accessible in given environment? */
 @VisibleForTesting
 static boolean isAccessible(Env env, JavaSymbol.TypeJavaSymbol c) {
   final boolean result;
   switch (c.flags() & Flags.ACCESS_FLAGS) {
     case Flags.PRIVATE:
       result = sameOutermostClass(env.enclosingClass, c.owner());
       break;
     case 0:
       result = env.packge == c.packge();
       break;
     case Flags.PUBLIC:
       result = true;
       break;
     case Flags.PROTECTED:
       result = env.packge == c.packge() || isInnerSubClass(env.enclosingClass, c.owner());
       break;
     default:
       throw new IllegalStateException();
   }
   // TODO check accessibility of enclosing type: isAccessible(env, c.type.getEnclosingType())
   return result;
 }
예제 #13
0
  static {
    rootPackage = new JavaSymbol.PackageJavaSymbol("", null);
    unknownSymbol =
        new JavaSymbol.TypeJavaSymbol(Flags.PUBLIC, "!unknownSymbol!", rootPackage) {
          @Override
          public void addUsage(IdentifierTree tree) {
            // noop
          }

          @Override
          public boolean isTypeSymbol() {
            return false;
          }

          @Override
          public boolean isUnknown() {
            return true;
          }
        };
    unknownSymbol.members =
        new Scope(unknownSymbol) {
          @Override
          public void enter(JavaSymbol symbol) {
            // noop
          }
        };
    unknownType =
        new JavaType.ClassJavaType(unknownSymbol) {
          @Override
          public String toString() {
            return "!unknown!";
          }
        };
    unknownType.tag = JavaType.UNKNOWN;
    unknownType.supertype = null;
    unknownType.interfaces = ImmutableList.of();
    unknownSymbol.type = unknownType;
  }
예제 #14
0
 /** Is given class a subclass of given base class? */
 @VisibleForTesting
 static boolean isSubClass(JavaSymbol.TypeJavaSymbol c, JavaSymbol base) {
   // TODO get rid of null check
   if (c == null) {
     return false;
   }
   // TODO see Javac
   if (c == base) {
     // same class
     return true;
   } else if ((base.flags() & Flags.INTERFACE) != 0) {
     // check if class implements base
     for (JavaType interfaceType : c.getInterfaces()) {
       if (isSubClass(interfaceType.symbol, base)) {
         return true;
       }
     }
     // check if superclass implements base
     return isSubClass(superclassSymbol(c), base);
   } else {
     // check if class extends base or its superclass extends base
     return isSubClass(superclassSymbol(c), base);
   }
 }
예제 #15
0
 @Nullable
 private static JavaSymbol.TypeJavaSymbol superclassSymbol(JavaSymbol.TypeJavaSymbol c) {
   JavaType supertype = c.getSuperclass();
   return supertype == null ? null : supertype.symbol;
 }
예제 #16
0
  public Symbols(BytecodeCompleter bytecodeCompleter) {
    defaultPackage = new JavaSymbol.PackageJavaSymbol("", rootPackage);

    predefClass = new JavaSymbol.TypeJavaSymbol(Flags.PUBLIC, "", rootPackage);
    predefClass.members = new Scope(predefClass);
    ((JavaType.ClassJavaType) predefClass.type).interfaces = ImmutableList.of();

    // TODO should have type "noType":
    noSymbol = new JavaSymbol.TypeJavaSymbol(0, "", rootPackage);

    methodClass = new JavaSymbol.TypeJavaSymbol(Flags.PUBLIC, "", noSymbol);

    // builtin types
    byteType = initType(JavaType.BYTE, "byte");
    charType = initType(JavaType.CHAR, "char");
    shortType = initType(JavaType.SHORT, "short");
    intType = initType(JavaType.INT, "int");
    longType = initType(JavaType.LONG, "long");
    floatType = initType(JavaType.FLOAT, "float");
    doubleType = initType(JavaType.DOUBLE, "double");
    booleanType = initType(JavaType.BOOLEAN, "boolean");
    nullType = initType(JavaType.BOT, "<nulltype>");
    voidType = initType(JavaType.VOID, "void");

    bytecodeCompleter.init(this);

    // predefined types for java lang
    JavaSymbol.PackageJavaSymbol javalang = bytecodeCompleter.enterPackage("java.lang");
    // define a star import scope to let resolve types to java.lang when needed.
    javalang.members = new Scope.StarImportScope(javalang, bytecodeCompleter);
    javalang.members.enter(javalang);

    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;

    // Associate boxed types
    boxedTypes = HashBiMap.create();
    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);

    for (Entry<JavaType, JavaType> entry : boxedTypes.entrySet()) {
      entry.getKey().primitiveWrapperType = entry.getValue();
      entry.getValue().primitiveType = entry.getKey();
    }

    // TODO comment me
    arrayClass = new JavaSymbol.TypeJavaSymbol(Flags.PUBLIC, "Array", noSymbol);
    JavaType.ClassJavaType arrayClassType = (JavaType.ClassJavaType) arrayClass.type;
    arrayClassType.supertype = objectType;
    arrayClassType.interfaces = ImmutableList.of(cloneableType, serializableType);
    arrayClass.members = new Scope(arrayClass);
    arrayClass
        .members()
        .enter(
            new JavaSymbol.VariableJavaSymbol(
                Flags.PUBLIC | Flags.FINAL, "length", intType, arrayClass));
    // TODO arrayClass implements clone() method

    enterOperators();
  }
예제 #17
0
 /** Is given class a subclass of given base class, or an inner class of a subclass? */
 private static boolean isInnerSubClass(JavaSymbol.TypeJavaSymbol c, JavaSymbol base) {
   while (c != null && isSubClass(c, base)) {
     c = c.owner().enclosingClass();
   }
   return c != null;
 }