1 11 package org.eclipse.jdt.internal.eval; 12 13 import java.util.Locale ; 14 import java.util.Map ; 15 16 import org.eclipse.jdt.core.CompletionRequestor; 17 import org.eclipse.jdt.core.IJavaProject; 18 import org.eclipse.jdt.core.compiler.*; 19 import org.eclipse.jdt.internal.codeassist.CompletionEngine; 20 import org.eclipse.jdt.internal.codeassist.ISelectionRequestor; 21 import org.eclipse.jdt.internal.codeassist.SelectionEngine; 22 import org.eclipse.jdt.internal.compiler.ClassFile; 23 import org.eclipse.jdt.internal.compiler.IProblemFactory; 24 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; 25 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; 26 import org.eclipse.jdt.internal.compiler.env.IBinaryType; 27 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; 28 import org.eclipse.jdt.internal.compiler.env.INameEnvironment; 29 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; 30 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; 31 import org.eclipse.jdt.internal.compiler.util.SuffixConstants; 32 import org.eclipse.jdt.internal.core.SearchableEnvironment; 33 import org.eclipse.jdt.internal.core.util.Util; 34 35 38 public class EvaluationContext implements EvaluationConstants, SuffixConstants { 39 42 static final boolean TIMING = false; 43 44 47 static int VAR_CLASS_COUNTER = 0; 48 static int CODE_SNIPPET_COUNTER = 0; 49 50 GlobalVariable[] variables; 51 int variableCount; 52 char[][] imports; 53 char[] packageName; 54 boolean varsChanged; 55 VariablesInfo installedVars; 56 IBinaryType codeSnippetBinary; 57 String lineSeparator; 58 59 60 char[] declaringTypeName; 61 int[] localVariableModifiers; 62 char[][] localVariableTypeNames; 63 char[][] localVariableNames; 64 65 66 boolean isStatic; 67 boolean isConstructorCall; 68 71 public EvaluationContext() { 72 this.variables = new GlobalVariable[5]; 73 this.variableCount = 0; 74 this.imports = CharOperation.NO_CHAR_CHAR; 75 this.packageName = CharOperation.NO_CHAR; 76 this.varsChanged = true; 77 this.isStatic = true; 78 this.isConstructorCall = false; 79 this.lineSeparator = org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR; } 81 84 public GlobalVariable[] allVariables() { 85 GlobalVariable[] result = new GlobalVariable[this.variableCount]; 86 System.arraycopy(this.variables, 0, result, 0, this.variableCount); 87 return result; 88 } 89 104 public void complete(char[] codeSnippet, int completionPosition, SearchableEnvironment environment, CompletionRequestor requestor, Map options, IJavaProject project) { 105 try { 106 IRequestor variableRequestor = new IRequestor() { 107 public boolean acceptClassFiles(ClassFile[] classFiles, char[] codeSnippetClassName) { 108 return true; 110 } 111 public void acceptProblem(CategorizedProblem problem, char[] fragmentSource, int fragmentKind) { 112 } 114 }; 115 this.evaluateVariables(environment, options, variableRequestor, new DefaultProblemFactory(Locale.getDefault())); 116 } catch (InstallException e) { 117 } 119 final char[] className = "CodeSnippetCompletion".toCharArray(); final CodeSnippetToCuMapper mapper = new CodeSnippetToCuMapper( 121 codeSnippet, 122 this.packageName, 123 this.imports, 124 className, 125 this.installedVars == null ? null : this.installedVars.className, 126 this.localVariableNames, 127 this.localVariableTypeNames, 128 this.localVariableModifiers, 129 this.declaringTypeName, 130 this.lineSeparator 131 ); 132 ICompilationUnit sourceUnit = new ICompilationUnit() { 133 public char[] getFileName() { 134 return CharOperation.concat(className, Util.defaultJavaExtension().toCharArray()); 135 } 136 public char[] getContents() { 137 return mapper.getCUSource(EvaluationContext.this.lineSeparator); 138 } 139 public char[] getMainTypeName() { 140 return className; 141 } 142 public char[][] getPackageName() { 143 return null; 144 } 145 }; 146 147 CompletionEngine engine = new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project); 148 149 if (this.installedVars != null) { 150 IBinaryType binaryType = this.getRootCodeSnippetBinary(); 151 if (binaryType != null) { 152 engine.lookupEnvironment.cacheBinaryType(binaryType, null ); 153 } 154 155 ClassFile[] classFiles = installedVars.classFiles; 156 for (int i = 0; i < classFiles.length; i++) { 157 ClassFile classFile = classFiles[i]; 158 IBinaryType binary = null; 159 try { 160 binary = new ClassFileReader(classFile.getBytes(), null); 161 } catch (ClassFormatException e) { 162 e.printStackTrace(); } 164 engine.lookupEnvironment.cacheBinaryType(binary, null ); 165 } 166 } 167 168 engine.complete(sourceUnit, mapper.startPosOffset + completionPosition, mapper.startPosOffset); 169 } 170 174 public void deleteVariable(GlobalVariable variable) { 175 GlobalVariable[] vars = this.variables; 176 int index = -1; 177 for (int i = 0; i < this.variableCount; i++) { 178 if (vars[i].equals(variable)) { 179 index = i; 180 break; 181 } 182 } 183 if (index == -1) { 184 return; 185 } 186 int elementCount = this.variableCount--; 187 int j = elementCount - index - 1; 188 if (j > 0) { 189 System.arraycopy(vars, index + 1, vars, index, j); 190 } 191 vars[elementCount - 1] = null; 192 this.varsChanged = true; 193 } 194 private void deployCodeSnippetClassIfNeeded(IRequestor requestor) { 195 if (this.codeSnippetBinary == null) { 196 requestor.acceptClassFiles( 198 new ClassFile[] { 199 new ClassFile() { 200 public byte[] getBytes() { 201 return getCodeSnippetBytes(); 202 } 203 public char[][] getCompoundName() { 204 return EvaluationConstants.ROOT_COMPOUND_NAME; 205 } 206 } 207 }, 208 null); 209 } 210 } 211 215 public void evaluate( 216 char[] codeSnippet, 217 char[][] contextLocalVariableTypeNames, 218 char[][] contextLocalVariableNames, 219 int[] contextLocalVariableModifiers, 220 char[] contextDeclaringTypeName, 221 boolean contextIsStatic, 222 boolean contextIsConstructorCall, 223 INameEnvironment environment, 224 Map options, 225 final IRequestor requestor, 226 IProblemFactory problemFactory) throws InstallException { 227 228 this.localVariableTypeNames = contextLocalVariableTypeNames; 230 this.localVariableNames = contextLocalVariableNames; 231 this.localVariableModifiers = contextLocalVariableModifiers; 232 this.declaringTypeName = contextDeclaringTypeName; 233 this.isStatic = contextIsStatic; 234 this.isConstructorCall = contextIsConstructorCall; 235 236 this.deployCodeSnippetClassIfNeeded(requestor); 237 238 try { 239 class ForwardingRequestor implements IRequestor { 241 boolean hasErrors = false; 242 public boolean acceptClassFiles(ClassFile[] classFiles, char[] codeSnippetClassName) { 243 return requestor.acceptClassFiles(classFiles, codeSnippetClassName); 244 } 245 public void acceptProblem(CategorizedProblem problem, char[] fragmentSource, int fragmentKind) { 246 requestor.acceptProblem(problem, fragmentSource, fragmentKind); 247 if (problem.isError()) { 248 this.hasErrors = true; 249 } 250 } 251 } 252 ForwardingRequestor forwardingRequestor = new ForwardingRequestor(); 253 if (this.varsChanged) { 254 evaluateVariables(environment, options, forwardingRequestor, problemFactory); 255 } 256 257 if (!forwardingRequestor.hasErrors) { 259 Evaluator evaluator = 260 new CodeSnippetEvaluator( 261 codeSnippet, 262 this, 263 environment, 264 options, 265 requestor, 266 problemFactory); 267 ClassFile[] classes = null; 268 if (TIMING) { 269 long start = System.currentTimeMillis(); 270 classes = evaluator.getClasses(); 271 System.out.println("Time to compile [" + new String (codeSnippet) + "] was " + (System.currentTimeMillis() - start) + "ms"); } else { 273 classes = evaluator.getClasses(); 274 } 275 if (classes != null && classes.length > 0) { 277 char[] simpleClassName = evaluator.getClassName(); 278 char[] pkgName = this.getPackageName(); 279 char[] qualifiedClassName = 280 pkgName.length == 0 ? 281 simpleClassName : 282 CharOperation.concat(pkgName, simpleClassName, '.'); 283 CODE_SNIPPET_COUNTER++; 284 requestor.acceptClassFiles(classes, qualifiedClassName); 285 } 286 } 287 } finally { 288 this.localVariableTypeNames = null; 290 this.localVariableNames = null; 291 this.localVariableModifiers = null; 292 this.declaringTypeName = null; 293 this.isStatic = true; 294 this.isConstructorCall = false; 295 } 296 } 297 301 public void evaluate(char[] codeSnippet, INameEnvironment environment, Map options, final IRequestor requestor, IProblemFactory problemFactory) throws InstallException { 302 this.evaluate( 303 codeSnippet, 304 null, 305 null, 306 null, 307 null, 308 true, 309 false, 310 environment, 311 options, 312 requestor, 313 problemFactory); 314 } 315 318 public void evaluateImports(INameEnvironment environment, IRequestor requestor, IProblemFactory problemFactory) { 319 for (int i = 0; i < this.imports.length; i++) { 320 CategorizedProblem[] problems = new CategorizedProblem[] {null}; 321 char[] importDeclaration = this.imports[i]; 322 char[][] splitDeclaration = CharOperation.splitOn('.', importDeclaration); 323 int splitLength = splitDeclaration.length; 324 if (splitLength > 0) { 325 char[] pkgName = splitDeclaration[splitLength - 1]; 326 if (pkgName.length == 1 && pkgName[0] == '*') { 327 char[][] parentName; 328 switch (splitLength) { 329 case 1: 330 parentName = null; 331 break; 332 case 2: 333 parentName = null; 334 pkgName = splitDeclaration[splitLength - 2]; 335 break; 336 default: 337 parentName = CharOperation.subarray(splitDeclaration, 0, splitLength - 2); 338 pkgName = splitDeclaration[splitLength - 2]; 339 } 340 if (!environment.isPackage(parentName, pkgName)) { 341 String [] arguments = new String [] {new String (importDeclaration)}; 342 problems[0] = problemFactory.createProblem(importDeclaration, IProblem.ImportNotFound, arguments, arguments, ProblemSeverities.Warning, 0, importDeclaration.length - 1, i, 0); 343 } 344 } else { 345 if (environment.findType(splitDeclaration) == null) { 346 String [] arguments = new String [] {new String (importDeclaration)}; 347 problems[0] = problemFactory.createProblem(importDeclaration, IProblem.ImportNotFound, arguments, arguments, ProblemSeverities.Warning, 0, importDeclaration.length - 1, i, 0); 348 } 349 } 350 } else { 351 String [] arguments = new String [] {new String (importDeclaration)}; 352 problems[0] = problemFactory.createProblem(importDeclaration, IProblem.ImportNotFound, arguments, arguments, ProblemSeverities.Warning, 0, importDeclaration.length - 1, i, 0); 353 } 354 if (problems[0] != null) { 355 requestor.acceptProblem(problems[0], importDeclaration, EvaluationResult.T_IMPORT); 356 } 357 } 358 } 359 364 public void evaluateVariable(GlobalVariable variable, INameEnvironment environment, Map options, IRequestor requestor, IProblemFactory problemFactory) throws InstallException { 365 this.evaluate(variable.getName(), environment, options, requestor, problemFactory); 366 } 367 371 public void evaluateVariables(INameEnvironment environment, Map options, IRequestor requestor, IProblemFactory problemFactory) throws InstallException { 372 this.deployCodeSnippetClassIfNeeded(requestor); 373 VariablesEvaluator evaluator = new VariablesEvaluator(this, environment, options, requestor, problemFactory); 374 ClassFile[] classes = evaluator.getClasses(); 375 if (classes != null) { 376 if (classes.length > 0) { 377 Util.sort(classes, new Util.Comparer() { 381 public int compare(Object a, Object b) { 382 if (a == b) return 0; 383 ClassFile enclosing = ((ClassFile) a).enclosingClassFile; 384 while (enclosing != null) { 385 if (enclosing == b) 386 return 1; 387 enclosing = enclosing.enclosingClassFile; 388 } 389 return -1; 390 } 391 }); 392 393 if (!requestor.acceptClassFiles(classes, null)) { 395 throw new InstallException(); 396 } 397 398 int count = this.variableCount; 400 GlobalVariable[] variablesCopy = new GlobalVariable[count]; 401 System.arraycopy(this.variables, 0, variablesCopy, 0, count); 402 this.installedVars = new VariablesInfo(evaluator.getPackageName(), evaluator.getClassName(), classes, variablesCopy, count); 403 VAR_CLASS_COUNTER++; 404 } 405 this.varsChanged = false; 406 } 407 } 408 436 byte[] getCodeSnippetBytes() { 437 return new byte[] { 438 -54, -2, -70, -66, 0, 3, 0, 45, 0, 35, 1, 0, 48, 111, 114, 103, 47, 101, 99, 108, 105, 112, 115, 101, 47, 106, 100, 116, 47, 105, 110, 116, 101, 114, 110, 97, 108, 47, 101, 118, 97, 108, 47, 116, 97, 114, 103, 101, 116, 47, 67, 111, 100, 101, 83, 110, 105, 112, 112, 101, 116, 7, 0, 1, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 7, 0, 3, 1, 0, 10, 114, 101, 115, 117, 108, 116, 84, 121, 112, 101, 1, 0, 17, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 67, 108, 97, 115, 115, 59, 1, 0, 11, 114, 101, 115, 117, 108, 116, 86, 97, 108, 117, 101, 1, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 1, 0, 7, 99, 108, 97, 115, 115, 36, 48, 1, 0, 9, 83, 121, 110, 116, 104, 101, 116, 105, 99, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 12, 0, 11, 0, 12, 10, 0, 4, 0, 14, 1, 0, 14, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 86, 111, 105, 100, 7, 0, 16, 1, 0, 4, 84, 89, 80, 69, 12, 0, 18, 0, 6, 9, 0, 17, 0, 19, 12, 0, 5, 0, 6, 9, 0, 2, 0, 21, 12, 0, 7, 0, 8, 9, 0, 2, 0, 23, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 13, 103, 101, 116, 82, 101, 115, 117, 108, 116, 84, 121, 112, 101, 1, 0, 19, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 67, 108, 97, 115, 115, 59, 1, 0, 14, 103, 101, 116, 82, 101, 115, 117, 108, 116, 86, 97, 108, 117, 101, 1, 0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 1, 0, 3, 114, 117, 110, 1, 0, 9, 115, 101, 116, 82, 101, 115, 117, 108, 116, 1, 0, 38, 40, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 67, 108, 97, 115, 115, 59, 41, 86, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 16, 67, 111, 100, 101, 83, 110, 105, 112, 112, 101, 116, 46, 106, 97, 118, 97, 0, 33, 0, 2, 0, 4, 0, 0, 0, 3, 0, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 7, 0, 8, 0, 0, 0, 8, 0, 9, 0, 6, 0, 1, 0, 10, 0, 0, 0, 0, 0, 5, 0, 1, 0, 11, 0, 12, 0, 1, 0, 13, 0, 0, 0, 53, 0, 2, 0, 1, 0, 0, 0, 17, 42, -73, 0, 15, 42, -78, 0, 20, -75, 0, 22, 42, 1, -75, 0, 24, -79, 0, 0, 0, 1, 0, 25, 0, 0, 0, 18, 0, 4, 0, 0, 0, 17, 0, 4, 0, 18, 0, 11, 0, 19, 0, 16, 0, 17, 0, 1, 0, 26, 0, 27, 0, 1, 0, 13, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -76, 0, 22, -80, 0, 0, 0, 1, 0, 25, 0, 0, 0, 6, 0, 1, 0, 0, 0, 24, 0, 1, 0, 28, 0, 29, 0, 1, 0, 13, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -76, 0, 24, -80, 0, 0, 0, 1, 0, 25, 0, 0, 0, 6, 0, 1, 0, 0, 0, 30, 0, 1, 0, 30, 0, 12, 0, 1, 0, 13, 0, 0, 0, 25, 0, 0, 0, 1, 0, 0, 0, 1, -79, 0, 0, 0, 1, 0, 25, 0, 0, 0, 6, 0, 1, 0, 0, 0, 36, 0, 1, 0, 31, 0, 32, 0, 1, 0, 13, 0, 0, 0, 43, 0, 2, 0, 3, 0, 0, 0, 11, 42, 43, -75, 0, 24, 42, 44, -75, 0, 22, -79, 0, 0, 0, 1, 0, 25, 0, 0, 0, 14, 0, 3, 0, 0, 0, 42, 0, 5, 0, 43, 0, 10, 0, 41, 0, 1, 0, 33, 0, 0, 0, 2, 0, 34 439 }; 440 } 441 445 public static String getCodeSnippetSource() { 446 return 447 "package org.eclipse.jdt.internal.eval.target;\n" + "\n" + "/*\n" + " * (c) Copyright IBM Corp. 2000, 2001.\n" + " * All Rights Reserved.\n" + " */\n" + "/**\n" + " * The root of all code snippet classes. Code snippet classes\n" + " * are supposed to overide the run() method.\n" + " * <p>\n" + " * IMPORTANT NOTE:\n" + " * All methods in this class must be public since this class is going to be loaded by the\n" + " * bootstrap class loader, and the other code snippet support classes might be loaded by \n" + " * another class loader (so their runtime packages are going to be different).\n" + " */\n" + "public class CodeSnippet {\n" + " private Class resultType = void.class;\n" + " private Object resultValue = null;\n" + "/**\n" + " * Returns the result type of the code snippet evaluation.\n" + " */\n" + "public Class getResultType() {\n" + " return this.resultType;\n" + "}\n" + "/**\n" + " * Returns the result value of the code snippet evaluation.\n" + " */\n" + "public Object getResultValue() {\n" + " return this.resultValue;\n" + "}\n" + "/**\n" + " * The code snippet. Subclasses must override this method with a transformed code snippet\n" + " * that stores the result using setResult(Class, Object).\n" + " */\n" + "public void run() {\n" + "}\n" + "/**\n" + " * Stores the result type and value of the code snippet evaluation.\n" + " */\n" + "public void setResult(Object someResultValue, Class someResultType) {\n" + " this.resultValue = someResultValue;\n" + " this.resultType = someResultType;\n" + "}\n" + "}\n"; } 492 497 public char[][] getImports() { 498 return this.imports; 499 } 500 505 public char[] getPackageName() { 506 return this.packageName; 507 } 508 511 IBinaryType getRootCodeSnippetBinary() { 512 if (this.codeSnippetBinary == null) { 513 this.codeSnippetBinary = new CodeSnippetSkeleton(); 514 } 515 return this.codeSnippetBinary; 516 } 517 public char[] getVarClassName() { 518 if (installedVars == null) return CharOperation.NO_CHAR; 519 return CharOperation.concat(installedVars.packageName, installedVars.className, '.'); 520 } 521 528 public GlobalVariable newVariable(char[] typeName, char[] name, char[] initializer) { 529 GlobalVariable var = new GlobalVariable(typeName, name, initializer); 530 if (this.variableCount >= this.variables.length) System.arraycopy(this.variables, 0, this.variables = new GlobalVariable[this.variableCount * 2], 0, this.variableCount); 532 this.variables[this.variableCount++] = var; 533 this.varsChanged = true; 534 return var; 535 } 536 557 public void select( 558 char[] codeSnippet, 559 int selectionSourceStart, 560 int selectionSourceEnd, 561 SearchableEnvironment environment, 562 ISelectionRequestor requestor, 563 Map options) { 564 565 final char[] className = "CodeSnippetSelection".toCharArray(); final CodeSnippetToCuMapper mapper = new CodeSnippetToCuMapper( 567 codeSnippet, 568 this.packageName, 569 this.imports, 570 className, 571 this.installedVars == null ? null : this.installedVars.className, 572 this.localVariableNames, 573 this.localVariableTypeNames, 574 this.localVariableModifiers, 575 this.declaringTypeName, 576 this.lineSeparator 577 ); 578 ICompilationUnit sourceUnit = new ICompilationUnit() { 579 public char[] getFileName() { 580 return CharOperation.concat(className, Util.defaultJavaExtension().toCharArray()); 581 } 582 public char[] getContents() { 583 return mapper.getCUSource(EvaluationContext.this.lineSeparator); 584 } 585 public char[] getMainTypeName() { 586 return className; 587 } 588 public char[][] getPackageName() { 589 return null; 590 } 591 }; 592 SelectionEngine engine = new SelectionEngine(environment, mapper.getSelectionRequestor(requestor), options); 593 engine.select(sourceUnit, mapper.startPosOffset + selectionSourceStart, mapper.startPosOffset + selectionSourceEnd); 594 } 595 600 public void setImports(char[][] imports) { 601 this.imports = imports; 602 this.varsChanged = true; } 604 607 public void setLineSeparator(String lineSeparator) { 608 this.lineSeparator = lineSeparator; 609 } 610 614 public void setPackageName(char[] packageName) { 615 this.packageName = packageName; 616 this.varsChanged = true; } 618 } 619 | Popular Tags |