1 16 package com.google.gwt.dev.jdt; 17 18 import com.google.gwt.core.ext.TreeLogger; 19 import com.google.gwt.core.ext.UnableToCompleteException; 20 import com.google.gwt.core.ext.typeinfo.CompilationUnitProvider; 21 import com.google.gwt.dev.util.Empty; 22 import com.google.gwt.dev.util.log.ThreadLocalTreeLoggerProxy; 23 24 import org.eclipse.jdt.core.compiler.CharOperation; 25 import org.eclipse.jdt.core.compiler.IProblem; 26 import org.eclipse.jdt.internal.compiler.CompilationResult; 27 import org.eclipse.jdt.internal.compiler.Compiler; 28 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; 29 import org.eclipse.jdt.internal.compiler.ICompilerRequestor; 30 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; 31 import org.eclipse.jdt.internal.compiler.IProblemFactory; 32 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; 33 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; 34 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; 35 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; 36 import org.eclipse.jdt.internal.compiler.env.INameEnvironment; 37 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; 38 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 39 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; 40 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; 41 42 import java.util.HashMap ; 43 import java.util.HashSet ; 44 import java.util.Iterator ; 45 import java.util.Locale ; 46 import java.util.Map ; 47 import java.util.Set ; 48 49 53 public abstract class AbstractCompiler { 54 55 61 private class CompilerImpl extends Compiler { 62 63 public HashSet resolved = new HashSet (); 64 65 private Set cuds; 66 67 public CompilerImpl(INameEnvironment environment, 68 IErrorHandlingPolicy policy, Map settings, 69 ICompilerRequestor requestor, IProblemFactory problemFactory) { 70 super(environment, policy, settings, requestor, problemFactory); 71 } 72 73 public void compile(ICompilationUnit[] sourceUnits) { 74 super.compile(sourceUnits); 75 cuds = null; 76 } 77 78 public void process(CompilationUnitDeclaration cud, int index) { 79 { 81 this.parser.getMethodBodies(cud); 82 83 if (cud.scope != null) { 85 cud.scope.faultInTypes(); 86 } 87 88 if (cud.scope != null) { 90 cud.scope.verifyMethods(lookupEnvironment.methodVerifier()); 91 } 92 93 cud.resolve(); 95 96 cud.analyseCode(); 98 99 if (doGenerateBytes) { 101 cud.generateCode(); 102 } 103 104 if (options.produceReferenceInfo && cud.scope != null) { 106 cud.scope.storeDependencyInfo(); 107 } 108 109 cud.compilationResult.totalUnitsKnown = totalUnits; 111 } 112 113 ICompilationUnit cu = cud.compilationResult.compilationUnit; 114 String loc = String.valueOf(cu.getFileName()); 115 TreeLogger logger = threadLogger.branch(TreeLogger.SPAM, 116 "Scanning for additional dependencies: " + loc, null); 117 118 String [] typeNames = doFindAdditionalTypesUsingJsni(logger, cud); 121 122 for (int i = 0; i < typeNames.length; i++) { 125 String typeName = typeNames[i]; 126 final String msg = "Need additional type '" + typeName + "'"; 127 logger.log(TreeLogger.SPAM, msg, null); 128 129 char[][] chars = CharOperation.splitOn('.', typeName.toCharArray()); 134 lookupEnvironment.getType(chars); 135 } 136 137 typeNames = doFindAdditionalTypesUsingRebinds(logger, cud); 138 139 for (int i = 0; i < typeNames.length; i++) { 142 String typeName = typeNames[i]; 143 final String msg = "Need additional type '" + typeName + "'"; 144 logger.log(TreeLogger.SPAM, msg, null); 145 146 ReferenceBinding type = resolvePossiblyNestedType(typeName); 151 } 152 153 if (cuds != null) { 156 cuds.add(cud); 157 } 158 } 159 160 private void compile(ICompilationUnit[] units, Set cuds) { 161 this.cuds = cuds; 162 compile(units); 163 } 164 165 private ReferenceBinding resolvePossiblyNestedType(String typeName) { 166 ReferenceBinding type = null; 167 168 int p = typeName.indexOf('$'); 169 if (p > 0) { 170 String cupName = typeName.substring(0, p); 172 char[][] chars = CharOperation.splitOn('.', cupName.toCharArray()); 173 if (lookupEnvironment.getType(chars) != null) { 174 chars = CharOperation.splitOn('.', typeName.toCharArray()); 176 type = lookupEnvironment.getCachedType(chars); 177 if (type == null) { 178 return null; 180 } 181 } 182 } else { 183 char[][] chars = CharOperation.splitOn('.', typeName.toCharArray()); 185 type = lookupEnvironment.getType(chars); 186 } 187 188 if (type != null) { 189 return type; 191 } 192 193 p = typeName.lastIndexOf('.'); 196 if (p >= 0) { 197 typeName = typeName.substring(0, p) + "$" + typeName.substring(p + 1); 198 return resolvePossiblyNestedType(typeName); 199 } 200 201 return null; 202 } 203 } 204 205 private class ICompilerRequestorImpl implements ICompilerRequestor { 206 207 public ICompilerRequestorImpl() { 208 } 209 210 public void acceptResult(CompilationResult result) { 211 IProblem[] errors = result.getErrors(); 214 215 if (errors != null && errors.length > 0) { 216 String fn = String.valueOf(result.compilationUnit.getFileName()); 219 String msg = "Errors in '" + fn + "'"; 220 TreeLogger branch = getLogger().branch(TreeLogger.ERROR, msg, null); 221 222 for (int i = 0; i < errors.length; i++) { 223 IProblem error = errors[i]; 224 225 msg = error.toString(); 228 msg = msg.substring(msg.indexOf(' ')); 229 230 if (error.getID() >= IProblem.InvalidUsageOfTypeParameters 231 && error.getID() <= IProblem.InvalidUsageOfAnnotationDeclarations) { 232 msg = "GWT does not yet support the Java 5.0 language enhancements; only 1.4 compatible source may be used"; 234 } 235 236 StringBuffer msgBuf = new StringBuffer (); 239 int line = error.getSourceLineNumber(); 240 if (line > 0) { 241 msgBuf.append("Line "); 242 msgBuf.append(line); 243 msgBuf.append(": "); 244 } 245 msgBuf.append(msg); 246 branch.log(TreeLogger.ERROR, msgBuf.toString(), null); 247 } 248 } 249 250 doAcceptResult(result); 253 } 254 } 255 256 private class INameEnvironmentImpl implements INameEnvironment { 257 258 public INameEnvironmentImpl() { 259 } 260 261 public void cleanup() { 262 } 264 265 public NameEnvironmentAnswer findType(char[] type, char[][] pkg) { 266 return findType(CharOperation.arrayConcat(pkg, type)); 267 } 268 269 public NameEnvironmentAnswer findType(char[][] compoundTypeName) { 270 271 String qname = CharOperation.toString(compoundTypeName); 274 if (nameEnvironmentAnswerForTypeName.containsKey(qname)) { 275 return (NameEnvironmentAnswer) (nameEnvironmentAnswerForTypeName.get(qname)); 276 } 277 TreeLogger logger = threadLogger.branch(TreeLogger.SPAM, 278 "Compiler is asking about '" + qname + "'", null); 279 280 if (sourceOracle.isPackage(qname)) { 281 logger.log(TreeLogger.SPAM, "Found to be a package", null); 282 return null; 283 } 284 285 ByteCode byteCode = doGetByteCodeFromCache(logger, qname); 288 if (byteCode != null) { 289 byte[] classBytes = byteCode.getBytes(); 292 char[] loc = byteCode.getLocation().toCharArray(); 293 try { 294 logger.log(TreeLogger.SPAM, "Found cached bytes", null); 295 ClassFileReader cfr = new ClassFileReader(classBytes, loc); 296 NameEnvironmentAnswer out = new NameEnvironmentAnswer(cfr, null); 297 nameEnvironmentAnswerForTypeName.put(qname, out); 298 return out; 299 } catch (ClassFormatException e) { 300 String msg = "Bad bytecode for '" + qname + "'"; 303 compiler.problemReporter.abortDueToInternalError(msg); 304 return null; 305 } 306 } 307 308 int pos = qname.indexOf('$'); 312 if (pos >= 0) { 313 qname = qname.substring(0, pos); 314 } 315 CompilationUnitProvider cup; 316 try { 317 cup = sourceOracle.findCompilationUnit(logger, qname); 318 if (cup != null) { 319 logger.log(TreeLogger.SPAM, "Found type in compilation unit: " 320 + cup.getLocation(), null); 321 ICompilationUnitAdapter unit = new ICompilationUnitAdapter(cup); 322 NameEnvironmentAnswer out = new NameEnvironmentAnswer(unit, null); 323 nameEnvironmentAnswerForTypeName.put(qname, out); 324 return out; 325 } else { 326 logger.log(TreeLogger.SPAM, "Not a known type", null); 327 return null; 328 } 329 } catch (UnableToCompleteException e) { 330 String msg = "Error acquiring source for '" + qname + "'"; 333 compiler.problemReporter.abortDueToInternalError(msg); 334 return null; 335 } 336 } 337 338 public boolean isPackage(char[][] parentPkg, char[] pkg) { 339 final char[] pathChars = CharOperation.concatWith(parentPkg, pkg, '.'); 344 String packageName = String.valueOf(pathChars); 345 if (knownPackages.contains(packageName)) { 346 return true; 347 } else if (sourceOracle.isPackage(packageName)) { 348 rememberPackage(packageName); 351 return true; 352 } else { 353 return false; 354 } 355 } 356 } 357 358 private final CompilerImpl compiler; 359 360 private final boolean doGenerateBytes; 361 362 private final Set knownPackages = new HashSet (); 363 364 private final Map nameEnvironmentAnswerForTypeName = new HashMap (); 365 366 private final SourceOracle sourceOracle; 367 368 private final ThreadLocalTreeLoggerProxy threadLogger = new ThreadLocalTreeLoggerProxy(); 369 370 private final Map unitsByTypeName = new HashMap (); 371 372 protected AbstractCompiler(SourceOracle sourceOracle, boolean doGenerateBytes) { 373 this.sourceOracle = sourceOracle; 374 this.doGenerateBytes = doGenerateBytes; 375 rememberPackage(""); 376 377 INameEnvironment env = new INameEnvironmentImpl(); 378 IErrorHandlingPolicy pol = DefaultErrorHandlingPolicies.proceedWithAllProblems(); 379 IProblemFactory probFact = new DefaultProblemFactory(Locale.getDefault()); 380 ICompilerRequestor req = new ICompilerRequestorImpl(); 381 Map settings = new HashMap (); 382 settings.put(CompilerOptions.OPTION_LineNumberAttribute, 383 CompilerOptions.GENERATE); 384 settings.put(CompilerOptions.OPTION_SourceFileAttribute, 385 CompilerOptions.GENERATE); 386 391 settings.put(CompilerOptions.OPTION_PreserveUnusedLocal, 392 CompilerOptions.PRESERVE); 393 settings.put(CompilerOptions.OPTION_ReportDeprecation, 394 CompilerOptions.IGNORE); 395 settings.put(CompilerOptions.OPTION_LocalVariableAttribute, 396 CompilerOptions.GENERATE); 397 settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4); 398 settings.put(CompilerOptions.OPTION_TargetPlatform, 399 CompilerOptions.VERSION_1_4); 400 401 settings.put(CompilerOptions.OPTION_DocCommentSupport, 403 CompilerOptions.ENABLED); 404 405 compiler = new CompilerImpl(env, pol, settings, req, probFact); 406 } 407 408 public void invalidateUnitsInFiles(Set fileNames, Set typeNames) { 409 if (sourceOracle instanceof StandardSourceOracle) { 413 StandardSourceOracle sso = (StandardSourceOracle) sourceOracle; 414 sso.invalidateCups(typeNames); 415 } 416 for (Iterator iter = typeNames.iterator(); iter.hasNext();) { 417 String qname = (String ) iter.next(); 418 unitsByTypeName.remove(qname); 419 nameEnvironmentAnswerForTypeName.remove(qname); 420 } 421 } 422 423 protected final CompilationUnitDeclaration[] compile(TreeLogger logger, 424 ICompilationUnit[] units) { 425 threadLogger.set(logger); 429 Set cuds = new HashSet (); 430 compiler.compile(units, cuds); 431 int size = cuds.size(); 432 CompilationUnitDeclaration[] cudArray = new CompilationUnitDeclaration[size]; 433 return (CompilationUnitDeclaration[]) cuds.toArray(cudArray); 434 } 435 436 protected void doAcceptResult(CompilationResult result) { 437 } 440 441 protected String [] doFindAdditionalTypesUsingJsni(TreeLogger logger, 442 CompilationUnitDeclaration cud) { 443 return Empty.STRINGS; 444 } 445 446 protected String [] doFindAdditionalTypesUsingRebinds(TreeLogger logger, 447 CompilationUnitDeclaration cud) { 448 return Empty.STRINGS; 449 } 450 451 456 protected ByteCode doGetByteCodeFromCache(TreeLogger logger, 457 String binaryTypeName) { 458 return null; 459 } 460 461 466 protected ICompilationUnit getCompilationUnitForType(TreeLogger logger, 467 String binaryTypeName) throws UnableToCompleteException { 468 469 String top = stripNestedTypeNames(binaryTypeName); 472 473 ICompilationUnit unit = (ICompilationUnit) unitsByTypeName.get(top); 476 if (unit != null) { 477 return unit; 478 } 479 480 CompilationUnitProvider cup = sourceOracle.findCompilationUnit(logger, top); 483 if (cup == null) { 484 String s = "Unable to find compilation unit for type '" + top + "'"; 487 logger.log(TreeLogger.WARN, s, null); 488 throw new UnableToCompleteException(); 489 } 490 491 unit = new ICompilationUnitAdapter(cup); 494 unitsByTypeName.put(top, unit); 495 496 return unit; 497 } 498 499 protected TreeLogger getLogger() { 500 return threadLogger; 501 } 502 503 512 protected void rememberPackage(String packageName) { 513 int i = packageName.lastIndexOf('.'); 514 if (i != -1) { 515 rememberPackage(packageName.substring(0, i)); 518 } 519 knownPackages.add(packageName); 520 } 521 522 protected ReferenceBinding resolvePossiblyNestedType(String typeName) { 523 return compiler.resolvePossiblyNestedType(typeName); 524 } 525 526 protected void setLogger(TreeLogger logger) { 527 threadLogger.set(logger); 528 } 529 530 SourceOracle getSourceOracle() { 531 return sourceOracle; 532 } 533 534 private String stripNestedTypeNames(String binaryTypeName) { 535 int i = binaryTypeName.lastIndexOf('.'); 536 if (i == -1) { 537 i = 0; 538 } 539 int j = binaryTypeName.indexOf('$', i); 540 if (j != -1) { 541 return binaryTypeName.substring(0, j); 542 } else { 543 return binaryTypeName; 544 } 545 } 546 } 547 | Popular Tags |