| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.dev.javac; |
| |
| import com.google.gwt.core.ext.typeinfo.JClassType; |
| import com.google.gwt.core.ext.typeinfo.TypeOracleException; |
| import com.google.gwt.thirdparty.guava.common.base.Joiner; |
| |
| /** |
| * Tests for {@link TypeOracleUpdater} when provided sources. |
| */ |
| public class CompilationUnitTypeOracleUpdaterFromSourceTest extends TypeOracleUpdaterTestBase { |
| |
| protected CheckedJavaResource CU_HasSyntaxErrors = new CheckedJavaResource( |
| "test", "HasSyntaxErrors", "NoSyntaxErrors") { |
| @Override |
| public void check(JClassType classInfo) { |
| fail("This class should have been removed"); |
| } |
| |
| @Override |
| public String getSource() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("package test;\n"); |
| sb.append("class NoSyntaxErrors { }\n"); |
| sb.append("public class HasSyntaxErrors { a syntax error }\n"); |
| return sb.toString(); |
| } |
| }; |
| |
| protected CheckedJavaResource CU_HasUnresolvedSymbols = new CheckedJavaResource( |
| "test", "Invalid", "Valid") { |
| @Override |
| public void check(JClassType classInfo) { |
| fail("Both classes should have been removed"); |
| } |
| |
| @Override |
| public String getSource() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("package " + getPackageName() + ";\n"); |
| sb.append("public class Invalid extends NoSuchClass { }\n"); |
| sb.append("class Valid extends Object { }\n"); |
| return sb.toString(); |
| } |
| }; |
| |
| protected CheckedJavaResource CU_RefsInfectedCompilationUnit = new CheckedJavaResource( |
| "test", "RefsInfectedCompilationUnit") { |
| @Override |
| public void check(JClassType classInfo) { |
| fail("This class should should have been removed because it refers to a class in another compilation unit that had problems"); |
| } |
| |
| @Override |
| public String getSource() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("package test;\n"); |
| sb.append("public class RefsInfectedCompilationUnit extends Valid { }\n"); |
| return sb.toString(); |
| } |
| }; |
| |
| /** |
| * Tests that refreshing with a unit that has errors does not cause new units |
| * that reference unchanged units to be removed. The strategy is to add some |
| * good units that reference each other and build a {@link TypeOracle}. Then |
| * we add some new units that have errors as well as some units that reference |
| * old units which did not have errors. This ensures that the correct units |
| * are pruned from the type oracle in the case where we encounter units with |
| * errors. |
| */ |
| public void testRefreshWithErrors() throws TypeOracleException { |
| // Add Object |
| StringBuilder sb = new StringBuilder(); |
| sb.append("package java.lang;"); |
| sb.append("public class Object { }"); |
| addResource("java.lang.Object", sb); |
| |
| // Add UnmodifiedClass that will never change. |
| sb = new StringBuilder(); |
| sb.append("package test.refresh.with.errors;"); |
| sb.append("public class UnmodifiedClass { }"); |
| addResource("test.refresh.with.errors.UnmodifiedClass", sb); |
| |
| // Add GoodClass that references a class that will go bad. |
| sb = new StringBuilder(); |
| sb.append("package test.refresh.with.errors;\n"); |
| sb.append("public class GoodClass {\n"); |
| sb.append(" ClassThatWillGoBad ctwgb;\n"); |
| sb.append("}\n"); |
| addResource("test.refresh.with.errors.GoodClass", sb); |
| |
| // Add ClassThatWillGoBad that goes bad on the next refresh. |
| MutableJavaResource unitThatWillGoBad = new MutableJavaResource( |
| "test.refresh.with.errors", |
| "test.refresh.with.errors.ClassThatWillGoBad") { |
| |
| private String source = "package test.refresh.with.errors;\n" |
| + "public class ClassThatWillGoBad { }\n"; |
| |
| @Override |
| public String getSource() { |
| return source; |
| } |
| |
| @Override |
| public void touch() { |
| super.touch(); |
| source = "This will cause a syntax error."; |
| } |
| }; |
| |
| resources.add(unitThatWillGoBad); |
| |
| buildTypeOracle(); |
| |
| assertNotNull(typeOracle.findType("test.refresh.with.errors.UnmodifiedClass")); |
| assertNotNull(typeOracle.findType("test.refresh.with.errors.GoodClass")); |
| assertNotNull(typeOracle.findType("test.refresh.with.errors.ClassThatWillGoBad")); |
| |
| // Add AnotherGoodClass that references a |
| // class that was not recompiled. |
| sb = new StringBuilder(); |
| sb.append("package test.refresh.with.errors;\n"); |
| sb.append("public class AnotherGoodClass {\n"); |
| sb.append(" UnmodifiedClass uc; // This will cause the runaway pruning.\n"); |
| sb.append("}\n"); |
| addResource("test.refresh.with.errors.AnotherGoodClass", sb); |
| |
| // Add BadClass that has errors and originally |
| // forced issue 2238. |
| sb = new StringBuilder(); |
| sb.append("package test.refresh.with.errors;\n"); |
| sb.append("public class BadClass {\n"); |
| sb.append(" This will trigger a syntax error.\n"); |
| sb.append("}\n"); |
| addResource("test.refresh.with.errors.BadClass", sb); |
| |
| // Now this cup should cause errors. |
| unitThatWillGoBad.touch(); |
| |
| buildTypeOracle(); |
| |
| assertNotNull(typeOracle.findType("test.refresh.with.errors.UnmodifiedClass")); |
| assertNotNull(typeOracle.findType("test.refresh.with.errors.AnotherGoodClass")); |
| assertNull(typeOracle.findType("test.refresh.with.errors.BadClass")); |
| assertNull(typeOracle.findType("test.refresh.with.errors.ClassThatWillGoBad")); |
| assertNull(typeOracle.findType("test.refresh.with.errors.GoodClass")); |
| } |
| |
| public void testSyntaxErrors() throws TypeOracleException { |
| resources.add(CU_Object); |
| resources.add(CU_HasSyntaxErrors); |
| buildTypeOracle(); |
| |
| assertNull(typeOracle.findType(CU_HasSyntaxErrors.getTypeName())); |
| assertNotNull(typeOracle.findType(CU_Object.getTypeName())); |
| assertEquals(1, typeOracle.getTypes().length); |
| } |
| |
| public void testUnresolvedSymbols() throws TypeOracleException { |
| resources.add(CU_Object); |
| resources.add(CU_HasUnresolvedSymbols); |
| resources.add(CU_RefsInfectedCompilationUnit); |
| buildTypeOracle(); |
| |
| assertNull(typeOracle.findType(CU_HasUnresolvedSymbols.getTypeName())); |
| assertNull(typeOracle.findType(CU_RefsInfectedCompilationUnit.getTypeName())); |
| assertNotNull(typeOracle.findType(CU_Object.getTypeName())); |
| assertEquals(1, typeOracle.getTypes().length); |
| } |
| |
| public void testJava8InterfaceExclusions() throws TypeOracleException { |
| String java8Interface = Joiner.on("\n").join( |
| "package test.java8;", |
| "interface Java8Interface {", |
| " Object field = new Object();", |
| " final int constant = 1;", |
| " void m();", |
| " default void n() {};", |
| " static void o() {};", |
| "}"); |
| addResource("test.java8.Java8Interface", java8Interface); |
| resources.add(CU_Object); |
| buildTypeOracle(); |
| |
| assertEquals(1, typeOracle.findType("test.java8.Java8Interface").getMethods().length); |
| assertEquals("m", typeOracle.findType("test.java8.Java8Interface").getMethods()[0].getName()); |
| assertNotNull(typeOracle.findType(CU_Object.getTypeName())); |
| assertEquals(2, typeOracle.getTypes().length); |
| } |
| |
| @Override |
| protected void buildTypeOracle() throws TypeOracleException { |
| typeOracle = TypeOracleTestingUtils.buildTypeOracle(createTreeLogger(), |
| resources); |
| checkTypes(typeOracle.getTypes()); |
| } |
| } |