Clicking on an element declaration should allow to search for its usages/overriders/implementors/subtypes
1.1 --- a/remoting/server/web/resolve.web.api/src/org/netbeans/modules/jackpot30/resolve/api/ResolveService.java Fri Nov 30 22:05:42 2012 +0100
1.2 +++ b/remoting/server/web/resolve.web.api/src/org/netbeans/modules/jackpot30/resolve/api/ResolveService.java Sun Dec 02 22:31:11 2012 +0100
1.3 @@ -91,43 +91,6 @@
1.4 return javac.parse(relative);
1.5 }
1.6
1.7 - /**Long or String*/
1.8 - public static Object resolveGoToTarget(final CompilationInfo info, final long pos) throws IOException, InterruptedException {
1.9 - final Object[] result = new Object[1];
1.10 -
1.11 - new TreePathScanner<Void, Void>() {
1.12 - @Override public Void visitIdentifier(IdentifierTree node, Void p) {
1.13 - handle();
1.14 - return super.visitIdentifier(node, p);
1.15 - }
1.16 - @Override public Void visitMemberSelect(MemberSelectTree node, Void p) {
1.17 - handle();
1.18 - return super.visitMemberSelect(node, p);
1.19 - }
1.20 - private void handle() {
1.21 - Element el = info.getTrees().getElement(getCurrentPath());
1.22 -
1.23 - if (el == null) return;
1.24 -
1.25 - long[] span = nameSpan(info, getCurrentPath());
1.26 -
1.27 - if (span[0] <= pos && pos <= span[1]) {
1.28 - TreePath tp = info.getTrees().getPath(el);
1.29 -
1.30 - if (tp != null && tp.getCompilationUnit() == info.getCompilationUnit()) {
1.31 - result[0] = info.getTrees().getSourcePositions().getStartPosition(tp.getCompilationUnit(), tp.getLeaf());
1.32 - } else {
1.33 - assert JavaUtils.SUPPORTED_KINDS.contains(el.getKind());
1.34 -
1.35 - result[0] = JavaUtils.serialize(ElementHandle.create(el));
1.36 - }
1.37 - }
1.38 - }
1.39 - }.scan(info.getCompilationUnit(), null);
1.40 -
1.41 - return result[0];
1.42 - }
1.43 -
1.44 public static String resolveSource(String segment, String relative, String signature) throws IOException, InterruptedException {
1.45 String fqn = topLevelClassFromSignature(signature);
1.46 SourceRoot sourceRoot = sourceRoot(CategoryStorage.forId(segment), relative);
1.47 @@ -218,6 +181,10 @@
1.48 switch (forTree.getLeaf().getKind()) {
1.49 case IDENTIFIER: name = ((IdentifierTree) forTree.getLeaf()).getName(); break;
1.50 case MEMBER_SELECT: name = ((MemberSelectTree) forTree.getLeaf()).getIdentifier(); break;
1.51 + case ANNOTATION_TYPE: case CLASS:
1.52 + case ENUM: case INTERFACE: name = ((ClassTree) forTree.getLeaf()).getSimpleName(); break;
1.53 + case METHOD: name = ((MethodTree) forTree.getLeaf()).getName(); break;
1.54 + case VARIABLE: name = ((VariableTree) forTree.getLeaf()).getName(); break;
1.55 }
1.56
1.57 if (name != null) {
1.58 @@ -242,33 +209,26 @@
1.59
1.60 new TreePathScanner<Void, Void>() {
1.61 @Override public Void visitClass(ClassTree node, Void p) {
1.62 - handleDeclaration(node.getSimpleName());
1.63 + handleDeclaration();
1.64 return super.visitClass(node, p);
1.65 }
1.66 @Override public Void visitMethod(MethodTree node, Void p) {
1.67 - handleDeclaration(node.getName());
1.68 + handleDeclaration();
1.69 return super.visitMethod(node, p);
1.70 }
1.71 @Override public Void visitVariable(VariableTree node, Void p) {
1.72 - handleDeclaration(node.getName());
1.73 + handleDeclaration();
1.74 return super.visitVariable(node, p);
1.75 }
1.76 - private void handleDeclaration(CharSequence name) {
1.77 + private void handleDeclaration() {
1.78 Element el = info.getTrees().getElement(getCurrentPath());
1.79
1.80 if (el == null/*how?*/ || !JavaUtils.SUPPORTED_KINDS.contains(el.getKind())) return ;
1.81
1.82 String thisSignature = JavaUtils.serialize(ElementHandle.create(el));
1.83 - Tree node = getCurrentPath().getLeaf();
1.84
1.85 if (thisSignature.equals(signature)) {
1.86 - long[] spans = new long[] {
1.87 - info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), node),
1.88 - info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), node),
1.89 - ((JCTree) node).pos,
1.90 - ((JCTree) node).pos + name.length()
1.91 - };
1.92 - result[0] = spans;
1.93 + result[0] = nameSpan(info, getCurrentPath());
1.94 }
1.95 }
1.96 }.scan(info.getCompilationUnit(), null);
2.1 --- a/remoting/server/web/web.ui/nbproject/project.properties Fri Nov 30 22:05:42 2012 +0100
2.2 +++ b/remoting/server/web/web.ui/nbproject/project.properties Sun Dec 02 22:31:11 2012 +0100
2.3 @@ -28,6 +28,7 @@
2.4 endorsed.classpath=
2.5 excludes=
2.6 file.reference.org-netbeans-modules-java-lexer.jar=../../../../lib/org-netbeans-modules-java-lexer.jar
2.7 +file.reference.org-netbeans-modules-java-source.jar=../../../../lib/org-netbeans-modules-java-source.jar
2.8 file.reference.org-netbeans-modules-jumpto.jar=../../../../lib/org-netbeans-modules-jumpto.jar
2.9 file.reference.org-netbeans-modules-lexer.jar=../../../../lib/org-netbeans-modules-lexer.jar
2.10 file.reference.org-netbeans-modules-parsing-lucene.jar=../../../../lib/org-netbeans-modules-parsing-lucene.jar
2.11 @@ -53,7 +54,8 @@
2.12 ${file.reference.org-netbeans-modules-lexer.jar}:\
2.13 ${file.reference.org-openide-util.jar}:\
2.14 ${reference.resolve_web_api.jar}:\
2.15 - ${libs.javac.classpath}
2.16 + ${libs.javac.classpath}:\
2.17 + ${file.reference.org-netbeans-modules-java-source.jar}
2.18 # Space-separated list of extra javac options
2.19 javac.compilerargs=-Xbootclasspath/p:${libs.javac.classpath}
2.20 javac.deprecation=false
3.1 --- a/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java Fri Nov 30 22:05:42 2012 +0100
3.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java Sun Dec 02 22:31:11 2012 +0100
3.3 @@ -42,6 +42,13 @@
3.4
3.5 package org.netbeans.modules.jackpot30.backend.ui;
3.6
3.7 +import com.sun.source.tree.ClassTree;
3.8 +import com.sun.source.tree.IdentifierTree;
3.9 +import com.sun.source.tree.MemberSelectTree;
3.10 +import com.sun.source.tree.MethodTree;
3.11 +import com.sun.source.tree.VariableTree;
3.12 +import com.sun.source.util.TreePath;
3.13 +import com.sun.source.util.TreePathScanner;
3.14 import freemarker.template.TemplateException;
3.15 import java.io.IOException;
3.16 import java.net.URI;
3.17 @@ -58,6 +65,8 @@
3.18 import java.util.Map;
3.19 import java.util.Map.Entry;
3.20 import java.util.concurrent.atomic.AtomicBoolean;
3.21 +import javax.lang.model.element.Element;
3.22 +import javax.lang.model.element.ElementKind;
3.23 import javax.ws.rs.GET;
3.24 import javax.ws.rs.Path;
3.25 import javax.ws.rs.Produces;
3.26 @@ -66,6 +75,7 @@
3.27 import javax.ws.rs.core.UriInfo;
3.28 import org.codeviation.pojson.Pojson;
3.29 import org.netbeans.api.java.lexer.JavaTokenId;
3.30 +import org.netbeans.api.java.source.ElementHandle;
3.31 import org.netbeans.api.lexer.Token;
3.32 import org.netbeans.api.lexer.TokenHierarchy;
3.33 import org.netbeans.api.lexer.TokenSequence;
3.34 @@ -78,6 +88,7 @@
3.35 import org.netbeans.modules.jackpot30.backend.ui.highlighting.SemanticHighlighter;
3.36 import org.netbeans.modules.jackpot30.backend.ui.highlighting.TokenList;
3.37 import org.netbeans.modules.jackpot30.resolve.api.CompilationInfo;
3.38 +import org.netbeans.modules.jackpot30.resolve.api.JavaUtils;
3.39 import org.netbeans.modules.jackpot30.resolve.api.ResolveService;
3.40
3.41 /**
3.42 @@ -304,7 +315,7 @@
3.43 final String urlBase = URL_BASE_OVERRIDE != null ? URL_BASE_OVERRIDE : uriInfo.getBaseUri().toString();
3.44 Map<String, Object> configurationData = usagesSubclassesImpl(urlBase, segment, signatures, "files", new ComputeSegmentData() {
3.45 @Override public Object compute(String currentSegment) throws URISyntaxException, TemplateException, IOException {
3.46 - URI u = new URI(urlBase + "index/usages/search?path=" + escapeForQuery(currentSegment) + "&signatures=" + escapeForQuery(simplify(signatures)));
3.47 + URI u = new URI(urlBase + "index/usages/search?path=" + escapeForQuery(currentSegment) + "&signatures=" + escapeForQuery(signatures));
3.48 List<String> files = new ArrayList<String>(WebUtilities.requestStringArrayResponse(u));
3.49 Collections.sort(files);
3.50 return files;
3.51 @@ -350,11 +361,10 @@
3.52
3.53 configurationData.put("isSubtypes", true);
3.54 } else {
3.55 - final String method = methodSignature.substring(0, methodSignature.length() - 1);
3.56 configurationData = usagesSubclassesImpl(urlBase, segment, methodSignature, "implementors", new ComputeSegmentData() {
3.57 @Override
3.58 public Object compute(String currentSegment) throws URISyntaxException, TemplateException, IOException {
3.59 - URI u = new URI(urlBase + "index/implements/search?path=" + escapeForQuery(currentSegment) + "&method=" + escapeForQuery(method));
3.60 + URI u = new URI(urlBase + "index/implements/search?path=" + escapeForQuery(currentSegment) + "&method=" + escapeForQuery(methodSignature));
3.61 Map<String, List<Map<String, String>>> data = Pojson.load(HashMap.class, u);
3.62 List<Map<String, String>> implementors = new ArrayList<Map<String, String>>();
3.63 for (Entry<String, List<Map<String, String>>> relpath2ImplementorsE : data.entrySet()) {
3.64 @@ -621,27 +631,6 @@
3.65 return input;
3.66 }
3.67
3.68 - static String simplify(String originalSignature) {
3.69 - if ( !originalSignature.startsWith("METHOD:")
3.70 - && !originalSignature.startsWith("CONSTRUCTOR:")) return originalSignature;
3.71 - StringBuilder target = new StringBuilder(originalSignature.length());
3.72 - int b = 0;
3.73 -
3.74 - for (char c : originalSignature.toCharArray()) {
3.75 - if (c == '<') {
3.76 - b++;
3.77 - } else if (c == '>') {
3.78 - b--;
3.79 - } else if (b == '^') {
3.80 - return target.toString();
3.81 - } else if (b == 0) {
3.82 - target.append(c);
3.83 - }
3.84 - }
3.85 -
3.86 - return target.delete(target.length() - 1, target.length()).toString();
3.87 - }
3.88 -
3.89 static String strip(String originalSignature, String... prefixesToStrip) {
3.90 for (String strip : prefixesToStrip) {
3.91 if (originalSignature.startsWith(strip)) {
3.92 @@ -655,71 +644,166 @@
3.93 @GET
3.94 @Path("/target")
3.95 // @Produces("text/html")
3.96 - public String target(@QueryParam("path") String segment, @QueryParam("relative") String relative, @QueryParam("position") Long position, @QueryParam("signature") String signature) throws URISyntaxException, IOException, TemplateException, InterruptedException {
3.97 - CompilationInfo info = ResolveService.parse(segment, relative);
3.98 - Object target = null;
3.99 + public String target(@QueryParam("path") String segment, @QueryParam("relative") String relative, @QueryParam("position") final long position) throws URISyntaxException, IOException, TemplateException, InterruptedException {
3.100 + final CompilationInfo info = ResolveService.parse(segment, relative);
3.101 + final boolean[] declaration = new boolean[1];
3.102 + final long[] targetPosition = new long[] { -2 };
3.103 + final String[] signature = new String[1];
3.104 + final ElementKind[] kind = new ElementKind[1];
3.105
3.106 - if (signature != null) {
3.107 - long[] span = ResolveService.declarationSpans(info, signature);
3.108 + new TreePathScanner<Void, Void>() {
3.109 + @Override public Void visitIdentifier(IdentifierTree node, Void p) {
3.110 + handleUsage();
3.111 + return super.visitIdentifier(node, p);
3.112 + }
3.113 + @Override public Void visitMemberSelect(MemberSelectTree node, Void p) {
3.114 + handleUsage();
3.115 + return super.visitMemberSelect(node, p);
3.116 + }
3.117 + private void handleUsage() {
3.118 + Element el = info.getTrees().getElement(getCurrentPath());
3.119
3.120 - if (span != null) {
3.121 - target = span[2];
3.122 + if (el == null) return;
3.123 +
3.124 + long[] span = ResolveService.nameSpan(info, getCurrentPath());
3.125 +
3.126 + if (span[0] <= position && position <= span[1]) {
3.127 + if (JavaUtils.SUPPORTED_KINDS.contains(el.getKind())) {
3.128 + signature[0] = JavaUtils.serialize(ElementHandle.create(el));
3.129 + }
3.130 +
3.131 + TreePath tp = info.getTrees().getPath(el);
3.132 +
3.133 + if (tp != null && tp.getCompilationUnit() == info.getCompilationUnit()) {
3.134 + targetPosition[0] = info.getTrees().getSourcePositions().getStartPosition(tp.getCompilationUnit(), tp.getLeaf());
3.135 + }
3.136 + }
3.137 }
3.138 - } else {
3.139 - target = ResolveService.resolveGoToTarget(info, position);
3.140 - }
3.141 + @Override public Void visitClass(ClassTree node, Void p) {
3.142 + handleDeclaration();
3.143 + return super.visitClass(node, p);
3.144 + }
3.145 + @Override public Void visitMethod(MethodTree node, Void p) {
3.146 + handleDeclaration();
3.147 + return super.visitMethod(node, p);
3.148 + }
3.149 + @Override public Void visitVariable(VariableTree node, Void p) {
3.150 + handleDeclaration();
3.151 + return super.visitVariable(node, p);
3.152 + }
3.153 + private void handleDeclaration() {
3.154 + Element el = info.getTrees().getElement(getCurrentPath());
3.155 +
3.156 + if (el == null) return;
3.157 +
3.158 + long[] span = ResolveService.nameSpan(info, getCurrentPath());
3.159 +
3.160 + if (span[0] <= position && position <= span[1]) {
3.161 + if (JavaUtils.SUPPORTED_KINDS.contains(el.getKind())) {
3.162 + signature[0] = JavaUtils.serialize(ElementHandle.create(el));
3.163 + }
3.164 +
3.165 + declaration[0] = true;
3.166 + kind[0] = el.getKind();
3.167 + }
3.168 + }
3.169 + }.scan(info.getCompilationUnit(), null);
3.170
3.171 Map<String, Object> result = new HashMap<String, Object>();
3.172
3.173 - if (target instanceof Long) {
3.174 - result.put("position", target);
3.175 - } else if (target instanceof String) {
3.176 - String targetSignature = (String) target;
3.177 - String source = ResolveService.resolveSource(segment, relative, targetSignature);
3.178 + if (declaration[0]) {
3.179 + if (signature[0] != null) {
3.180 + List<Map<String, String>> menu = new ArrayList<Map<String, String>>();
3.181
3.182 - result.put("signature", targetSignature);
3.183 -
3.184 - if (source != null) {
3.185 - result.put("path", segment);
3.186 - result.put("source", source);
3.187 - } else {
3.188 - String singleSource = null;
3.189 - String singleSourceSegment = null;
3.190 - boolean multipleSources = false;
3.191 - List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
3.192 + menu.add(menuMap("Usages in current project", "/index/ui/usages?path=" + escapeForQuery(segment) + "&signatures=" + escapeForQuery(signature[0])));
3.193 + menu.add(menuMap("Usages in all known projects", "/index/ui/usages?signatures=" + escapeForQuery(signature[0])));
3.194
3.195 - for (Entry<? extends CategoryStorage, ? extends Iterable<? extends String>> e : ResolveService.findSourcesContaining(targetSignature).entrySet()) {
3.196 - Map<String, Object> categoryData = new HashMap<String, Object>();
3.197 + switch (kind[0]) {
3.198 + case METHOD:
3.199 + menu.add(menuMap("Overriders in the current project", "/index/ui/implements?path=" + escapeForQuery(segment) + "&method=" + escapeForQuery(signature[0])));
3.200 + menu.add(menuMap("Overriders in all known projects", "/index/ui/implements?method=" + escapeForQuery(signature[0])));
3.201 + break;
3.202 + case CLASS: case INTERFACE: case ENUM: case ANNOTATION_TYPE:
3.203 + menu.add(menuMap("Subtypes in the current project", "/index/ui/implements?path=" + escapeForQuery(segment) + "&type=" + escapeForQuery(signature[0])));
3.204 + menu.add(menuMap("Subtypes in all known projects", "/index/ui/implements?type=" + escapeForQuery(signature[0])));
3.205 + break;
3.206 + }
3.207 + result.put("menu", menu);
3.208 + }
3.209 + } else {
3.210 + if (targetPosition[0] != (-2)) {
3.211 + result.put("position", targetPosition[0]);
3.212 + } else if (signature[0] != null) {
3.213 + String targetSignature = signature[0];
3.214 + String source = ResolveService.resolveSource(segment, relative, targetSignature);
3.215
3.216 - categoryData.put("rootDisplayName", e.getKey().getDisplayName());
3.217 - categoryData.put("rootPath", e.getKey().getId());
3.218 - categoryData.put("files", e.getValue());
3.219 + result.put("signature", targetSignature);
3.220
3.221 - if (!multipleSources) {
3.222 - Iterator<? extends String> fIt = e.getValue().iterator();
3.223 + if (source != null) {
3.224 + result.put("path", segment);
3.225 + result.put("source", source);
3.226 + } else {
3.227 + String singleSource = null;
3.228 + String singleSourceSegment = null;
3.229 + boolean multipleSources = false;
3.230 + List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
3.231
3.232 - if (fIt.hasNext()) {
3.233 - singleSource = fIt.next();
3.234 - singleSourceSegment = e.getKey().getId();
3.235 + for (Entry<? extends CategoryStorage, ? extends Iterable<? extends String>> e : ResolveService.findSourcesContaining(targetSignature).entrySet()) {
3.236 + Map<String, Object> categoryData = new HashMap<String, Object>();
3.237 +
3.238 + categoryData.put("rootDisplayName", e.getKey().getDisplayName());
3.239 + categoryData.put("rootPath", e.getKey().getId());
3.240 + categoryData.put("files", e.getValue());
3.241 +
3.242 + if (!multipleSources) {
3.243 + Iterator<? extends String> fIt = e.getValue().iterator();
3.244 +
3.245 + if (fIt.hasNext()) {
3.246 + singleSource = fIt.next();
3.247 + singleSourceSegment = e.getKey().getId();
3.248 + }
3.249 +
3.250 + if (fIt.hasNext())
3.251 + multipleSources = true;
3.252 }
3.253 -
3.254 - if (fIt.hasNext())
3.255 - multipleSources = true;
3.256 +
3.257 + results.add(categoryData);
3.258 }
3.259
3.260 - results.add(categoryData);
3.261 - }
3.262 -
3.263 - if (singleSource != null && !multipleSources) {
3.264 - //TODO: will automatically jump to the single known target - correct
3.265 - result.put("path", singleSourceSegment);
3.266 - result.put("source", singleSource);
3.267 - } else if (!results.isEmpty()) {
3.268 - result.put("targets", results);
3.269 + if (singleSource != null && !multipleSources) {
3.270 + //TODO: will automatically jump to the single known target - correct?
3.271 + result.put("path", singleSourceSegment);
3.272 + result.put("source", singleSource);
3.273 + } else if (!results.isEmpty()) {
3.274 + result.put("targets", results);
3.275 + }
3.276 }
3.277 }
3.278 }
3.279
3.280 return Pojson.save(result);
3.281 }
3.282 +
3.283 + private static Map<String, String> menuMap(String displayName, String url) {
3.284 + Map<String, String> result = new HashMap<String, String>();
3.285 +
3.286 + result.put("displayName", displayName);
3.287 + result.put("url", url);
3.288 +
3.289 + return result;
3.290 + }
3.291 +
3.292 + @GET
3.293 + @Path("/declarationSpan")
3.294 +// @Produces("text/html")
3.295 + public String declarationSpan(@QueryParam("path") String segment, @QueryParam("relative") String relative, @QueryParam("signature") String signature) throws URISyntaxException, IOException, TemplateException, InterruptedException {
3.296 + CompilationInfo info = ResolveService.parse(segment, relative);
3.297 + long[] span = ResolveService.declarationSpans(info, signature);
3.298 +
3.299 + if (span == null) {
3.300 + span = new long[] {-1, -1, -1, -1};
3.301 + }
3.302 +
3.303 + return Pojson.save(span);
3.304 + }
3.305 }
4.1 --- a/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/showCode.html Fri Nov 30 22:05:42 2012 +0100
4.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/showCode.html Sun Dec 02 22:31:11 2012 +0100
4.3 @@ -23,10 +23,10 @@
4.4
4.5 for (var i = 0; i < $params.length; i++) {
4.6 if ($params[i].indexOf("signature=") !== (-1)) {
4.7 - $.get('/index/ui/target?path=${path}&relative=${relative}&signature=' + unescape($params[i].substring("signature=".length)), function(data) {
4.8 + $.get('/index/ui/declarationSpan?path=${path}&relative=${relative}&signature=' + unescape($params[i].substring("signature=".length)), function(data) {
4.9 var parsedData = $.parseJSON(data);
4.10 - if ("position" in parsedData) {
4.11 - window.location.hash = "#p" + parsedData.position;
4.12 + if (parsedData[2] !== (-1)) {
4.13 + window.location.hash = "#p" + parsedData[2];
4.14 }
4.15
4.16 });
4.17 @@ -66,6 +66,18 @@
4.18 title: 'Show',
4.19 width: 800 //XXX: hardcoded size
4.20 });
4.21 + } else if ("menu" in parsedData) {
4.22 + var menuDef = parsedData.menu;
4.23 + var popupContent = "";
4.24 + for (var i = 0; i < menuDef.length; i++) {
4.25 + var menuItem = menuDef[i];
4.26 + popupContent += '<a href="' + menuItem.url + '">' + menuItem.displayName + '</a><br>';
4.27 + $('#popup').html(popupContent)
4.28 + .dialog({
4.29 + title: 'Show',
4.30 + width: 800 //XXX: hardcoded size
4.31 + });
4.32 + }
4.33 } else if ("signature" in parsedData) {
4.34 alert("Cannot find source file for class: " + parsedData.signature.split(":")[1]);
4.35 } else {
5.1 --- a/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/ui-findType.html Fri Nov 30 22:05:42 2012 +0100
5.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/ui-findType.html Sun Dec 02 22:31:11 2012 +0100
5.3 @@ -5,7 +5,7 @@
5.4 <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/base/jquery-ui.css" rel="stylesheet" type="text/css">
5.5 <script type="text/javascript">
5.6 function methodPopup(relativePath, resultFile, signature) {
5.7 - $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '">Source Code</a><br>' +
5.8 + $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '&signatures=' + signature + '">Source Code</a><br>' +
5.9 '<a href="/index/ui/usages?path=' + relativePath + '&signatures=' + signature + '">Usages in the defining project</a><br>' +
5.10 '<a href="/index/ui/usages?signatures=' + signature + '">Usages in all known projects</a><br>' +
5.11 '<a href="/index/ui/implements?path=' + relativePath + '&method=' + signature + '">Overriders in the defining project</a><br>' +
5.12 @@ -16,7 +16,7 @@
5.13 });
5.14 }
5.15 function classPopup(relativePath, resultFile, signature) {
5.16 - $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '">Source Code</a><br>' +
5.17 + $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '&signatures=' + signature + '">Source Code</a><br>' +
5.18 '<a href="/index/ui/usages?path=' + relativePath + '&signatures=' + signature + '">Usages in the defining project</a><br>' +
5.19 '<a href="/index/ui/usages?signatures=' + signature + '">Usages in all known projects</a><br>' +
5.20 '<a href="/index/ui/implements?path=' + relativePath + '&type=' + signature + '">Subtypes in the defining project</a><br>' +
5.21 @@ -27,7 +27,7 @@
5.22 });
5.23 }
5.24 function otherPopup(relativePath, resultFile, signature) {
5.25 - $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '">Source Code</a><br>' +
5.26 + $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '&signatures=' + signature + '">Source Code</a><br>' +
5.27 '<a href="/index/ui/usages?path=' + relativePath + '&signatures=' + signature + '">Usages in the defining project</a><br>' +
5.28 '<a href="/index/ui/usages?signatures=' + signature + '">Usages in all known projects</a><br>')
5.29 .dialog({
5.30 @@ -75,7 +75,7 @@
5.31 <nobr>
5.32 <img src="/index/icons/${result.icon}" alt="${result.kind}"/>
5.33 <#if result.kind == "METHOD">
5.34 - <a href="javascript: methodPopup('${result.segment.segment}', '${result.file}', '${result.kind}:${result.enclosingFQN}:${result.simpleName}:${result.vmsignature};')">
5.35 + <a href="javascript: methodPopup('${result.segment.segment}', '${result.file}', '${result.kind}:${result.enclosingFQN}:${result.simpleName}:${result.vmsignature}')">
5.36 <#elseif result.kind == "CLASS" || result.kind == "INTERFACE" || result.kind == "ENUM" || result.kind == "ANNOTATION_TYPE">
5.37 <a href="javascript: classPopup('${result.segment.segment}', '${result.file}', '${result.kind}:${result.fqn}')">
5.38 <#else>