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.refactoring.java;
042:
043: import com.sun.source.tree.*;
044: import com.sun.source.util.SourcePositions;
045: import com.sun.source.util.TreePath;
046: import com.sun.source.util.Trees;
047: import java.io.IOException;
048: import javax.lang.model.element.Element;
049: import javax.lang.model.element.ElementKind;
050: import javax.swing.text.Position.Bias;
051: import org.netbeans.api.java.source.CompilationInfo;
052: import org.netbeans.api.java.source.TreeUtilities;
053: import org.netbeans.modules.refactoring.java.plugins.JavaWhereUsedQueryPlugin;
054: import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
055: import org.netbeans.modules.refactoring.java.ui.tree.ElementGripFactory;
056: import org.openide.ErrorManager;
057: import org.openide.filesystems.FileObject;
058: import org.openide.text.PositionBounds;
059: import org.openide.loaders.DataObject;
060: import org.openide.loaders.DataObjectNotFoundException;
061: import org.openide.text.CloneableEditorSupport;
062: import org.openide.text.PositionRef;
063: import org.openide.util.Lookup;
064: import org.openide.util.lookup.Lookups;
065:
066: public class WhereUsedElement extends
067: SimpleRefactoringElementImplementation {
068: private PositionBounds bounds;
069: private String displayText;
070: private FileObject parentFile;
071:
072: public WhereUsedElement(PositionBounds bounds, String displayText,
073: FileObject parentFile, TreePath tp, CompilationInfo info) {
074: this .bounds = bounds;
075: this .displayText = displayText;
076: this .parentFile = parentFile;
077: if (tp != null)
078: ElementGripFactory.getDefault().put(parentFile, tp, info);
079: }
080:
081: public String getDisplayText() {
082: return displayText;
083: }
084:
085: public Lookup getLookup() {
086: Object composite = ElementGripFactory.getDefault().get(
087: parentFile, bounds.getBegin().getOffset());
088: if (composite == null)
089: composite = parentFile;
090: return Lookups.singleton(composite);
091: }
092:
093: public PositionBounds getPosition() {
094: return bounds;
095: }
096:
097: public String getText() {
098: return displayText;
099: }
100:
101: public void performChange() {
102: }
103:
104: public FileObject getParentFile() {
105: return parentFile;
106: }
107:
108: public static WhereUsedElement create(CompilationInfo compiler,
109: TreePath tree) {
110: CompilationUnitTree unit = tree.getCompilationUnit();
111: CharSequence content = null;
112: try {
113: content = unit.getSourceFile().getCharContent(true);
114: } catch (IOException ex) {
115: ex.printStackTrace();
116: }
117: SourcePositions sp = compiler.getTrees().getSourcePositions();
118: Tree t = tree.getLeaf();
119: int start;
120: int end;
121: TreeUtilities treeUtils = compiler.getTreeUtilities();
122: if (t.getKind() == Tree.Kind.CLASS) {
123: int[] pos = treeUtils.findNameSpan((ClassTree) t);
124: if (pos == null) {
125: //#121084 hotfix
126: //happens for anonymous innerclasses
127: start = end = (int) sp.getStartPosition(unit, t);
128: } else {
129: start = pos[0];
130: end = pos[1];
131: }
132: } else if (t.getKind() == Tree.Kind.METHOD) {
133: int[] pos = treeUtils.findNameSpan((MethodTree) t);
134: if (pos == null) {
135: //#121084 hotfix
136: start = end = (int) sp.getStartPosition(unit, t);
137: } else {
138: start = pos[0];
139: end = pos[1];
140: }
141: } else if (t.getKind() == Tree.Kind.NEW_CLASS) {
142: ExpressionTree ident = ((NewClassTree) t).getIdentifier();
143: if (ident.getKind() == Tree.Kind.MEMBER_SELECT) {
144: int[] pos = treeUtils
145: .findNameSpan((MemberSelectTree) ident);
146: if (pos == null) {
147: //#121084 hotfix
148: start = end = (int) sp
149: .getStartPosition(unit, ident);
150: } else {
151: start = pos[0];
152: end = pos[1];
153: }
154: } else {
155: TreePath varTreePath = tree.getParentPath();
156: Tree varTree = varTreePath.getLeaf();
157: Trees trees = compiler.getTrees();
158: Element element = trees.getElement(varTreePath);
159: if (varTree.getKind() == Tree.Kind.VARIABLE
160: && element.getKind() == ElementKind.ENUM_CONSTANT) {
161: int[] pos = treeUtils
162: .findNameSpan((VariableTree) varTree);
163: if (pos == null) {
164: //#121084 hotfix
165: start = end = (int) sp.getStartPosition(unit,
166: varTree);
167: } else {
168: start = pos[0];
169: end = pos[1];
170: }
171: } else {
172: start = (int) sp.getStartPosition(unit, ident);
173: end = (int) sp.getEndPosition(unit, ident);
174: }
175: }
176: } else if (t.getKind() == Tree.Kind.MEMBER_SELECT) {
177: int[] pos = treeUtils.findNameSpan((MemberSelectTree) t);
178: if (pos == null) {
179: //#121084 hotfix
180: start = end = (int) sp.getStartPosition(unit, t);
181: } else {
182: start = pos[0];
183: end = pos[1];
184: }
185: } else {
186: start = (int) sp.getStartPosition(unit, t);
187: end = (int) sp.getEndPosition(unit, t);
188: if (end == -1) {
189: ErrorManager.getDefault().notify(
190: ErrorManager.INFORMATIONAL,
191: new RuntimeException(
192: "Cannot get end position for "
193: + t.getClass().getName()
194: + " "
195: + t
196: + " file:"
197: + compiler.getFileObject()
198: .getPath())); // NOI18N
199: end = start;
200: }
201: }
202:
203: assert start > 0 : "Cannot find start position in file "
204: + unit.getSourceFile().getName() + "\n tree="
205: + tree.toString();
206: assert end > 0 : "Cannot find end position in file "
207: + unit.getSourceFile().getName() + "\n tree="
208: + tree.toString();
209: LineMap lm = tree.getCompilationUnit().getLineMap();
210: long line = lm.getLineNumber(start);
211: long endLine = lm.getLineNumber(end);
212: long sta = lm.getStartPosition(line);
213: long en = lm.getStartPosition(endLine + 1) - 1;
214: StringBuffer sb = new StringBuffer();
215: sb.append(RetoucheUtils.getHtml(trimStart(content.subSequence(
216: (int) sta, (int) start).toString())));
217: sb.append("<b>"); //NOI18N
218: sb.append(content.subSequence((int) start, (int) end));
219: sb.append("</b>");//NOI18N
220: sb.append(RetoucheUtils.getHtml(trimEnd(content.subSequence(
221: (int) end, (int) en).toString())));
222:
223: DataObject dob = null;
224: try {
225: dob = DataObject.find(compiler.getFileObject());
226: } catch (DataObjectNotFoundException ex) {
227: ex.printStackTrace();
228: }
229: CloneableEditorSupport ces = JavaWhereUsedQueryPlugin
230: .findCloneableEditorSupport(dob);
231: PositionRef ref1 = ces.createPositionRef(start, Bias.Forward);
232: PositionRef ref2 = ces.createPositionRef(end, Bias.Forward);
233: PositionBounds bounds = new PositionBounds(ref1, ref2);
234: TreePath tr = getEnclosingTree(tree);
235: return new WhereUsedElement(bounds, sb.toString().trim(),
236: compiler.getFileObject(), tr, compiler);
237: }
238:
239: private static String trimStart(String s) {
240: for (int x = 0; x < s.length(); x++) {
241: if (Character.isWhitespace(s.charAt(x))) {
242: continue;
243: } else {
244: return s.substring(x, s.length());
245: }
246: }
247: return "";
248: }
249:
250: private static String trimEnd(String s) {
251: for (int x = s.length() - 1; x >= 0; x--) {
252: if (Character.isWhitespace(s.charAt(x))) {
253: continue;
254: } else {
255: return s.substring(0, x);
256: }
257: }
258: return "";
259: }
260:
261: public static WhereUsedElement create(int start, int end,
262: CompilationInfo compiler) {
263: CompilationUnitTree unit = compiler.getCompilationUnit();
264: CharSequence content = null;
265: try {
266: content = unit.getSourceFile().getCharContent(true);
267: } catch (IOException ex) {
268: ex.printStackTrace();
269: }
270: SourcePositions sp = compiler.getTrees().getSourcePositions();
271: LineMap lm = compiler.getCompilationUnit().getLineMap();
272: long line = lm.getLineNumber(start);
273: long endLine = lm.getLineNumber(end);
274: long sta = lm.getStartPosition(line);
275: long en = lm.getStartPosition(endLine + 1) - 1;
276: StringBuffer sb = new StringBuffer();
277: sb.append(RetoucheUtils.getHtml(trimStart(content.subSequence(
278: (int) sta, (int) start).toString())));
279: sb.append("<b>"); //NOI18N
280: sb.append(content.subSequence((int) start, (int) end));
281: sb.append("</b>");//NOI18N
282: sb.append(RetoucheUtils.getHtml(trimEnd(content.subSequence(
283: (int) end, (int) en).toString())));
284:
285: DataObject dob = null;
286: try {
287: dob = DataObject.find(compiler.getFileObject());
288: } catch (DataObjectNotFoundException ex) {
289: ex.printStackTrace();
290: }
291: CloneableEditorSupport ces = JavaWhereUsedQueryPlugin
292: .findCloneableEditorSupport(dob);
293: PositionRef ref1 = ces.createPositionRef(start, Bias.Forward);
294: PositionRef ref2 = ces.createPositionRef(end, Bias.Forward);
295: PositionBounds bounds = new PositionBounds(ref1, ref2);
296: return new WhereUsedElement(bounds, sb.toString().trim(),
297: compiler.getFileObject(), null, compiler);
298: }
299:
300: private static TreePath getEnclosingTree(TreePath tp) {
301: while (tp != null) {
302: Tree tree = tp.getLeaf();
303: if (tree.getKind() == Tree.Kind.CLASS
304: || tree.getKind() == Tree.Kind.METHOD
305: || tree.getKind() == Tree.Kind.IMPORT) {
306: return tp;
307: }
308: tp = tp.getParentPath();
309: }
310: return null;
311: }
312:
313: }
|