Example #1
0
  public void testMultipleImplementations() {
    StringBuilder buggyCode = new StringBuilder();
    buggyCode.append("import com.google.gwt.core.client.JavaScriptObject;\n");
    buggyCode.append("public class Buggy {\n");
    buggyCode.append("  static interface Squeaks {\n");
    buggyCode.append("    public void squeak();\n");
    buggyCode.append("  }\n");
    buggyCode.append("  static class Squeaker extends JavaScriptObject implements Squeaks {\n");
    buggyCode.append("    public final void squeak() { }\n");
    buggyCode.append("    protected Squeaker() { }\n");
    buggyCode.append("  }\n");
    buggyCode.append("  static class Squeaker2 extends JavaScriptObject implements Squeaks {\n");
    buggyCode.append("    public final void squeak() { }\n");
    buggyCode.append("    protected Squeaker2() { }\n");
    buggyCode.append("  }\n");
    buggyCode.append("}\n");

    shouldGenerateError(
        buggyCode,
        "Line 10: "
            + JSORestrictionsChecker.errAlreadyImplemented(
                "Buggy$Squeaks", "Buggy$Squeaker", "Buggy$Squeaker2"));
  }
      /**
       * A callback after the JDT compiler has compiled a .java file and created a matching
       * CompilationUnitDeclaration. We take this opportunity to create a matching CompilationUnit.
       */
      @Override
      public void process(
          CompilationUnitBuilder builder,
          CompilationUnitDeclaration cud,
          List<CompiledClass> compiledClasses) {
        Event event = SpeedTracerLogger.start(DevModeEventType.CSB_PROCESS);
        try {
          Map<MethodDeclaration, JsniMethod> jsniMethods =
              JsniCollector.collectJsniMethods(
                  cud,
                  builder.getSourceMapPath(),
                  builder.getSource(),
                  JsRootScope.INSTANCE,
                  DummyCorrelationFactory.INSTANCE);

          JSORestrictionsChecker.check(jsoState, cud);

          // JSNI check + collect dependencies.
          final Set<String> jsniDeps = new HashSet<String>();
          Map<String, Binding> jsniRefs = new HashMap<String, Binding>();
          JsniChecker.check(
              cud,
              jsoState,
              jsniMethods,
              jsniRefs,
              new JsniChecker.TypeResolver() {
                @Override
                public ReferenceBinding resolveType(String sourceOrBinaryName) {
                  ReferenceBinding resolveType = compiler.resolveType(sourceOrBinaryName);
                  if (resolveType != null) {
                    jsniDeps.add(String.valueOf(resolveType.qualifiedSourceName()));
                  }
                  return resolveType;
                }
              });

          Map<TypeDeclaration, Binding[]> artificialRescues =
              new HashMap<TypeDeclaration, Binding[]>();
          ArtificialRescueChecker.check(cud, builder.isGenerated(), artificialRescues);
          if (compilerContext.shouldCompileMonolithic()) {
            // GWT drives JDT in a way that allows missing references in the source to be resolved
            // to precompiled bytecode on disk (see INameEnvironment). This is done so that
            // annotations can be supplied in bytecode form only. But since no AST is available for
            // these types it creates the danger that some functional class (not just an annotation)
            // gets filled in but is missing AST. This would cause later compiler stages to fail.
            //
            // Library compilation needs to ignore this check since it is expected behavior for the
            // source being compiled in a library to make references to other types which are only
            // available as bytecode coming out of dependency libraries.
            //
            // But if the referenced bytecode did not come from a dependency library but instead was
            // free floating in the classpath, then there is no guarrantee that AST for it was ever
            // seen and translated to JS anywhere in the dependency tree. This would be a mistake.
            //
            // TODO(stalcup): add a more specific check for library compiles such that binary types
            // can be referenced but only if they are an Annotation or if the binary type comes from
            // a dependency library.
            BinaryTypeReferenceRestrictionsChecker.check(cud);
          }

          MethodArgNamesLookup methodArgs =
              MethodParamCollector.collect(cud, builder.getSourceMapPath());

          Interner<String> interner = StringInterner.get();
          String packageName = interner.intern(Shared.getPackageName(builder.getTypeName()));
          List<String> unresolvedQualified = new ArrayList<String>();
          List<String> unresolvedSimple = new ArrayList<String>();
          for (char[] simpleRef : cud.compilationResult().simpleNameReferences) {
            unresolvedSimple.add(interner.intern(String.valueOf(simpleRef)));
          }
          for (char[][] qualifiedRef : cud.compilationResult().qualifiedReferences) {
            unresolvedQualified.add(interner.intern(CharOperation.toString(qualifiedRef)));
          }
          for (String jsniDep : jsniDeps) {
            unresolvedQualified.add(interner.intern(jsniDep));
          }
          ArrayList<String> apiRefs = compiler.collectApiRefs(cud);
          for (int i = 0; i < apiRefs.size(); ++i) {
            apiRefs.set(i, interner.intern(apiRefs.get(i)));
          }
          Dependencies dependencies =
              new Dependencies(packageName, unresolvedQualified, unresolvedSimple, apiRefs);

          List<JDeclaredType> types = Collections.emptyList();
          if (!cud.compilationResult().hasErrors()) {
            // Make a GWT AST.
            types =
                astBuilder.process(
                    cud, builder.getSourceMapPath(), artificialRescues, jsniMethods, jsniRefs);
          }

          for (CompiledClass cc : compiledClasses) {
            allValidClasses.put(cc.getSourceName(), cc);
          }

          builder
              .setClasses(compiledClasses)
              .setTypes(types)
              .setDependencies(dependencies)
              .setJsniMethods(jsniMethods.values())
              .setMethodArgs(methodArgs)
              .setProblems(cud.compilationResult().getProblems());
          buildQueue.add(builder);
        } finally {
          event.end();
        }
      }