A crude sketch of find-type over net.
1.1 --- a/server/backend/impl/nbproject/genfiles.properties Tue Feb 15 20:14:52 2011 +0100
1.2 +++ b/server/backend/impl/nbproject/genfiles.properties Tue Feb 15 20:16:07 2011 +0100
1.3 @@ -1,8 +1,8 @@
1.4 -build.xml.data.CRC32=a49bef13
1.5 +build.xml.data.CRC32=f3f7e858
1.6 build.xml.script.CRC32=c32e03a8
1.7 build.xml.stylesheet.CRC32=a56c6a5b@1.44
1.8 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
1.9 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
1.10 -nbproject/build-impl.xml.data.CRC32=a49bef13
1.11 +nbproject/build-impl.xml.data.CRC32=f3f7e858
1.12 nbproject/build-impl.xml.script.CRC32=87e6e497
1.13 nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
2.1 --- a/server/backend/impl/nbproject/project.xml Tue Feb 15 20:14:52 2011 +0100
2.2 +++ b/server/backend/impl/nbproject/project.xml Tue Feb 15 20:16:07 2011 +0100
2.3 @@ -72,7 +72,7 @@
2.4 <build-prerequisite/>
2.5 <compile-dependency/>
2.6 <run-dependency>
2.7 - <specification-version>0.75.0.17.12.6</specification-version>
2.8 + <implementation-version/>
2.9 </run-dependency>
2.10 </dependency>
2.11 <dependency>
2.12 @@ -84,6 +84,15 @@
2.13 </run-dependency>
2.14 </dependency>
2.15 <dependency>
2.16 + <code-name-base>org.netbeans.modules.jumpto</code-name-base>
2.17 + <build-prerequisite/>
2.18 + <compile-dependency/>
2.19 + <run-dependency>
2.20 + <release-version>1</release-version>
2.21 + <implementation-version/>
2.22 + </run-dependency>
2.23 + </dependency>
2.24 + <dependency>
2.25 <code-name-base>org.netbeans.modules.project.ant</code-name-base>
2.26 <build-prerequisite/>
2.27 <compile-dependency/>
2.28 @@ -187,6 +196,24 @@
2.29 </run-dependency>
2.30 </dependency>
2.31 </module-dependencies>
2.32 + <test-dependencies>
2.33 + <test-type>
2.34 + <name>unit</name>
2.35 + <test-dependency>
2.36 + <code-name-base>org.netbeans.libs.junit4</code-name-base>
2.37 + <compile-dependency/>
2.38 + </test-dependency>
2.39 + <test-dependency>
2.40 + <code-name-base>org.netbeans.modules.junitlib</code-name-base>
2.41 + <compile-dependency/>
2.42 + </test-dependency>
2.43 + <test-dependency>
2.44 + <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
2.45 + <recursive/>
2.46 + <compile-dependency/>
2.47 + </test-dependency>
2.48 + </test-type>
2.49 + </test-dependencies>
2.50 <public-packages/>
2.51 </data>
2.52 </configuration>
3.1 --- a/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/API.java Tue Feb 15 20:14:52 2011 +0100
3.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/API.java Tue Feb 15 20:16:07 2011 +0100
3.3 @@ -52,7 +52,10 @@
3.4 import java.util.Arrays;
3.5 import java.util.Collection;
3.6 import java.util.Collections;
3.7 +import java.util.EnumSet;
3.8 import java.util.HashMap;
3.9 +import java.util.HashSet;
3.10 +import java.util.LinkedHashMap;
3.11 import java.util.LinkedList;
3.12 import java.util.List;
3.13 import java.util.Map;
3.14 @@ -60,6 +63,7 @@
3.15 import java.util.Set;
3.16 import java.util.concurrent.atomic.AtomicBoolean;
3.17 import java.util.concurrent.atomic.AtomicLong;
3.18 +import javax.lang.model.element.TypeElement;
3.19 import javax.tools.Diagnostic;
3.20 import javax.tools.JavaFileObject;
3.21 import javax.ws.rs.DefaultValue;
3.22 @@ -71,7 +75,11 @@
3.23 import javax.ws.rs.core.StreamingOutput;
3.24 import org.codeviation.pojson.Pojson;
3.25 import org.netbeans.api.java.classpath.ClassPath;
3.26 +import org.netbeans.api.java.source.ClassIndex.NameKind;
3.27 +import org.netbeans.api.java.source.ClassIndex.SearchScope;
3.28 +import org.netbeans.api.java.source.ClasspathInfo;
3.29 import org.netbeans.api.java.source.CompilationController;
3.30 +import org.netbeans.api.java.source.ElementHandle;
3.31 import org.netbeans.api.java.source.ModificationResult;
3.32 import org.netbeans.modules.jackpot30.backend.impl.CategoryStorage;
3.33 import org.netbeans.modules.jackpot30.impl.MessageImpl;
3.34 @@ -89,6 +97,8 @@
3.35 import org.netbeans.modules.jackpot30.impl.indexing.Index;
3.36 import org.netbeans.modules.jackpot30.spi.HintDescription;
3.37 import org.netbeans.modules.jackpot30.spi.PatternConvertor;
3.38 +import org.netbeans.modules.java.source.usages.ClassIndexManager;
3.39 +import org.netbeans.modules.jumpto.type.GoToTypeAction;
3.40 import org.netbeans.spi.editor.hints.ErrorDescription;
3.41 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
3.42 import org.openide.filesystems.FileObject;
3.43 @@ -399,6 +409,65 @@
3.44 return Pojson.save(result);
3.45 }
3.46
3.47 + @GET
3.48 + @Path("/findType")
3.49 + @Produces("text/plain")
3.50 + public String findType(@QueryParam("path") String segment, @QueryParam("prefix") String prefix, @QueryParam("casesensitive") @DefaultValue("false") boolean casesensitive, @QueryParam("asynchronous") @DefaultValue(value="false") boolean asynchronous) throws IOException {
3.51 + assert !asynchronous;
3.52 +
3.53 + //copied (and converted to NameKind) from jumpto's GoToTypeAction:
3.54 + boolean exact = prefix.endsWith(" "); // NOI18N
3.55 +
3.56 + prefix = prefix.trim();
3.57 +
3.58 + if ( prefix.length() == 0) {
3.59 + return "";
3.60 + }
3.61 +
3.62 + NameKind nameKind;
3.63 + int wildcard = GoToTypeAction.containsWildCard(prefix);
3.64 +
3.65 + if (exact) {
3.66 + //nameKind = panel.isCaseSensitive() ? SearchType.EXACT_NAME : SearchType.CASE_INSENSITIVE_EXACT_NAME;
3.67 + nameKind = NameKind.SIMPLE_NAME;
3.68 + }
3.69 + else if ((GoToTypeAction.isAllUpper(prefix) && prefix.length() > 1) || GoToTypeAction.isCamelCase(prefix)) {
3.70 + nameKind = NameKind.CAMEL_CASE;
3.71 + }
3.72 + else if (wildcard != -1) {
3.73 + nameKind = casesensitive ? NameKind.REGEXP : NameKind.CASE_INSENSITIVE_REGEXP;
3.74 + }
3.75 + else {
3.76 + nameKind = casesensitive ? NameKind.PREFIX : NameKind.CASE_INSENSITIVE_PREFIX;
3.77 + }
3.78 +
3.79 + Map<String, List<String>> result = new LinkedHashMap<String, List<String>>();
3.80 + Set<FileObject> srcRoots = CategoryStorage.getCategoryContent(segment);
3.81 + FileObject deepestCommonParent = deepestCommonParent(srcRoots);
3.82 +
3.83 + for (FileObject srcRoot : srcRoots) {
3.84 + String rootId = FileUtil.getRelativePath(deepestCommonParent, srcRoot);
3.85 + List<String> currentResult = new ArrayList<String>();
3.86 +
3.87 + result.put(rootId, currentResult);
3.88 +
3.89 + ClassIndexManager.getDefault().createUsagesQuery(srcRoot.getURL(), true);
3.90 + ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(srcRoot));
3.91 + Set<ElementHandle<TypeElement>> names = new HashSet<ElementHandle<TypeElement>>(cpInfo.getClassIndex().getDeclaredTypes(prefix, nameKind, EnumSet.of(SearchScope.SOURCE)));
3.92 +
3.93 + if (nameKind == NameKind.CAMEL_CASE) {
3.94 + names.addAll(cpInfo.getClassIndex().getDeclaredTypes(prefix, NameKind.CASE_INSENSITIVE_PREFIX, EnumSet.of(SearchScope.SOURCE)));
3.95 + }
3.96 +
3.97 + for (ElementHandle<TypeElement> d : names) {
3.98 + currentResult.add(d.getBinaryName());
3.99 + }
3.100 + }
3.101 +
3.102 + return Pojson.save(result);
3.103 + }
3.104 +
3.105 + //XXX: not really correct, a base directory(-ies?) should be set in the category!
3.106 private static FileObject deepestCommonParent(Set<FileObject> roots) {
3.107 FileObject result = null;
3.108
4.1 --- a/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/UI.java Tue Feb 15 20:14:52 2011 +0100
4.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/UI.java Tue Feb 15 20:16:07 2011 +0100
4.3 @@ -39,6 +39,7 @@
4.4
4.5 package org.netbeans.modules.jackpot30.backend.impl.ui;
4.6
4.7 +import java.util.Comparator;
4.8 import javax.ws.rs.core.Response;
4.9 import java.util.LinkedHashMap;
4.10 import java.util.Map.Entry;
4.11 @@ -154,18 +155,23 @@
4.12
4.13 URI codeURL = new URI("http://localhost:9998/index/cat?path=" + escapeForQuery(path) + "&relative=" + escapeForQuery(relativePath));
4.14 String code = WebUtilities.requestStringResponse(codeURL);
4.15 - URI spansURL = new URI("http://localhost:9998/index/findSpans?path=" + escapeForQuery(path) + "&relativePath=" + escapeForQuery(relativePath) + "&pattern=" + escapeForQuery(pattern));
4.16 - int currentCodePos = 0;
4.17 - for (int[] span : parseSpans(WebUtilities.requestStringResponse(spansURL))) { //XXX: sorted!
4.18 - Map<String, String> occ = new HashMap<String, String>();
4.19 - occ.put("prefix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, span[0])));
4.20 - occ.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1])));
4.21 - occurrences.add(occ);
4.22 - currentCodePos = span[1];
4.23 +
4.24 + if (pattern != null) {
4.25 + URI spansURL = new URI("http://localhost:9998/index/findSpans?path=" + escapeForQuery(path) + "&relativePath=" + escapeForQuery(relativePath) + "&pattern=" + escapeForQuery(pattern));
4.26 + int currentCodePos = 0;
4.27 + for (int[] span : parseSpans(WebUtilities.requestStringResponse(spansURL))) { //XXX: sorted!
4.28 + Map<String, String> occ = new HashMap<String, String>();
4.29 + occ.put("prefix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, span[0])));
4.30 + occ.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1])));
4.31 + occurrences.add(occ);
4.32 + currentCodePos = span[1];
4.33 + }
4.34 +
4.35 + configurationData.put("suffix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, code.length())));
4.36 + } else {
4.37 + configurationData.put("suffix", WebUtilities.escapeForHTMLElement(code));
4.38 }
4.39
4.40 - configurationData.put("suffix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, code.length())));
4.41 -
4.42 return processTemplate("ui-cat.html", configurationData);
4.43 }
4.44
4.45 @@ -238,6 +244,59 @@
4.46 return Response.ok(processTemplate("ui-apply.html", configurationData), "text/html").build();
4.47 }
4.48
4.49 + @GET
4.50 + @Path("/searchType")
4.51 + @Produces("text/html")
4.52 + public String searchType(@QueryParam("path") String path, @QueryParam("prefix") String prefix) throws URISyntaxException, IOException, TemplateException {
4.53 + Map<String, Object> configurationData = new HashMap<String, Object>();
4.54 +
4.55 + configurationData.put("paths", list());
4.56 + configurationData.put("selectedPath", path);
4.57 + configurationData.put("prefix", prefix);
4.58 +
4.59 + if (prefix != null && path != null) {
4.60 + URI u = new URI("http://localhost:9998/index/findType?path=" + escapeForQuery(path) + "&prefix=" + escapeForQuery(prefix));
4.61 + long queryTime = System.currentTimeMillis();
4.62 + @SuppressWarnings("unchecked") //XXX: should not trust something got from the network!
4.63 + Map<String, List<String>> types = Pojson.load(LinkedHashMap.class, u);
4.64 + List<Map<String, Object>> results = new LinkedList<Map<String, Object>>();
4.65 +
4.66 + queryTime = System.currentTimeMillis() - queryTime;
4.67 +
4.68 + for (Entry<String, List<String>> e : types.entrySet()) {
4.69 + for (String fqn : e.getValue()) {
4.70 + Map<String, Object> found = new HashMap<String, Object>(3);
4.71 +
4.72 + found.put("fqn", fqn);
4.73 +
4.74 + if (fqn.contains("$")) {
4.75 + fqn = fqn.substring(0, fqn.indexOf("$"));
4.76 + }
4.77 +
4.78 + found.put("relativePath", e.getKey() + "/" + fqn.replace('.', '/') + ".java");
4.79 +
4.80 + results.add(found);
4.81 + }
4.82 + }
4.83 +
4.84 + Collections.sort(results, new Comparator<Map<String, Object>>() {
4.85 + @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) {
4.86 + return ((String) o1.get("fqn")).compareTo((String) o2.get("fqn"));
4.87 + }
4.88 + });
4.89 +
4.90 + configurationData.put("results", results);
4.91 +
4.92 + Map<String, Object> statistics = new HashMap<String, Object>();
4.93 +
4.94 + statistics.put("queryTime", queryTime);
4.95 +
4.96 + configurationData.put("statistics", statistics);
4.97 + }
4.98 +
4.99 + return processTemplate("ui-findType.html", configurationData);
4.100 + }
4.101 +
4.102 private static final Map<String, String> prefix2SpanName = new LinkedHashMap<String, String>();
4.103
4.104 static {
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/ui-findType.html Tue Feb 15 20:16:07 2011 +0100
5.3 @@ -0,0 +1,28 @@
5.4 +<html>
5.5 +<head>
5.6 + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
5.7 +</head>
5.8 +<body>
5.9 +<form method="get">
5.10 +<label for="path">Project:</label>
5.11 +<select size="1" name="path">");
5.12 + <#list paths as path>
5.13 + <option <#if selectedPath?? && path.segment == selectedPath>selected</#if> value="${path.segment}">
5.14 + ${path.displayName}
5.15 + </option>
5.16 + </#list>
5.17 +</select>
5.18 +<br>
5.19 +<label for="prefix">Type Name:</label><input type="text" name="prefix"<#if prefix??>value="${prefix}"</#if>/><br>
5.20 +<input type="submit" name="Find Candidates"/>
5.21 +</form>
5.22 +
5.23 +<#if results??>
5.24 + Found types:<br>
5.25 + <#list results as result>
5.26 + <a href="/index/ui/show?path=${selectedPath}&relative=${result.relativePath}">${result.fqn}</a><br>
5.27 + </#list>
5.28 +</#if>
5.29 +
5.30 +</body>
5.31 +</html>