KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > eval > CodeSnippetToCuMapper


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.eval;
12
13 import org.eclipse.jdt.core.CompletionContext;
14 import org.eclipse.jdt.core.CompletionProposal;
15 import org.eclipse.jdt.core.CompletionRequestor;
16 import org.eclipse.jdt.core.Flags;
17 import org.eclipse.jdt.core.Signature;
18 import org.eclipse.jdt.core.compiler.*;
19 import org.eclipse.jdt.core.compiler.IProblem;
20 import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
21
22 /**
23  * Maps back and forth a code snippet to a compilation unit.
24  * The structure of the compilation unit is as follows:
25  * [package <package name>;]
26  * [import <import name>;]*
27  * public class <code snippet class name> extends <global variable class name> {
28  * [<declaring type> val$this;]
29  * public void run() {
30  * <code snippet>
31  * }
32  * }
33  */

34 class CodeSnippetToCuMapper implements EvaluationConstants {
35     /**
36      * The generated compilation unit.
37      */

38     public char[] cuSource;
39     
40     /**
41      * Where the code snippet starts in the generated compilation unit.
42      */

43     public int lineNumberOffset = 0;
44     public int startPosOffset = 0;
45
46     // Internal fields
47
char[] codeSnippet;
48     char[] snippetPackageName;
49     char[][] snippetImports;
50     char[] snippetClassName;
51     char[] snippetVarClassName;
52     char[] snippetDeclaringTypeName;
53
54     // Mapping of external local variables
55
char[][] localVarNames;
56     char[][] localVarTypeNames;
57     int[] localVarModifiers;
58     
59 /**
60  * Rebuild source in presence of external local variables
61  */

62  public CodeSnippetToCuMapper(char[] codeSnippet, char[] packageName, char[][] imports, char[] className, char[] varClassName, char[][] localVarNames, char[][] localVarTypeNames, int[] localVarModifiers, char[] declaringTypeName, String JavaDoc lineSeparator) {
63     this.codeSnippet = codeSnippet;
64     this.snippetPackageName = packageName;
65     this.snippetImports = imports;
66     this.snippetClassName = className;
67     this.snippetVarClassName = varClassName;
68     this.localVarNames = localVarNames;
69     this.localVarTypeNames = localVarTypeNames;
70     this.localVarModifiers = localVarModifiers;
71     this.snippetDeclaringTypeName = declaringTypeName;
72     this.buildCUSource(lineSeparator);
73 }
74 private void buildCUSource(String JavaDoc lineSeparator) {
75     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
76
77     // package declaration
78
if (this.snippetPackageName != null && this.snippetPackageName.length != 0) {
79         buffer.append("package "); //$NON-NLS-1$
80
buffer.append(this.snippetPackageName);
81         buffer.append(";").append(lineSeparator); //$NON-NLS-1$
82
this.lineNumberOffset++;
83     }
84
85     // import declarations
86
char[][] imports = this.snippetImports;
87     for (int i = 0; i < imports.length; i++) {
88         buffer.append("import "); //$NON-NLS-1$
89
buffer.append(imports[i]);
90         buffer.append(';').append(lineSeparator);
91         this.lineNumberOffset++;
92     }
93
94     // class declaration
95
buffer.append("public class "); //$NON-NLS-1$
96
buffer.append(this.snippetClassName);
97
98     // super class is either a global variable class or the CodeSnippet class
99
if (this.snippetVarClassName != null) {
100         buffer.append(" extends "); //$NON-NLS-1$
101
buffer.append(this.snippetVarClassName);
102     } else {
103         buffer.append(" extends "); //$NON-NLS-1$
104
buffer.append(PACKAGE_NAME);
105         buffer.append("."); //$NON-NLS-1$
106
buffer.append(ROOT_CLASS_NAME);
107     }
108     buffer.append(" {").append(lineSeparator); //$NON-NLS-1$
109
this.lineNumberOffset++;
110
111     if (this.snippetDeclaringTypeName != null){
112         buffer.append(" "); //$NON-NLS-1$
113
buffer.append(this.snippetDeclaringTypeName);
114         buffer.append(" "); //$NON-NLS-1$
115
buffer.append(DELEGATE_THIS); // val$this
116
buffer.append(';').append(lineSeparator);
117         this.lineNumberOffset++;
118     }
119     // add some storage location for local variable persisted state
120
if (this.localVarNames != null) {
121         for (int i = 0, max = this.localVarNames.length; i < max; i++) {
122             buffer.append(" "); //$NON-NLS-1$
123
buffer.append(this.localVarTypeNames[i]);
124             buffer.append(" "); //$NON-NLS-1$
125
buffer.append(LOCAL_VAR_PREFIX); // val$...
126
buffer.append(this.localVarNames[i]);
127             buffer.append(';').append(lineSeparator);
128             this.lineNumberOffset++;
129         }
130     }
131     // run() method declaration
132
buffer.append("public void run() throws Throwable {").append(lineSeparator); //$NON-NLS-1$
133
this.lineNumberOffset++;
134     this.startPosOffset = buffer.length();
135     buffer.append(this.codeSnippet);
136     // a line separator is required after the code snippet source code
137
// in case the code snippet source code ends with a line comment
138
// http://dev.eclipse.org/bugs/show_bug.cgi?id=14838
139
buffer.append(lineSeparator).append('}').append(lineSeparator);
140
141     // end of class declaration
142
buffer.append('}').append(lineSeparator);
143
144     // store result
145
int length = buffer.length();
146     this.cuSource = new char[length];
147     buffer.getChars(0, length, this.cuSource, 0);
148 }
149 /**
150  * Returns a completion requestor that wraps the given requestor and shift the results
151  * according to the start offset and line number offset of the code snippet in the generated compilation unit.
152  */

153 public CompletionRequestor getCompletionRequestor(final CompletionRequestor originalRequestor) {
154     return new CompletionRequestor() {
155         public void accept(CompletionProposal proposal) {
156             switch(proposal.getKind()) {
157                 case CompletionProposal.TYPE_REF:
158                     int flags = proposal.getFlags();
159                     if((flags & Flags.AccEnum) == 0 &&
160                             (flags & Flags.AccInterface) == 0) {
161                         // Remove completion on generated class name or generated global variable class name
162
char[] packageName = proposal.getDeclarationSignature();
163                         char[] className = Signature.getSignatureSimpleName(proposal.getSignature());
164                         if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.snippetPackageName)
165                                 && (CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetClassName)
166                                     || CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetVarClassName))) return;
167                         
168                         if (CharOperation.equals(packageName, PACKAGE_NAME)
169                                 && CharOperation.equals(className, ROOT_CLASS_NAME)) return;
170                     }
171                     break;
172                 case CompletionProposal.METHOD_REF:
173                 case CompletionProposal.METHOD_DECLARATION:
174                     // Remove completion on generated method
175
char[] declaringTypePackageName = Signature.getSignatureQualifier(proposal.getDeclarationSignature());
176                     char[] declaringTypeName = Signature.getSignatureSimpleName(proposal.getDeclarationSignature());
177                     
178                     if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.snippetPackageName)
179                             && CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.snippetClassName)) return;
180                     
181                     if (CharOperation.equals(declaringTypePackageName, PACKAGE_NAME)
182                             && CharOperation.equals(declaringTypeName, ROOT_CLASS_NAME)) return;
183                     break;
184             }
185             originalRequestor.accept(proposal);
186         }
187         
188         public void completionFailure(IProblem problem) {
189             problem.setSourceStart(problem.getSourceStart() - CodeSnippetToCuMapper.this.startPosOffset);
190             problem.setSourceEnd(problem.getSourceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
191             problem.setSourceLineNumber(problem.getSourceLineNumber() - CodeSnippetToCuMapper.this.lineNumberOffset);
192             originalRequestor.completionFailure(problem);
193         }
194         
195         public void acceptContext(CompletionContext context) {
196             originalRequestor.acceptContext(context);
197         }
198         
199         public void beginReporting() {
200             originalRequestor.beginReporting();
201         }
202         
203         public void endReporting() {
204             originalRequestor.endReporting();
205         }
206         
207         public boolean isIgnored(int completionProposalKind) {
208             return originalRequestor.isIgnored(completionProposalKind);
209         }
210         
211         public void setIgnored(int completionProposalKind, boolean ignore) {
212             originalRequestor.setIgnored(completionProposalKind, ignore);
213         }
214         
215         public boolean isAllowingRequiredProposals(int mainKind, int requiredKind) {
216             return originalRequestor.isAllowingRequiredProposals(mainKind, requiredKind);
217         }
218
219         public void setAllowsRequiredProposals(int mainKind, int requiredKind, boolean allow) {
220             originalRequestor.setAllowsRequiredProposals(mainKind, requiredKind, allow);
221         }
222     };
223 }
224 public char[] getCUSource(String JavaDoc lineSeparator) {
225     if (this.cuSource == null) {
226         buildCUSource(lineSeparator);
227     }
228     return this.cuSource;
229 }
230 /**
231  * Returns the type of evaluation that corresponds to the given line number in the generated compilation unit.
232  */

