KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > eval > ast > engine > EvaluationSourceGenerator


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.debug.eval.ast.engine;
12
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.Path;
19 import org.eclipse.core.runtime.Status;
20 import org.eclipse.debug.core.DebugException;
21 import org.eclipse.jdt.core.IClassFile;
22 import org.eclipse.jdt.core.ICompilationUnit;
23 import org.eclipse.jdt.core.IJavaElement;
24 import org.eclipse.jdt.core.IJavaProject;
25 import org.eclipse.jdt.core.JavaCore;
26 import org.eclipse.jdt.core.JavaModelException;
27 import org.eclipse.jdt.core.dom.AST;
28 import org.eclipse.jdt.core.dom.ASTParser;
29 import org.eclipse.jdt.core.dom.CompilationUnit;
30 import org.eclipse.jdt.debug.core.IJavaReferenceType;
31 import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
32 import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
33 import org.eclipse.jdt.internal.debug.core.model.JDIReferenceType;
34
35 import com.sun.jdi.AbsentInformationException;
36 import com.sun.jdi.Location;
37 import com.sun.jdi.ReferenceType;
38
39 /**
40  * Creates the source code necessary to evaluate a code snippet.
41  * The (simplified) structure of the source is as follows:
42  * [package <package name>;]
43  * [import <import name>;]*
44  * public class <code snippet class name> extends <global variable class name> {
45  * public void run() {
46  * <code snippet>
47  * }
48  * }
49  */

