001: /*
002: * GlobalTag.java
003: *
004: * Copyright (C) 1998-2004 Peter Graves
005: * $Id: GlobalTag.java,v 1.2 2004/05/21 16:50:24 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import gnu.regexp.RE;
025: import gnu.regexp.REMatch;
026: import gnu.regexp.UncheckedRE;
027: import java.util.List;
028: import javax.swing.undo.CompoundEdit;
029:
030: public final class GlobalTag extends Tag {
031: private final String filename;
032:
033: private GlobalTag(String name, String signature, String filename) {
034: super (name, signature);
035: this .filename = filename;
036: }
037:
038: private GlobalTag(String name, String signature, String filename,
039: String canonicalSignature) {
040: super (name, signature);
041: this .filename = filename;
042: this .canonicalSignature = canonicalSignature;
043: }
044:
045: public final String getFileName() {
046: return filename;
047: }
048:
049: // Return tag name from line in tag file.
050: public static String getTagName(Line line) {
051: int i = line.getText().indexOf(Tagger.separatorChar);
052: if (i < 0) // Should never happen.
053: return line.getText();
054: else
055: return line.substring(0, i);
056: }
057:
058: // Construct global tag from one line of text in tag file.
059: public static GlobalTag makeGlobalTag(String s) {
060: int index = s.indexOf(Tagger.separatorChar);
061: if (index < 0)
062: return null;
063: String name = s.substring(0, index);
064: s = s.substring(index + 1);
065: index = s.indexOf(Tagger.separatorChar);
066: if (index < 0)
067: return null;
068: String filename = s.substring(0, index);
069: s = s.substring(index + 1);
070: index = s.indexOf(Tagger.separatorChar);
071: if (index < 0) {
072: // No canonical signature.
073: String signature = s;
074: return new GlobalTag(name, signature, filename);
075: }
076: String signature = s.substring(0, index);
077: String canonicalSignature = s.substring(index + 1);
078: return new GlobalTag(name, signature, filename,
079: canonicalSignature);
080: }
081:
082: public String getClassName() {
083: // Java.
084: int index = name.indexOf('.');
085: if (index >= 0)
086: return name.substring(0, index);
087: // C++, Perl.
088: index = name.indexOf("::");
089: if (index >= 0)
090: return name.substring(0, index);
091: // C, Lisp.
092: return null;
093: }
094:
095: public String getMethodName() {
096: // Java
097: int index = name.indexOf('.');
098: if (index >= 0)
099: return name.substring(index + 1);
100: // C++
101: index = name.indexOf("::");
102: if (index >= 0)
103: return name.substring(index + 2);
104: return name;
105: }
106:
107: public String getLongName() {
108: String s = signature.trim();
109: if (s.startsWith("DEFUN")) {
110: // Emacs source.
111: return name;
112: }
113: if (s.startsWith("(")) {
114: // Lisp.
115: s = s.substring(1).trim();
116: // First word should be "defun" or "defvar" or some such...
117: int end = 0;
118: final int limit = s.length();
119: for (int i = 0; i < limit; i++) {
120: char c = s.charAt(i);
121: if (c == ' ' || c == '\t') {
122: end = i;
123: break;
124: }
125: }
126: String definer = s.substring(0, end);
127: s = s.substring(end).trim();
128: FastStringBuffer sb = new FastStringBuffer('(');
129: sb.append(definer);
130: sb.append(' ');
131: if (definer.equals("defgeneric")
132: || definer.equals("defmethod")) {
133: sb.append(s);
134: return sb.toString();
135: }
136: for (int i = 0; i < limit; i++) {
137: char c = s.charAt(i);
138: if (c == ' ' || c == '\t') {
139: sb.append(s.substring(0, i));
140: sb.append(" ...");
141: return sb.toString();
142: }
143: if (c == ')') {
144: sb.append(s.substring(0, i + 1));
145: return sb.toString();
146: }
147: }
148: sb.append(s);
149: sb.append(" ...");
150: return sb.toString();
151: }
152: if (name.startsWith("class "))
153: return name;
154: // Strip comment if any.
155: // BUG! Only really relevant to Java-like languages.
156: int index = s.indexOf("//");
157: if (index >= 0)
158: s = s.substring(0, index).trim();
159: index = s.lastIndexOf(')');
160: if (index >= 0)
161: s = s.substring(0, index + 1);
162: if (s.endsWith("("))
163: s = s.substring(0, s.length() - 1);
164: // Try to substitute the fully qualified method name.
165: // Try Java first.
166: String separator = ".";
167: int sepLength = 1;
168: index = name.indexOf(separator);
169: if (index >= 0) {
170: String methodName = name.substring(index + sepLength);
171: index = s.indexOf(methodName);
172: if (index >= 0) {
173: String head = s.substring(0, index);
174: String tail = s.substring(index + methodName.length());
175: s = head + name + tail;
176: }
177: } else {
178: // C++.
179: separator = "::";
180: sepLength = 2;
181: index = name.indexOf(separator);
182: if (index >= 0) {
183: String methodName = name.substring(index + sepLength);
184: index = s.indexOf(methodName);
185: if (index >= 0) {
186: String head = s.substring(0, index);
187: String tail = s.substring(index
188: + methodName.length());
189: s = head + name + tail;
190: }
191: }
192: }
193: return s;
194: }
195:
196: public String toString() {
197: // JavaScript.
198: if (signature.trim().startsWith("function "))
199: return signature + " "
200: + File.getInstance(filename).getName();
201: else
202: return super .toString();
203: }
204:
205: public void gotoTag(Editor editor) {
206: editor.setWaitCursor();
207: Buffer buf = Editor.getBuffer(File.getInstance(filename));
208: if (buf != null) {
209: editor.makeNext(buf);
210: editor.activate(buf);
211: Position pos = findSignatureInCurrentBuffer(buf, signature);
212: if (pos != null) {
213: CompoundEdit compoundEdit = editor.beginCompoundEdit();
214: editor.addUndo(SimpleEdit.FOLD);
215: editor.unfoldMethod(pos.getLine());
216: editor.moveDotTo(pos);
217: TagCommands.centerTag(editor);
218: editor.endCompoundEdit(compoundEdit);
219: editor.updateDisplay();
220: }
221: }
222: editor.setDefaultCursor();
223: }
224:
225: private static Position findSignatureInCurrentBuffer(Buffer buffer,
226: String signature) {
227: final List localTags = buffer.getTags(true);
228: if (localTags == null)
229: return null;
230: final int limit = localTags.size();
231: for (int i = 0; i < limit; i++) {
232: LocalTag localTag = (LocalTag) localTags.get(i);
233: if (localTag.getSignature().equals(signature))
234: return localTag.getPosition();
235: }
236: // We did not find an exact match. The signature may have changed.
237: // Look for a substring containing the function name and argument list
238: // only.
239: RE re = new UncheckedRE("\\w+\\s*\\(.*\\)");
240: REMatch match = re.getMatch(signature);
241: if (match != null) {
242: String sub = match.toString();
243: for (int i = 0; i < limit; i++) {
244: LocalTag localTag = (LocalTag) localTags.get(i);
245: if (localTag.getSignature().indexOf(sub) >= 0)
246: return localTag.getPosition();
247: }
248: }
249: return null;
250: }
251: }
|