233 public int getEvaluationType(int lineNumber) {
234     int currentLine = 1;
235
236     // check package declaration
237
if (this.snippetPackageName != null && this.snippetPackageName.length != 0) {
238         if (lineNumber == 1) {
239             return EvaluationResult.T_PACKAGE;
240         }
241         currentLine++;
242     }
243
244     // check imports
245
char[][] imports = this.snippetImports;
246     if ((currentLine <= lineNumber) && (lineNumber < (currentLine + imports.length))) {
247         return EvaluationResult.T_IMPORT;
248     }
249     currentLine += imports.length + 1; // + 1 to skip the class declaration line
250

251     // check generated fields
252
currentLine +=
253         (this.snippetDeclaringTypeName == null ? 0 : 1)
254         + (this.localVarNames == null ? 0 : this.localVarNames.length);
255     if (currentLine > lineNumber) {
256         return EvaluationResult.T_INTERNAL;
257     }
258     currentLine ++; // + 1 to skip the method declaration line
259

260     // check code snippet
261
if (currentLine >= this.lineNumberOffset) {
262         return EvaluationResult.T_CODE_SNIPPET;
263     }
264
265     // default
266
return EvaluationResult.T_INTERNAL;
267 }
268 /**
269  * Returns the import defined at the given line number.
270  */