50 public class EvaluationSourceGenerator {
51
52     private String JavaDoc fCodeSnippet;
53     
54     private String JavaDoc[] fLocalVariableTypeNames;
55     private String JavaDoc[] fLocalVariableNames;
56         
57     
58     private String JavaDoc fSource;
59     private String JavaDoc fCompilationUnitName;
60     private int fSnippetStartPosition;
61     private int fRunMethodStartPosition;
62     private int fRunMethodLength;
63     
64     /**
65      * Rebuild source in presence of external local variables
66      */

67     public EvaluationSourceGenerator(String JavaDoc[] localVariableTypesNames, String JavaDoc[] localVariableNames, String JavaDoc codeSnippet) {
68         fLocalVariableTypeNames = localVariableTypesNames;
69         fLocalVariableNames = localVariableNames;
70         fCodeSnippet= getCompleteSnippet(codeSnippet);
71     }
72     
73     public EvaluationSourceGenerator(String JavaDoc codeSnippet) {
74         this(new String JavaDoc[0], new String JavaDoc[0], codeSnippet);
75     }
76
77     protected String JavaDoc getCompleteSnippet(String JavaDoc codeSnippet) {
78
79         if (isExpression(codeSnippet)) {
80             codeSnippet = "return " + codeSnippet + ';'; //$NON-NLS-1$
81
}
82         return codeSnippet;
83     }
84     
85     /**
86      * Returns whether the given snippet represents an expression.
87      * This is determined by examining the snippet for non-quoted semicolons.
88      *
89      * Returns <code>true</code> if the snippet is an expression, or
90      * <code>false</code> if the expresssion contains a statement.
91      */

92     protected boolean isExpression(String JavaDoc codeSnippet) {
93         boolean inString= false;
94         byte[] chars= codeSnippet.getBytes();
95         for (int i= 0, numChars= chars.length; i < numChars; i++) {
96             switch (chars[i]) {
97                 case '\\':
98                     if (inString) { // skip the char after an escape char
99
i++;
100                     }
101                     break;
102                 case '\"':
103                 case '\'':
104                     inString= !inString;
105                     break;
106                 case ';':
107                     if (!inString) {
108                         return false;
109                     }
110                     break;
111             }
112         }
113         return true;
114     }
115     
116     public String JavaDoc getCompilationUnitName() {
117         return fCompilationUnitName;
118     }
119     
120     public int getSnippetStart() {
121         return fSnippetStartPosition;
122     }
123     public int getRunMethodStart() {
124         return fRunMethodStartPosition;
125     }
126     public int getRunMethodLength() {
127         return fRunMethodLength;
128     }
129     protected void setSnippetStart(int position) {
130         fSnippetStartPosition= position;
131     }
132     protected void setRunMethodStart(int position) {
133         fRunMethodStartPosition= position;
134     }
135     protected void setRunMethodLength(int length) {
136         fRunMethodLength= length;
137     }
138     
139     public String JavaDoc getSnippet() {
140         return fCodeSnippet;
141     }
142
143     private void createEvaluationSourceFromSource(String JavaDoc source, String JavaDoc typeName, int position, boolean createInAStaticMethod, IJavaProject project) throws DebugException {
144         ASTParser parser = ASTParser.newParser(AST.JLS3);
145         parser.setSource(source.toCharArray());
146         Map JavaDoc options=JavaCore.getDefaultOptions();
147         options.put(JavaCore.COMPILER_COMPLIANCE, project.getOption(JavaCore.COMPILER_COMPLIANCE, true));
148         String JavaDoc sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
149         options.put(JavaCore.COMPILER_SOURCE, sourceLevel);
150         parser.setCompilerOptions(options);
151         CompilationUnit unit= (CompilationUnit)parser.createAST(null);
152         SourceBasedSourceGenerator visitor= new SourceBasedSourceGenerator(unit, typeName, position, createInAStaticMethod, fLocalVariableTypeNames, fLocalVariableNames, fCodeSnippet, sourceLevel);
153         unit.accept(visitor);
154         
155         if (visitor.hasError()) {
156             throw new DebugException(new Status(IStatus.ERROR, JDIDebugPlugin.getUniqueIdentifier(), IStatus.OK, visitor.getError(), null));
157         }
158         
159         String JavaDoc sourceRes= visitor.getSource();
160         if (sourceRes == null) {
161             return;
162         }
163         setSource(sourceRes);
164         setCompilationUnitName(visitor.getCompilationUnitName());
165         setSnippetStart(visitor.getSnippetStart());
166         setRunMethodStart(visitor.getRunMethodStart());
167         setRunMethodLength(visitor.getRunMethodLength());
168     }
169     
170     private void createEvaluationSourceFromJDIObject(BinaryBasedSourceGenerator objectToEvaluationSourceMapper) {
171         
172         setCompilationUnitName(objectToEvaluationSourceMapper.getCompilationUnitName());
173         setSnippetStart(objectToEvaluationSourceMapper.getSnippetStart());
174         setRunMethodStart(objectToEvaluationSourceMapper.getRunMethodStart());
175         setRunMethodLength(fCodeSnippet.length() + objectToEvaluationSourceMapper.getRunMethodLength());
176         setSource(objectToEvaluationSourceMapper.getSource().insert(objectToEvaluationSourceMapper.getCodeSnippetPosition(), fCodeSnippet).toString());
177     }
178     
179     private BinaryBasedSourceGenerator getInstanceSourceMapper(JDIReferenceType referenceType, boolean isInStaticMethod, IJavaProject project) {
180         String JavaDoc sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
181         BinaryBasedSourceGenerator objectToEvaluationSourceMapper = new BinaryBasedSourceGenerator(fLocalVariableTypeNames, fLocalVariableNames, isInStaticMethod, sourceLevel);
182         objectToEvaluationSourceMapper.buildSource(referenceType);
183         return objectToEvaluationSourceMapper;
184     }
185     
186     public String JavaDoc getSource(IJavaReferenceType type, IJavaProject javaProject, boolean isStatic) throws CoreException {
187         if (fSource == null) {
188             String JavaDoc baseSource= getTypeSourceFromProject(type, javaProject);
189             int lineNumber= getLineNumber((JDIReferenceType)type);
190             if (baseSource != null && lineNumber != -1) {
191                 createEvaluationSourceFromSource(baseSource, type.getName(), lineNumber, isStatic, javaProject);
192             }
193             if (fSource == null) {
194                 BinaryBasedSourceGenerator mapper= getInstanceSourceMapper((JDIReferenceType) type, isStatic, javaProject);
195                 createEvaluationSourceFromJDIObject(mapper);
196             }
197         }
198         return fSource;
199     }
200
201     private int getLineNumber(JDIReferenceType type) {
202         ReferenceType referenceType= (ReferenceType) type.getUnderlyingType();
203         try {
204             List JavaDoc allLineLocations = referenceType.allLineLocations();
205             if (!allLineLocations.isEmpty()) {
206                 return ((Location)allLineLocations.get(0)).lineNumber();
207             }
208         } catch (AbsentInformationException e) {
209         }
210         return -1;
211     }
212
213     protected void setCompilationUnitName(String JavaDoc name) {
214         fCompilationUnitName= name;
215     }
216     
217     protected void setSource(String JavaDoc source) {
218         fSource= source;
219     }
220
221     private String JavaDoc getTypeSourceFromProject(IJavaReferenceType type, IJavaProject javaProject) throws CoreException {
222         String JavaDoc[] sourcePaths = type.getSourcePaths(null);
223         IJavaElement element = null;
224         if (sourcePaths != null && sourcePaths.length > 0) {
225             element = javaProject.findElement(new Path(sourcePaths[0]));
226         } else {
227             // must guess at source name when debug attribute not present
228
element = JavaDebugUtils.findElement(type.getName(), javaProject);
229         }
230         return resolveSource(element);
231     }
232     
233     /**
234      * Returns source for the given class file or compilation unit
235      * or <code>null</code> if none.
236      *
237      * @param element Java element or <code>null</code>
238      */

239     private String JavaDoc resolveSource(IJavaElement element) throws DebugException {
240         String JavaDoc source= null;
241         try {
242             if (element instanceof IClassFile) {
243                 source = ((IClassFile)element).getSource();
244             } else if (element instanceof ICompilationUnit) {
245                 source = ((ICompilationUnit)element).getSource();
246             }
247         } catch (JavaModelException e) {
248             throw new DebugException(e.getStatus());
249         }
250         return source;
251     }
252
253 }
254
Popular Tags