001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.gsfret.editor.semantic;
042:
043: import java.util.ArrayList;
044: import java.util.Collection;
045: import java.util.Collections;
046: import java.util.EnumSet;
047: import java.util.HashMap;
048: import java.util.HashSet;
049: import java.util.List;
050: import java.util.Map;
051: import java.util.Set;
052: import java.util.Stack;
053: import javax.swing.text.Document;
054: import org.netbeans.napi.gsfret.source.CompilationInfo;
055: import org.netbeans.modules.editor.highlights.spi.Highlight;
056:
057: /**
058: * This file is originally from Retouche, the Java Support
059: * infrastructure in NetBeans. I have modified the file as little
060: * as possible to make merging Retouche fixes back as simple as
061: * possible.
062: *
063: *
064: * @author Jan Lahoda
065: */
066: public class MethodExitDetector { // extends CancellableTreePathScanner<Boolean, Stack<Tree>> {
067:
068: /** Creates a new instance of MethodExitDetector */
069: public MethodExitDetector() {
070: }
071:
072: private CompilationInfo info;
073:
074: // private Document doc;
075: // private Set<Highlight> highlights;
076: // private Collection<TypeMirror> exceptions;
077: // private Stack<Map<TypeMirror, List<Highlight>>> exceptions2HighlightsStack;
078:
079: public Set<Highlight> process(CompilationInfo info,
080: Document document/*, MethodTree methoddecl, Collection<Tree> excs*/) {
081: this .info = info;
082: System.err.println("MethodExitDetecter is Lobotomized");
083: // this.doc = document;
084: // this.highlights = new HashSet<Highlight>();
085: // this.exceptions2HighlightsStack = new Stack<Map<TypeMirror, List<Highlight>>>();
086: // this.exceptions2HighlightsStack.push(null);
087: //
088: // try {
089: Set<Highlight> result = new HashSet<Highlight>();
090: //
091: // CompilationUnitTree cu = info.getCompilationUnit();
092: //
093: // Boolean wasReturn = scan(TreePath.getPath(cu, methoddecl), null);
094: //
095: // if (isCanceled())
096: // return Collections.emptySet();
097: //
098: // if (excs == null) {
099: // //"return" exit point only if not searching for exceptions:
100: // result.addAll(highlights);
101: //
102: // if (wasReturn != Boolean.TRUE) {
103: // int lastBracket = Utilities.findLastBracket(methoddecl, cu, info.getTrees().getSourcePositions(), document);
104: //
105: // if (lastBracket != (-1)) {
106: // //highlight the "fall over" exitpoint:
107: // result.add(Utilities.createHighlight(cu, info.getTrees().getSourcePositions(), document, lastBracket, lastBracket + 1, EnumSet.of(ColoringAttributes.MARK_OCCURRENCES), MarkOccurencesHighlighter.ES_COLOR));
108: // }
109: // }
110: // }
111: //
112: // List<TypeMirror> exceptions = null;
113: //
114: // if (excs != null) {
115: // exceptions = new ArrayList<TypeMirror>();
116: //
117: // for (Tree t : excs) {
118: // if (isCanceled())
119: // return Collections.emptySet();
120: //
121: // TypeMirror m = info.getTrees().getTypeMirror(TreePath.getPath(cu, t));
122: //
123: // if (m != null) {
124: // exceptions.add(m);
125: // }
126: // }
127: // }
128: //
129: // Types t = info.getTypes();
130: //
131: // assert exceptions2HighlightsStack.size() == 1 : exceptions2HighlightsStack.size();
132: //
133: // Map<TypeMirror, List<Highlight>> exceptions2Highlights = exceptions2HighlightsStack.peek();
134: //
135: // //exceptions2Highlights may be null if the method is empty (or not finished, like "public void")
136: // //see ExitPointsEmptyMethod and ExitPointsStartedMethod tests:
137: // if (exceptions2Highlights != null) {
138: // for (TypeMirror type1 : exceptions2Highlights.keySet()) {
139: // if (isCanceled())
140: // return Collections.emptySet();
141: //
142: // boolean add = true;
143: //
144: // if (exceptions != null) {
145: // add = false;
146: //
147: // for (TypeMirror type2 : exceptions) {
148: // add |= t.isAssignable(type1, type2);
149: // }
150: // }
151: //
152: // if (add) {
153: // result.addAll(exceptions2Highlights.get(type1));
154: // }
155: // }
156: // }
157: //
158: return result;
159: // } finally {
160: // //clean-up:
161: // this.info = null;
162: // this.doc = null;
163: // this.highlights = null;
164: // this.exceptions2HighlightsStack = null;
165: // }
166: }
167:
168: // private void addToExceptionsMap(TypeMirror key, Highlight value) {
169: // if (value == null)
170: // return ;
171: //
172: // Map<TypeMirror, List<Highlight>> map = exceptions2HighlightsStack.peek();
173: //
174: // if (map == null) {
175: // map = new HashMap<TypeMirror, List<Highlight>>();
176: // exceptions2HighlightsStack.pop();
177: // exceptions2HighlightsStack.push(map);
178: // }
179: //
180: // List<Highlight> l = map.get(key);
181: //
182: // if (l == null) {
183: // map.put(key, l = new ArrayList<Highlight>());
184: // }
185: //
186: // l.add(value);
187: // }
188: //
189: // private void doPopup() {
190: // Map<TypeMirror, List<Highlight>> top = exceptions2HighlightsStack.pop();
191: //
192: // if (top == null)
193: // return ;
194: //
195: // Map<TypeMirror, List<Highlight>> result = exceptions2HighlightsStack.pop();
196: //
197: // if (result == null) {
198: // exceptions2HighlightsStack.push(top);
199: // return ;
200: // }
201: //
202: // for (TypeMirror key : top.keySet()) {
203: // List<Highlight> topKey = top.get(key);
204: // List<Highlight> resultKey = result.get(key);
205: //
206: // if (topKey == null)
207: // continue;
208: //
209: // if (resultKey == null) {
210: // result.put(key, topKey);
211: // continue;
212: // }
213: //
214: // resultKey.addAll(topKey);
215: // }
216: //
217: // exceptions2HighlightsStack.push(result);
218: // }
219: //
220: // private Highlight createHighlight(TreePath tree) {
221: // return Utilities.createHighlight(info.getCompilationUnit(), info.getTrees().getSourcePositions(), doc, tree, EnumSet.of(ColoringAttributes.MARK_OCCURRENCES), MarkOccurencesHighlighter.ES_COLOR);
222: // }
223: //
224: // @Override
225: // public Boolean visitTry(TryTree tree, Stack<Tree> d) {
226: // exceptions2HighlightsStack.push(null);
227: //
228: // Boolean returnInTryBlock = scan(tree.getBlock(), d);
229: //
230: // boolean returnInCatchBlock = true;
231: //
232: // for (Tree t : tree.getCatches()) {
233: // Boolean b = scan(t, d);
234: //
235: // returnInCatchBlock &= b == Boolean.TRUE;
236: // }
237: //
238: // Boolean returnInFinallyBlock = scan(tree.getFinallyBlock(), d);
239: //
240: // doPopup();
241: //
242: // if (returnInTryBlock == Boolean.TRUE && returnInCatchBlock)
243: // return Boolean.TRUE;
244: //
245: // return returnInFinallyBlock;
246: // }
247: //
248: // @Override
249: // public Boolean visitReturn(ReturnTree tree, Stack<Tree> d) {
250: // if (exceptions == null) {
251: // Highlight h = createHighlight(getCurrentPath());
252: //
253: // if (h != null) {
254: // highlights.add(h);
255: // }
256: // }
257: //
258: // super.visitReturn(tree, d);
259: // return Boolean.TRUE;
260: // }
261: //
262: // @Override
263: // public Boolean visitCatch(CatchTree tree, Stack<Tree> d) {
264: // TypeMirror type1 = info.getTrees().getTypeMirror(new TreePath(new TreePath(getCurrentPath(), tree.getParameter()), tree.getParameter().getType()));
265: // Types t = info.getTypes();
266: //
267: // if (type1 != null) {
268: // Set<TypeMirror> toRemove = new HashSet<TypeMirror>();
269: // Map<TypeMirror, List<Highlight>> exceptions2Highlights = exceptions2HighlightsStack.peek();
270: //
271: // if (exceptions2Highlights != null) {
272: // for (TypeMirror type2 : exceptions2Highlights.keySet()) {
273: // if (t.isAssignable(type2, type1)) {
274: // toRemove.add(type2);
275: // }
276: // }
277: //
278: // for (TypeMirror type : toRemove) {
279: // exceptions2Highlights.remove(type);
280: // }
281: // }
282: //
283: // }
284: //
285: // scan(tree.getParameter(), d);
286: // return scan(tree.getBlock(), d);
287: // }
288: //
289: // @Override
290: // public Boolean visitMethodInvocation(MethodInvocationTree tree, Stack<Tree> d) {
291: // Element el = info.getTrees().getElement(new TreePath(getCurrentPath(), tree.getMethodSelect()));
292: //
293: // if (el == null) {
294: // System.err.println("Warning: decl == null");
295: // System.err.println("tree=" + tree);
296: // }
297: //
298: // if (el != null && el.getKind() == ElementKind.METHOD) {
299: // for (TypeMirror m : ((ExecutableElement) el).getThrownTypes()) {
300: // addToExceptionsMap(m, createHighlight(getCurrentPath()));
301: // }
302: // }
303: //
304: // super.visitMethodInvocation(tree, d);
305: // return null;
306: // }
307: //
308: // @Override
309: // public Boolean visitThrow(ThrowTree tree, Stack<Tree> d) {
310: // addToExceptionsMap(info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), tree.getExpression())), createHighlight(getCurrentPath()));
311: //
312: // super.visitThrow(tree, d);
313: //
314: // return Boolean.TRUE;
315: // }
316: //
317: // @Override
318: // public Boolean visitNewClass(NewClassTree tree, Stack<Tree> d) {
319: // Element el = info.getTrees().getElement(getCurrentPath());
320: //
321: // if (el != null && el.getKind() == ElementKind.CONSTRUCTOR) {
322: // for (TypeMirror m : ((ExecutableElement) el).getThrownTypes()) {
323: // addToExceptionsMap(m, createHighlight(getCurrentPath()));
324: // }
325: // }
326: //
327: // super.visitNewClass(tree, d);
328: // return null;
329: // }
330: //
331: // @Override
332: // public Boolean visitMethod(MethodTree node, Stack<Tree> p) {
333: // scan(node.getModifiers(), p);
334: // scan(node.getReturnType(), p);
335: // scan(node.getTypeParameters(), p);
336: // scan(node.getParameters(), p);
337: // scan(node.getThrows(), p);
338: // return scan(node.getBody(), p);
339: // }
340: //
341: // @Override
342: // public Boolean visitIf(IfTree node, Stack<Tree> p) {
343: // scan(node.getCondition(), p);
344: // Boolean thenResult = scan(node.getThenStatement(), p);
345: // Boolean elseResult = scan(node.getElseStatement(), p);
346: //
347: // if (thenResult == Boolean.TRUE && elseResult == Boolean.TRUE)
348: // return Boolean.TRUE;
349: //
350: // return null;
351: // }
352:
353: }
|