1 /*******************************************************************************
2 * This program and the accompanying materials
3 * are made available under the terms of the Eclipse Public License v1.0
4 * which accompanies this distribution, and is available at
5 * http://www.eclipse.org/legal/epl-v10.html.
7 * This file is a derivative of code released by the University of
8 * California under the terms listed below.
10 * Refinement Analysis Tools is Copyright ©2007 The Regents of the
11 * University of California (Regents). Provided that this notice and
12 * the following two paragraphs are included in any distribution of
13 * Refinement Analysis Tools or its derivative work, Regents agrees
14 * not to assert any of Regents' copyright rights in Refinement
15 * Analysis Tools against recipient for recipients reproduction,
16 * preparation of derivative works, public display, public
17 * performance, distribution or sublicensing of Refinement Analysis
18 * Tools and derivative works, in source code and object code form.
19 * This agreement not to assert does not confer, by implication,
20 * estoppel, or otherwise any license or rights in any intellectual
21 * property of Regents, including, but not limited to, any patents
22 * of Regents or Regents employees.
24 * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
25 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
26 * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
27 * AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 * FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
33 * WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
34 * DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
35 * IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
36 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
38 package edu
.berkeley
.cs
.bodik
.svelte
.plugin
;
40 import org
.eclipse
.core
.resources
.IFile
;
41 import org
.eclipse
.core
.resources
.IWorkspace
;
42 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
43 import org
.eclipse
.core
.runtime
.IPath
;
44 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
45 import org
.eclipse
.core
.runtime
.IStatus
;
46 import org
.eclipse
.core
.runtime
.Path
;
47 import org
.eclipse
.core
.runtime
.Status
;
48 import org
.eclipse
.jdt
.core
.ICompilationUnit
;
49 import org
.eclipse
.jdt
.core
.IMethod
;
50 import org
.eclipse
.jdt
.core
.Signature
;
51 import org
.eclipse
.jdt
.core
.dom
.AST
;
52 import org
.eclipse
.jdt
.core
.dom
.ASTNode
;
53 import org
.eclipse
.jdt
.internal
.corext
.dom
.NodeFinder
;
54 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
55 import org
.eclipse
.jface
.text
.BadLocationException
;
56 import org
.eclipse
.jface
.text
.IDocument
;
57 import org
.eclipse
.ui
.IEditorDescriptor
;
58 import org
.eclipse
.ui
.IEditorInput
;
59 import org
.eclipse
.ui
.IEditorPart
;
60 import org
.eclipse
.ui
.IEditorRegistry
;
61 import org
.eclipse
.ui
.IWorkbenchPage
;
62 import org
.eclipse
.ui
.IWorkbenchWindow
;
63 import org
.eclipse
.ui
.PartInitException
;
64 import org
.eclipse
.ui
.PlatformUI
;
65 import org
.eclipse
.ui
.internal
.WorkbenchPlugin
;
66 import org
.eclipse
.ui
.internal
.dialogs
.DialogUtil
;
67 import org
.eclipse
.ui
.part
.FileEditorInput
;
68 import org
.eclipse
.ui
.progress
.UIJob
;
69 import org
.eclipse
.ui
.texteditor
.AbstractTextEditor
;
70 import org
.eclipse
.ui
.texteditor
.IDocumentProvider
;
72 import com
.ibm
.wala
.ipa
.callgraph
.CGNode
;
73 import com
.ibm
.wala
.ipa
.slicer
.NormalReturnCallee
;
74 import com
.ibm
.wala
.ipa
.slicer
.NormalStatement
;
75 import com
.ibm
.wala
.ipa
.slicer
.ParamCallee
;
76 import com
.ibm
.wala
.ipa
.slicer
.Statement
;
78 import edu
.berkeley
.cs
.bodik
.svelte
.CGNodeUtils
;
79 import edu
.berkeley
.cs
.bodik
.svelte
.SourcePosition
;
80 import edu
.berkeley
.cs
.bodik
.svelte
.StatementUtils
;
83 * Should probably move some of this to SliceEnvironment.
88 public class EclipseUtils
{
90 public static IFile
findIFileForFilename(String filename
) {
91 if (filename
!= null) {
92 IWorkspace workspace
= ResourcesPlugin
.getWorkspace();
93 IPath location
= Path
.fromOSString(filename
);
94 IFile f
= workspace
.getRoot().getFileForLocation(location
);
100 public static class MethodSignature
{
101 private String packageName
;
102 private String className
;
103 private String methodName
;
104 private String methodParams
;
105 private String methodReturnValue
;
107 public MethodSignature(String signature
) {
108 // find it and go to it!
109 int class_met_boundary
= signature
.lastIndexOf('.');
111 String pkg_and_classname
= signature
.substring(0, class_met_boundary
);
112 String method_signature
= signature
.substring(class_met_boundary
+ 1);
114 int pkg_class_boundary
= pkg_and_classname
.lastIndexOf('.');
116 // TODO: if in default package?
117 if (pkg_class_boundary
== -1) {
118 this.packageName
= null;
119 this.className
= pkg_and_classname
;
121 this.packageName
= pkg_and_classname
.substring(0, pkg_class_boundary
);
122 this.className
= pkg_and_classname
.substring(pkg_class_boundary
+ 1);
125 int met_param_boundary
= method_signature
.indexOf('(');
126 int param_ret_boundary
= method_signature
.indexOf(')');
128 this.methodName
= method_signature
.substring(0, met_param_boundary
);
129 if (this.methodName
.equals("<init>"))
130 this.methodName
= this.className
;
131 this.methodParams
= method_signature
.substring(met_param_boundary
+ 1,
133 this.methodReturnValue
= method_signature
.substring(param_ret_boundary
+ 1);
136 public String
getPackageName() {
140 public String
getClassName() {
144 public String
getMethodSignature() {
145 return methodName
+ '(' + methodParams
+ ')' + methodReturnValue
;
148 public String
getQualifiedClassName() {
149 if (packageName
== null)
151 return packageName
+ "." + className
;
154 public String
getSignature() {
155 return getQualifiedClassName() + "." + getMethodSignature();
158 public String
[] getUnqualifiedParameterTypes() {
159 return Signature
.getParameterTypes(getMethodSignature().replace('/', '.').replaceAll(
160 "L[^;]*\\.([^;\\.]*);", "Q$1;")); // java/lang/String -> QString
163 public String
getMethodName() {
167 public boolean matchesMethod(IMethod m
) {
168 String paramTypes
[] = m
.getParameterTypes();
169 for ( int i
= 0; i
< paramTypes
.length
; i
++ )
170 paramTypes
[i
] = paramTypes
[i
].replaceAll("L[^;]*\\.([^;\\.]*);", "Q$1;");
171 if ( getUnqualifiedParameterTypes().equals(paramTypes
) )
177 public static void openFile(IFile file
) {
178 // get default editor descriptor
179 IEditorRegistry editorRegistry
= WorkbenchPlugin
.getDefault().getEditorRegistry();
180 IEditorDescriptor defaultEditorDescriptor
= editorRegistry
181 .getDefaultEditor(file
.toString());
182 // // || defaultEditorDescriptor.isOpenExternal() is only eclipse 3.x!!!
183 if (defaultEditorDescriptor
== null) {
184 defaultEditorDescriptor
= editorRegistry
.getDefaultEditor("dummy.txt");
187 // Open new file in editor
188 IWorkbenchWindow dw
= PlatformUI
.getWorkbench().getActiveWorkbenchWindow();
189 FileEditorInput fileEditorInput
= new FileEditorInput(file
);
191 IWorkbenchPage page
= dw
.getActivePage();
193 // page.openEditor(fileEditorInput,"org.eclipse.ui.DefaultTextEditor");
194 page
.openEditor(fileEditorInput
, defaultEditorDescriptor
.getId());
195 } catch (PartInitException e
) {
196 DialogUtil
.openError(dw
.getShell(), "Could not open new file", e
.getMessage(), e
);
202 * Uses the Slice Environment's project to look for the file.
204 * Passing a ParamCallee statement will highlight the line of the function definition.
208 public static void gotoStatement(Statement ss
) {
212 if (ss
instanceof ParamCallee
) {
213 ParamCallee pac
= (ParamCallee
) ss
;
214 CGNode node
= ((ParamCallee
) ss
).getNode();
216 int arg_index
= pac
.getValueNumber() - 1;
217 if (!node
.getMethod().isStatic())
220 EclipseJdtUtils
.gotoNodeParam(node
.getMethod().getSignature().toString(), arg_index
,
221 EclipseJdtUtils
.getJavaProjectFromProject(SliceEnvironment
.env().getProject()));
222 } else if (ss
instanceof NormalReturnCallee
) {
223 CGNode node
= ((NormalReturnCallee
) ss
).getNode();
224 EclipseJdtUtils
.gotoNode(node
.getMethod().getSignature().toString(), EclipseJdtUtils
.getJavaProjectFromProject(SliceEnvironment
.env().getProject()));
225 } else if (!(ss
instanceof NormalStatement
)) {
226 ss
= StatementUtils
.getCallerStatement(ss
);
229 if (ss
!= null && ss
instanceof NormalStatement
) {
230 SourcePosition sp
= CGNodeUtils
.getSourcePositionOfInstructionIndex(ss
.getNode(),
231 ((NormalStatement
) ss
).getInstructionIndex(), EclipseJdtUtils
232 .getJavaProjectFromOpenEditor());
234 if (sp
.filename
== null)
236 IFile f
= EclipseUtils
.findIFileForFilename(sp
.filename
);
238 EclipseUtils
.openFile(f
);
240 IEditorPart iep
= PlatformUI
.getWorkbench().getActiveWorkbenchWindow()
241 .getActivePage().getActiveEditor();
242 AbstractTextEditor e
= (AbstractTextEditor
) iep
;
244 if ( sp
.offsetStart
== -1 ) {
245 // Shrike: line numbers only.
246 IDocumentProvider prov
= ((AbstractTextEditor
) iep
).getDocumentProvider();
247 IEditorInput input
= iep
.getEditorInput();
248 IDocument document
= prov
.getDocument(input
);
250 int start
= document
.getLineOffset(sp
.lineStart
-1); // line numbers off by one.
251 int end
= document
.getLineOffset(sp
.lineEnd
-1)+document
.getLineLength(sp
.lineEnd
-1)-1;
252 e
.selectAndReveal(start
,end
-start
);
253 } catch (BadLocationException e1
) {
256 e
.selectAndReveal(sp
.offsetStart
, sp
.offsetEnd
- sp
.offsetStart
);
264 @SuppressWarnings("deprecation")
265 public static ASTNode
getRootNode(ICompilationUnit cu
) {
266 ASTNode root
= AST
.parseCompilationUnit(cu
, false);
270 @SuppressWarnings("deprecation")
271 public static ASTNode
getRootNodeWithBindings(ICompilationUnit cu
) {
272 ASTNode root
= AST
.parseCompilationUnit(cu
, true);
276 public static ASTNode
getCoveringNode(ASTNode root
, int offset
, int length
) {
277 NodeFinder nf
= new NodeFinder(offset
, length
);
279 ASTNode selected
= nf
.getCoveringNode();
283 public static void errorMsgInUIThread(final String title
, final String msg
) {
284 new UIJob("errormessage") {
286 public IStatus
runInUIThread(IProgressMonitor monitor
) {
289 PlatformUI
.getWorkbench().getActiveWorkbenchWindow()
293 return new Status(IStatus
.OK
, SveltePlugin
.PLUGIN_ID
, null);