/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.eval; import java.util.Locale; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.CompletionRequestor; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.codeassist.CompletionEngine; import org.eclipse.jdt.internal.codeassist.ISelectionRequestor; import org.eclipse.jdt.internal.codeassist.SelectionEngine; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.IProblemFactory; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.SearchableEnvironment; import org.eclipse.jdt.internal.core.util.Util; /** * @see org.eclipse.jdt.core.eval.IEvaluationContext */ public class EvaluationContext implements EvaluationConstants, SuffixConstants { /** * Global counters so that several evaluation context can deploy on the same runtime. */ static int VAR_CLASS_COUNTER= 0; static int CODE_SNIPPET_COUNTER= 0; GlobalVariable[] variables; int variableCount; char[][] imports; char[] packageName; boolean varsChanged; VariablesInfo installedVars; IBinaryType codeSnippetBinary; String lineSeparator; /* do names implicitly refer to a given type */ char[] declaringTypeName; int[] localVariableModifiers; char[][] localVariableTypeNames; char[][] localVariableNames; /* can 'this' be used in this context */ boolean isStatic; boolean isConstructorCall; /** * Creates a new evaluation context. */ public EvaluationContext() { this.variables= new GlobalVariable[5]; this.variableCount= 0; this.imports= CharOperation.NO_CHAR_CHAR; this.packageName= CharOperation.NO_CHAR; this.varsChanged= true; this.isStatic= true; this.isConstructorCall= false; this.lineSeparator= org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR; // default value } /** * Returns the global variables of this evaluation context in the order they were created in. */ public GlobalVariable[] allVariables() { GlobalVariable[] result= new GlobalVariable[this.variableCount]; System.arraycopy(this.variables, 0, result, 0, this.variableCount); return result; } /** * Computes a completion at the specified position of the given code snippet. (Note that this * evaluation context's VM doesn't need to be running.) * * @param environment used to resolve type/package references and search for types/packages * based on partial names. * * @param requestor since the engine might produce answers of various forms, the engine is * associated with a requestor able to accept all possible completions. * * @param options set of options used to configure the code assist engine. * * @param owner the owner of working copies that take precedence over their original compilation * units * * @param monitor the progress monitor used to report progress */ public void complete( char[] codeSnippet, int completionPosition, SearchableEnvironment environment, CompletionRequestor requestor, Map options, final IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) { try { IRequestor variableRequestor= new IRequestor() { public boolean acceptClassFiles(ClassFile[] classFiles, char[] codeSnippetClassName) { // Do nothing return true; } public void acceptProblem(CategorizedProblem problem, char[] fragmentSource, int fragmentKind) { // Do nothing } }; evaluateVariables(environment, options, variableRequestor, new DefaultProblemFactory(Locale.getDefault())); } catch (InstallException e) { // Do nothing } final char[] className= "CodeSnippetCompletion".toCharArray(); //$NON-NLS-1$ final CodeSnippetToCuMapper mapper= new CodeSnippetToCuMapper( codeSnippet, this.packageName, this.imports, className, this.installedVars == null ? null : this.installedVars.className, this.localVariableNames, this.localVariableTypeNames, this.localVariableModifiers, this.declaringTypeName, this.lineSeparator ); ICompilationUnit sourceUnit= new ICompilationUnit() { public char[] getFileName() { return CharOperation.concat(className, Util.defaultJavaExtension().toCharArray()); } public char[] getContents() { return mapper.getCUSource(EvaluationContext.this.lineSeparator); } public char[] getMainTypeName() { return className; } public char[][] getPackageName() { return null; } }; CompletionEngine engine= new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project, owner, monitor); if (this.installedVars != null) { IBinaryType binaryType= getRootCodeSnippetBinary(); if (binaryType != null) { engine.lookupEnvironment.cacheBinaryType(binaryType, null /*no access restriction*/); } ClassFile[] classFiles= this.installedVars.classFiles; for (int i= 0; i < classFiles.length; i++) { ClassFile classFile= classFiles[i]; IBinaryType binary= null; try { binary= new ClassFileReader(classFile.getBytes(), null); } catch (ClassFormatException e) { e.printStackTrace(); // Should never happen since we compiled this type } engine.lookupEnvironment.cacheBinaryType(binary, null /*no access restriction*/); } } engine.complete(sourceUnit, mapper.startPosOffset + completionPosition, mapper.startPosOffset, null/*extended context isn't computed*/); } /** * Deletes the given variable from this evaluation context. This will take effect in the target * VM only the next time global variables are installed. */ public void deleteVariable(GlobalVariable variable) { GlobalVariable[] vars= this.variables; int index= -1; for (int i= 0; i < this.variableCount; i++) { if (vars[i].equals(variable)) { index= i; break; } } if (index == -1) { return; } int elementCount= this.variableCount--; int j= elementCount - index - 1; if (j > 0) { System.arraycopy(vars, index + 1, vars, index, j); } vars[elementCount - 1]= null; this.varsChanged= true; } private void deployCodeSnippetClassIfNeeded(IRequestor requestor) throws InstallException { if (this.codeSnippetBinary == null) { // Deploy CodeSnippet class (only once) if (!requestor.acceptClassFiles( new ClassFile[] { new ClassFile() { public byte[] getBytes() { return getCodeSnippetBytes(); } public char[][] getCompoundName() { return EvaluationConstants.ROOT_COMPOUND_NAME; } } }, null)) throw new InstallException(); } } /** * @see org.eclipse.jdt.core.eval.IEvaluationContext * @exception org.eclipse.jdt.internal.eval.InstallException if the code snippet class files * could not be deployed. */ public void evaluate( char[] codeSnippet, char[][] contextLocalVariableTypeNames, char[][] contextLocalVariableNames, int[] contextLocalVariableModifiers, char[] contextDeclaringTypeName, boolean contextIsStatic, boolean contextIsConstructorCall, INameEnvironment environment, Map options, final IRequestor requestor, IProblemFactory problemFactory) throws InstallException { // Initialialize context this.localVariableTypeNames= contextLocalVariableTypeNames; this.localVariableNames= contextLocalVariableNames; this.localVariableModifiers= contextLocalVariableModifiers; this.declaringTypeName= contextDeclaringTypeName; this.isStatic= contextIsStatic; this.isConstructorCall= contextIsConstructorCall; deployCodeSnippetClassIfNeeded(requestor); try { // Install new variables if needed class ForwardingRequestor implements IRequestor { boolean hasErrors= false; public boolean acceptClassFiles(ClassFile[] classFiles, char[] codeSnippetClassName) { return requestor.acceptClassFiles(classFiles, codeSnippetClassName); } public void acceptProblem(CategorizedProblem problem, char[] fragmentSource, int fragmentKind) { requestor.acceptProblem(problem, fragmentSource, fragmentKind); if (problem.isError()) { this.hasErrors= true; } } } ForwardingRequestor forwardingRequestor= new ForwardingRequestor(); if (this.varsChanged) { evaluateVariables(environment, options, forwardingRequestor, problemFactory); } // Compile code snippet if there was no errors while evaluating the variables if (!forwardingRequestor.hasErrors) { Evaluator evaluator= new CodeSnippetEvaluator( codeSnippet, this, environment, options, requestor, problemFactory); ClassFile[] classes= evaluator.getClasses(); // Send code snippet on target if (classes != null && classes.length > 0) { char[] simpleClassName= evaluator.getClassName(); char[] pkgName= getPackageName(); char[] qualifiedClassName= pkgName.length == 0 ? simpleClassName : CharOperation.concat(pkgName, simpleClassName, '.'); CODE_SNIPPET_COUNTER++; if (!requestor.acceptClassFiles(classes, qualifiedClassName)) throw new InstallException(); } } } finally { // Reinitialize context to default values this.localVariableTypeNames= null; this.localVariableNames= null; this.localVariableModifiers= null; this.declaringTypeName= null; this.isStatic= true; this.isConstructorCall= false; } } /** * @see org.eclipse.jdt.core.eval.IEvaluationContext * @exception org.eclipse.jdt.internal.eval.InstallException if the code snippet class files * could not be deployed. */ public void evaluate(char[] codeSnippet, INameEnvironment environment, Map options, final IRequestor requestor, IProblemFactory problemFactory) throws InstallException { this.evaluate( codeSnippet, null, null, null, null, true, false, environment, options, requestor, problemFactory); } /** * @see org.eclipse.jdt.core.eval.IEvaluationContext */ public void evaluateImports(INameEnvironment environment, IRequestor requestor, IProblemFactory problemFactory) { for (int i= 0; i < this.imports.length; i++) { CategorizedProblem[] problems= new CategorizedProblem[] { null }; char[] importDeclaration= this.imports[i]; char[][] splitDeclaration= CharOperation.splitOn('.', importDeclaration); int splitLength= splitDeclaration.length; if (splitLength > 0) { char[] pkgName= splitDeclaration[splitLength - 1]; if (pkgName.length == 1 && pkgName[0] == '*') { char[][] parentName; switch (splitLength) { case 1: parentName= null; break; case 2: parentName= null; pkgName= splitDeclaration[splitLength - 2]; break; default: parentName= CharOperation.subarray(splitDeclaration, 0, splitLength - 2); pkgName= splitDeclaration[splitLength - 2]; } if (!environment.isPackage(parentName, pkgName)) { String[] arguments= new String[] { new String(importDeclaration) }; problems[0]= problemFactory.createProblem(importDeclaration, IProblem.ImportNotFound, arguments, arguments, ProblemSeverities.Warning, 0, importDeclaration.length - 1, i, 0); } } else { if (environment.findType(splitDeclaration) == null) { String[] arguments= new String[] { new String(importDeclaration) }; problems[0]= problemFactory.createProblem(importDeclaration, IProblem.ImportNotFound, arguments, arguments, ProblemSeverities.Warning, 0, importDeclaration.length - 1, i, 0); } } } else { String[] arguments= new String[] { new String(importDeclaration) }; problems[0]= problemFactory.createProblem(importDeclaration, IProblem.ImportNotFound, arguments, arguments, ProblemSeverities.Warning, 0, importDeclaration.length - 1, i, 0); } if (problems[0] != null) { requestor.acceptProblem(problems[0], importDeclaration, EvaluationResult.T_IMPORT); } } } /** * @see org.eclipse.jdt.core.eval.IEvaluationContext * @exception org.eclipse.jdt.internal.eval.InstallException if the code snippet class files * could not be deployed. * @exception java.lang.IllegalArgumentException if the global has not been installed yet. */ public void evaluateVariable(GlobalVariable variable, INameEnvironment environment, Map options, IRequestor requestor, IProblemFactory problemFactory) throws InstallException { this.evaluate(variable.getName(), environment, options, requestor, problemFactory); } /** * @see org.eclipse.jdt.core.eval.IEvaluationContext * @exception org.eclipse.jdt.internal.eval.InstallException if the code snippet class files * could not be deployed. */ public void evaluateVariables(INameEnvironment environment, Map options, IRequestor requestor, IProblemFactory problemFactory) throws InstallException { deployCodeSnippetClassIfNeeded(requestor); VariablesEvaluator evaluator= new VariablesEvaluator(this, environment, options, requestor, problemFactory); ClassFile[] classes= evaluator.getClasses(); if (classes != null) { if (classes.length > 0) { // Sort classes so that enclosing types are cached before nested types // otherwise an AbortCompilation is thrown in 1.5 mode since the enclosing type // is needed to resolve a nested type Util.sort(classes, new Util.Comparer() { public int compare(Object a, Object b) { if (a == b) return 0; ClassFile enclosing= ((ClassFile)a).enclosingClassFile; while (enclosing != null) { if (enclosing == b) return 1; enclosing= enclosing.enclosingClassFile; } return -1; } }); // Send classes if (!requestor.acceptClassFiles(classes, null)) { throw new InstallException(); } // Remember that the variables have been installed int count= this.variableCount; GlobalVariable[] variablesCopy= new GlobalVariable[count]; System.arraycopy(this.variables, 0, variablesCopy, 0, count); this.installedVars= new VariablesInfo(evaluator.getPackageName(), evaluator.getClassName(), classes, variablesCopy, count); VAR_CLASS_COUNTER++; } this.varsChanged= false; } } /** * Returns the bytes of the CodeSnippet class. Generated using the following code snippet: * [java.io.BufferedWriter writer = new java.io.BufferedWriter(new * java.io.FileWriter("d:/temp/CodeSnippet.java")); * writer.write(org.eclipse.jdt.internal.eval.EvaluationContext.getCodeSnippetSource()); * writer.close(); org.eclipse.jdt.internal.compiler.batch.Main.compile( * "d:/temp/CodeSnippet.java -d d:/temp -classpath d:/jdk1.2.2/jre/lib/rt.jar -verbose"); * java.io.FileInputStream reader = new * java.io.FileInputStream("d:/temp/org/eclipse/jdt/internal/eval/target/CodeSnippet.class"); * byte[] bytes = org.eclipse.jdt.internal.core.Util.readContentsAsBytes(reader); * reader.close(); StringBuffer buffer = new StringBuffer(); * buffer.append("private byte[] getCodeSnippetBytes() {\n"); * buffer.append(" return new byte[] {\n"); buffer.append(" "); for (int i = 0; i < * bytes.length; i++) { buffer.append(bytes[i]); if (i == bytes.length - 1) { * buffer.append("\n"); } else { buffer.append(", "); } } buffer.append(" };\n"); * buffer.append("}"); buffer.toString() ] */ byte[] getCodeSnippetBytes() { return new byte[] { -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 }; } /** * Returns the source of the CodeSnippet class. This is used to generate the binary of the * CodeSnippetClass */ public static String getCodeSnippetSource() { return "package org.eclipse.jdt.internal.eval.target;\n" + //$NON-NLS-1$ "\n" + //$NON-NLS-1$ "/*\n" + //$NON-NLS-1$ " * (c) Copyright IBM Corp. 2000, 2001.\n" + //$NON-NLS-1$ " * All Rights Reserved.\n" + //$NON-NLS-1$ " */\n" + //$NON-NLS-1$ "/**\n" + //$NON-NLS-1$ " * The root of all code snippet classes. Code snippet classes\n" + //$NON-NLS-1$ " * are supposed to overide the run() method.\n" + //$NON-NLS-1$ " * <p>\n" + //$NON-NLS-1$ " * IMPORTANT NOTE:\n" + //$NON-NLS-1$ " * All methods in this class must be public since this class is going to be loaded by the\n" + //$NON-NLS-1$ " * bootstrap class loader, and the other code snippet support classes might be loaded by \n" + //$NON-NLS-1$ " * another class loader (so their runtime packages are going to be different).\n" + //$NON-NLS-1$ " */\n" + //$NON-NLS-1$ "public class CodeSnippet {\n" + //$NON-NLS-1$ " private Class resultType = void.class;\n" + //$NON-NLS-1$ " private Object resultValue = null;\n" + //$NON-NLS-1$ "/**\n" + //$NON-NLS-1$ " * Returns the result type of the code snippet evaluation.\n" + //$NON-NLS-1$ " */\n" + //$NON-NLS-1$ "public Class getResultType() {\n" + //$NON-NLS-1$ " return this.resultType;\n" + //$NON-NLS-1$ "}\n" + //$NON-NLS-1$ "/**\n" + //$NON-NLS-1$ " * Returns the result value of the code snippet evaluation.\n" + //$NON-NLS-1$ " */\n" + //$NON-NLS-1$ "public Object getResultValue() {\n" + //$NON-NLS-1$ " return this.resultValue;\n" + //$NON-NLS-1$ "}\n" + //$NON-NLS-1$ "/**\n" + //$NON-NLS-1$ " * The code snippet. Subclasses must override this method with a transformed code snippet\n" + //$NON-NLS-1$ " * that stores the result using setResult(Class, Object).\n" + //$NON-NLS-1$ " */\n" + //$NON-NLS-1$ "public void run() {\n" + //$NON-NLS-1$ "}\n" + //$NON-NLS-1$ "/**\n" + //$NON-NLS-1$ " * Stores the result type and value of the code snippet evaluation.\n" + //$NON-NLS-1$ " */\n" + //$NON-NLS-1$ "public void setResult(Object someResultValue, Class someResultType) {\n" + //$NON-NLS-1$ " this.resultValue = someResultValue;\n" + //$NON-NLS-1$ " this.resultType = someResultType;\n" + //$NON-NLS-1$ "}\n" + //$NON-NLS-1$ "}\n"; //$NON-NLS-1$ } /** * Returns the imports of this evaluation context. An import is the name of a package or the * fully qualified name of a type as defined in the import statement of a compilation unit. */ public char[][] getImports() { return this.imports; } /** * Returns the dot-separated name of the package code snippets are run into. Returns an empty * array for the default package. This is the default if the package name has never been set. */ public char[] getPackageName() { return this.packageName; } /** * Return the binary for the root code snippet class (ie. * org.eclipse.jdt.internal.eval.target.CodeSnippet). */ IBinaryType getRootCodeSnippetBinary() { if (this.codeSnippetBinary == null) { this.codeSnippetBinary= new CodeSnippetSkeleton(); } return this.codeSnippetBinary; } public char[] getVarClassName() { if (this.installedVars == null) return CharOperation.NO_CHAR; return CharOperation.concat(this.installedVars.packageName, this.installedVars.className, '.'); } /** * Creates a new global variable with the given name, type and initializer. If the variable is * not initialized, the initializer can be null. Note that this doesn't install it to this * evaluation context's VM. * * @see GlobalVariable */ public GlobalVariable newVariable(char[] typeName, char[] name, char[] initializer) { GlobalVariable var= new GlobalVariable(typeName, name, initializer); if (this.variableCount >= this.variables.length) // assume variables is never empty System.arraycopy(this.variables, 0, this.variables= new GlobalVariable[this.variableCount * 2], 0, this.variableCount); this.variables[this.variableCount++]= var; this.varsChanged= true; return var; } /** * Computes the selection at the specified positions of the given code snippet. (Note that this * evaluation context's VM doesn't need to be running.) * * @param codeSnippet char[] The code snipper source * * @param selectionSourceStart int * * @param selectionSourceEnd int * * @param environment org.eclipse.jdt.internal.core.SearchableEnvironment used to resolve * type/package references and search for types/packages based on partial names. * * @param requestor org.eclipse.jdt.internal.codeassist.ISelectionRequestor since the engine * might produce answers of various forms, the engine is associated with a requestor * able to accept all possible selections. * * @param options java.util.Map set of options used to configure the code assist engine. */ public void select( char[] codeSnippet, int selectionSourceStart, int selectionSourceEnd, SearchableEnvironment environment, ISelectionRequestor requestor, Map options, WorkingCopyOwner owner) { final char[] className= "CodeSnippetSelection".toCharArray(); //$NON-NLS-1$ final CodeSnippetToCuMapper mapper= new CodeSnippetToCuMapper( codeSnippet, this.packageName, this.imports, className, this.installedVars == null ? null : this.installedVars.className, this.localVariableNames, this.localVariableTypeNames, this.localVariableModifiers, this.declaringTypeName, this.lineSeparator ); ICompilationUnit sourceUnit= new ICompilationUnit() { public char[] getFileName() { return CharOperation.concat(className, Util.defaultJavaExtension().toCharArray()); } public char[] getContents() { return mapper.getCUSource(EvaluationContext.this.lineSeparator); } public char[] getMainTypeName() { return className; } public char[][] getPackageName() { return null; } }; SelectionEngine engine= new SelectionEngine(environment, mapper.getSelectionRequestor(requestor), options, owner); engine.select(sourceUnit, mapper.startPosOffset + selectionSourceStart, mapper.startPosOffset + selectionSourceEnd); } /** * Sets the imports of this evaluation context. An import is the name of a package or the fully * qualified name of a type as defined in the import statement of a compilation unit (see the * Java Language Specifications for more details). */ public void setImports(char[][] imports) { this.imports= imports; this.varsChanged= true; // this may change the visibility of the variable's types } /** * Sets the line separator used by this evaluation context. */ public void setLineSeparator(String lineSeparator) { this.lineSeparator= lineSeparator; } /** * Sets the dot-separated name of the package code snippets are ran into. The default package * name is an empty array. */ public void setPackageName(char[] packageName) { this.packageName= packageName; this.varsChanged= true; // this may change the visibility of the variable's types } }