271 public char[] getImport(int lineNumber) {
272     int importStartLine = this.lineNumberOffset - 1 - this.snippetImports.length;
273     return this.snippetImports[lineNumber - importStartLine];
274 }
275 /**
276  * Returns a selection requestor that wraps the given requestor and shift the problems
277  * according to the start offset and line number offset of the code snippet in the generated compilation unit.
278  */

279 public ISelectionRequestor getSelectionRequestor(final ISelectionRequestor originalRequestor) {
280     return new ISelectionRequestor() {
281         public void acceptType(char[] packageName, char[] typeName, int modifiers, boolean isDeclaration, char[] uniqueKey, int start, int end) {
282             originalRequestor.acceptType(packageName, typeName, modifiers, isDeclaration, uniqueKey, start, end);
283         }
284         public void acceptError(CategorizedProblem error) {
285             error.setSourceLineNumber(error.getSourceLineNumber() - CodeSnippetToCuMapper.this.lineNumberOffset);
286             error.setSourceStart(error.getSourceStart() - CodeSnippetToCuMapper.this.startPosOffset);
287             error.setSourceEnd(error.getSourceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
288             originalRequestor.acceptError(error);
289         }
290         public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, boolean isDeclaration, char[] uniqueKey, int start, int end) {
291             originalRequestor.acceptField(declaringTypePackageName, declaringTypeName, name, isDeclaration, uniqueKey, start, end);
292         }
293         public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String JavaDoc enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String JavaDoc[] parameterSignatures, char[][] typeParameterNames, char[][][] typeParameterBoundNames, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
294             originalRequestor.acceptMethod(declaringTypePackageName, declaringTypeName, enclosingDeclaringTypeSignature, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, typeParameterNames, typeParameterBoundNames, isConstructor, isDeclaration, uniqueKey, start, end);
295         }
296         public void acceptPackage(char[] packageName) {
297             originalRequestor.acceptPackage(packageName);
298         }
299         
300         public void acceptTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] typeParameterName, boolean isDeclaration, int start, int end) {
301             originalRequestor.acceptTypeParameter(declaringTypePackageName, declaringTypeName, typeParameterName, isDeclaration, start, end);
302         }
303         public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selectorEnd, char[] typeParameterName,boolean isDeclaration, int start, int end) {
304             originalRequestor.acceptMethodTypeParameter(declaringTypePackageName, declaringTypeName, selector, selectorStart, selectorEnd, typeParameterName, isDeclaration, start, end);
305         }
306     };
307 }
308 }
309
Popular Tags