/* * Copyright 2008 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.dev.javac.testing.impl.JavaResourceBase; import com.google.gwt.dev.javac.testing.impl.MockResource; import junit.framework.TestCase; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.Compiler; import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; import org.eclipse.jdt.internal.compiler.ICompilerRequestor; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; /** * Validates certain JDT behaviors that the compilation process may depend on * for correctness. One useful aspect would be that if we upgrade JDT in the * future, this test could help validate our assumptions. */ public class JdtBehaviorTest extends TestCase { /** * Hook-point if we need to modify the compiler behavior. */ private static class CompilerImpl extends Compiler { public CompilerImpl(INameEnvironment environment, ICompilerRequestor requestor) { super(environment, DefaultErrorHandlingPolicies.proceedWithAllProblems(), JdtCompiler.getCompilerOptions(), requestor, new DefaultProblemFactory(Locale.getDefault())); } } /** * Hook point to accept results. */ private class ICompilerRequestorImpl implements ICompilerRequestor { public void acceptResult(CompilationResult result) { if (result.hasErrors()) { StringBuilder sb = new StringBuilder(); for (CategorizedProblem problem : result.getErrors()) { sb.append(problem.toString()); sb.append('\n'); } fail(sb.toString()); } for (ClassFile classFile : result.getClassFiles()) { char[][] classNameArray = classFile.getCompoundName(); char[][] packageArray = CharOperation.subarray(classNameArray, 0, classNameArray.length - 1); char[] packageName = CharOperation.concatWith(packageArray, '.'); char[] className = CharOperation.concatWith(classNameArray, '.'); addPackages(String.valueOf(packageName)); classFiles.put(String.valueOf(className), classFile); } } private void addPackages(String packageName) { while (true) { packages.add(String.valueOf(packageName)); int pos = packageName.lastIndexOf('.'); if (pos > 0) { packageName = packageName.substring(0, pos); } else { packages.add(""); break; } } } } /** * How JDT receives files from the environment. */ private class INameEnvironmentImpl implements INameEnvironment { public void cleanup() { // intentionally blank } public NameEnvironmentAnswer findType(char[] type, char[][] pkg) { return findType(CharOperation.arrayConcat(pkg, type)); } public NameEnvironmentAnswer findType(char[][] compoundTypeName) { final char[] typeChars = CharOperation.concatWith(compoundTypeName, '.'); String typeName = String.valueOf(typeChars); // System.out.println("findType: " + typeName); ClassFile classFile = classFiles.get(typeName); if (classFile != null) { try { byte[] bytes = classFile.getBytes(); char[] loc = classFile.fileName(); ClassFileReader cfr = new ClassFileReader(bytes, loc); return new NameEnvironmentAnswer(cfr, null); } catch (ClassFormatException e) { throw new RuntimeException("Unexpectedly unable to parse class file", e); } } return null; } public boolean isPackage(char[][] parentPkg, char[] pkg) { final char[] pathChars = CharOperation.concatWith(parentPkg, pkg, '.'); String packageName = String.valueOf(pathChars); // System.out.println("isPackage: " + packageName); return packages.contains(packageName); } } private static class ResourceAdapter implements ICompilationUnit { private final MockResource sourceFile; public ResourceAdapter(MockResource resource) { sourceFile = resource; } public char[] getContents() { try { return Shared.readSource(sourceFile).toCharArray(); } catch (IOException ex) { fail("Couldn't read sourceFile: " + sourceFile + " - " + ex); } return null; } public char[] getFileName() { return sourceFile.getLocation().toCharArray(); } public char[] getMainTypeName() { return Shared.getShortName(Shared.getTypeName(sourceFile)).toCharArray(); } public char[][] getPackageName() { return CharOperation.splitOn('.', Shared.getPackageName( Shared.getTypeName(sourceFile)).toCharArray()); } @Override public String toString() { return sourceFile.toString(); } } protected Map<String, ClassFile> classFiles = new HashMap<String, ClassFile>(); /** * New object for each test case. */ protected INameEnvironmentImpl environment = new INameEnvironmentImpl(); protected Set<String> packages = new HashSet<String>(); /** * New object for each test case. */ protected ICompilerRequestorImpl requestor = new ICompilerRequestorImpl(); /** * New object for each test case. */ CompilerImpl compiler = new CompilerImpl(environment, requestor); public void testIncrementalBuild() { List<MockResource> resources = new ArrayList<MockResource>(); Collections.addAll(resources, JavaResourceBase.getStandardResources()); resources.add(JavaResourceBase.FOO); doCompile(resources); // Now incremental build the bar cup. doCompile(Arrays.asList(JavaResourceBase.BAR)); } public void testSingleBuild() { List<MockResource> resources = new ArrayList<MockResource>(); Collections.addAll(resources, JavaResourceBase.getStandardResources()); resources.add(JavaResourceBase.FOO); resources.add(JavaResourceBase.BAR); doCompile(resources); } private void doCompile(List<? extends MockResource> resources) { ICompilationUnit[] icus = new ICompilationUnit[resources.size()]; for (int i = 0; i < icus.length; ++i) { icus[i] = new ResourceAdapter(resources.get(i)); } compiler.compile(icus); } }