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(); } }