/** Recursively creates enclosing types first. */
 private void createCompiledClass(ClassFile classFile, Map<ClassFile, CompiledClass> results) {
   if (results.containsKey(classFile)) {
     // Already created.
     return;
   }
   CompiledClass enclosingClass = null;
   if (classFile.enclosingClassFile != null) {
     ClassFile enclosingClassFile = classFile.enclosingClassFile;
     createCompiledClass(enclosingClassFile, results);
     enclosingClass = results.get(enclosingClassFile);
     assert enclosingClass != null;
   }
   String internalName = CharOperation.charToString(classFile.fileName());
   CompiledClass result =
       new CompiledClass(
           classFile.getBytes(), enclosingClass, isLocalType(classFile), internalName);
   results.put(classFile, result);
 }
Exemple #2
0
    private void resolveClassReference(JsniRef jsniRef) {
      // Precedence rules as of JLS 6.4.1.
      // 1. Enclosing type.
      // 2. Visible type in same compilation unit.
      // 3. Named import.
      // 4. Same package.
      // 5. Import on demand.

      String originalName = jsniRef.className();
      String importedClassName = originalName;
      if (importedClassName.contains(".")) {
        // Only retain up the first dot to support innerclasses. E.g. import c.g.A and reference
        // @A.I::f.
        importedClassName = importedClassName.substring(0, importedClassName.indexOf("."));
      }

      // 1 & 2. Check to see if this name refers to the enclosing class or is directly accessible
      // from it.
      ReferenceBinding declaringClass = method.binding.declaringClass;
      while (declaringClass != null) {
        String declaringClassName = JdtUtil.getSourceName(declaringClass);
        if (declaringClassName.equals(importedClassName)
            || declaringClassName.endsWith("." + importedClassName)) {
          // Referring to declaring class name using unqualified name.
          jsniRef.setResolvedClassName(
              declaringClassName + originalName.substring(importedClassName.length()));
          return;
        }
        String fullClassName =
            JdtUtil.getBinaryName(declaringClass) + "$" + originalName.replace('.', '$');
        if (typeResolver.resolveType(fullClassName) != null) {
          jsniRef.setResolvedClassName(JdtUtil.getSourceName(declaringClass) + "." + originalName);
          return;
        }
        declaringClass = declaringClass.enclosingTypeAt(1);
      }

      // 3. Check to see if this name is one of the named imports.
      for (ImportReference importReference : cudImports) {
        String nameFromImport = JdtUtil.asDottedString(importReference.getImportName());
        if (!importReference.isStatic()
            && importReference.trailingStarPosition == 0
            && nameFromImport.endsWith("." + importedClassName)) {
          jsniRef.setResolvedClassName(
              nameFromImport + originalName.substring(importedClassName.length()));
          return;
        }
      }

      // 4. Check to see if this name is resolvable from the current package.
      String currentPackageBinaryClassName =
          JdtUtil.getBinaryName(
              CharOperation.charToString(method.binding.declaringClass.qualifiedPackageName()),
              originalName);

      if (typeResolver.resolveType(currentPackageBinaryClassName) != null) {
        jsniRef.setResolvedClassName(
            JdtUtil.getSourceName(
                CharOperation.charToString(method.binding.declaringClass.qualifiedPackageName()),
                originalName));
        return;
      }

      // 5. Check to see if this name is resolvable as an import on demand.
      List<String> importPackages = Lists.newArrayList("java.lang");
      for (ImportReference importReference : cudImports) {
        if (importReference.isStatic() || importReference.trailingStarPosition == 0) {
          continue;
        }
        importPackages.add(JdtUtil.asDottedString(importReference.getImportName()));
      }
      for (String importPackage : importPackages) {
        String fullClassName = importPackage + "." + originalName.replace('.', '$');
        if (typeResolver.resolveType(fullClassName) != null) {
          jsniRef.setResolvedClassName(importPackage + "." + originalName);
          return;
        }
      }

      // Otherwise leave it as it is.
      // TODO(rluble): Maybe we should leave it null here.
      jsniRef.setResolvedClassName(jsniRef.className());
    }