diff --git a/pom.xml b/pom.xml
index fa95bd4..01ad52a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
de.markiewb.netbeans.plugins
open-file-at-cursor-plugin
- 1.3.0.4-SNAPSHOT
+ 1.3.0.5-SNAPSHOT
nbm
@@ -193,6 +193,8 @@ Features:
<li>[<a href="https://github.com/markiewb/nb-resource-hyperlink-at-cursor/issues/12">Feature 12</a>]: Support fully qualified classnames</li>
<li>[<a href="https://github.com/markiewb/nb-resource-hyperlink-at-cursor/issues/14">Feature 14</a>]: Search for classname in dependencies too (only works for dependencies with sources)</li>
<li>[<a href="https://github.com/markiewb/nb-resource-hyperlink-at-cursor/issues/10">Feature 10</a>]: Find files in same package but different source root</li>
+<li>[<a href="https://github.com/markiewb/nb-resource-hyperlink-at-cursor/issues/16">Issue 16</a>]: Make the hyperlinking faster / use less IO</li>
+
</ul>
<h2>Updates in 1.2.2:</h2>
diff --git a/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResourceHyperlinkProvider.java b/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResourceHyperlinkProvider.java
index 286d3b4..c404904 100644
--- a/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResourceHyperlinkProvider.java
+++ b/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResourceHyperlinkProvider.java
@@ -20,9 +20,11 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
@@ -94,6 +96,8 @@ public class ResourceHyperlinkProvider implements HyperlinkProviderExt {
public static final String MAVEN_TYPE_OTHER = "Resources"; //NOI18N
public static final String MAVEN_TYPE_TEST_OTHER = "TestResources"; //NOI18N
public static final String MAVEN_TYPE_GEN_SOURCES = "GeneratedSources"; //NOI18N
+ public static final Cache cache = new Cache();
+ private static final int EXPIRE_CACHE_IN_SECONDS = 10;
public static void openInEditor(FileObject fileToOpen) {
DataObject fileDO;
@@ -134,8 +138,11 @@ public void preferenceChange(PreferenceChangeEvent evt) {
@Override
public boolean isHyperlinkPoint(Document document, int offset, HyperlinkType type) {
- ResultTO matches = findResources(document, offset);
- return matches.isValid();
+ updateCacheIfNecessary(document, offset);
+ if (null == cache.matches) {
+ return false;
+ }
+ return cache.matches.isValid();
}
private ResultTO findResources(Document document, int offset) {
@@ -183,7 +190,7 @@ private ResultTO findResources(Document document, int offset) {
// StatusDisplayer.getDefault().setStatusText("Path :" + startOffset + "/" + endOffset + "/" + offset + "//" + (offset - startOffset) + "=" + innerSelectedText);
Set findFiles = findFiles(doc, linkTarget);
if (findFiles.isEmpty()) {
- return ResultTO.createEmpty();
+ return ResultTO.createEmpty(startOffset, endOffset);
}
return ResultTO.create(startOffset, endOffset, linkTarget, findFiles);
}
@@ -312,7 +319,8 @@ private FileObject getMatchingFileInCurrentDirectory(Document doc, String path)
@Override
public int[] getHyperlinkSpan(Document doc, int offset, HyperlinkType type) {
- ResultTO matches = findResources(doc, offset);
+ updateCacheIfNecessary(doc, offset);
+ ResultTO matches = cache.matches;
if (matches.isValid()) {
return new int[]{matches.startOffsetInLiteral, matches.endOffsetInLiteral};
} else {
@@ -320,9 +328,47 @@ public int[] getHyperlinkSpan(Document doc, int offset, HyperlinkType type) {
}
}
+ private void updateCacheIfNecessary(Document doc, int offset) {
+ boolean isSameRequest = false;
+ boolean timeExpired = false;
+ FileObject fileObject = NbEditorUtilities.getFileObject(doc);
+ if (null != cache.request_filePath && null != cache.request_lastUpdated) {
+ final boolean sameFile = fileObject.getPath().equals(cache.request_filePath);
+ //if there was a previously match
+ boolean withinOffSetRange = cache.matches.startOffsetInLiteral <= offset && offset <= cache.matches.endOffsetInLiteral;
+ //if there was not a previously match
+ final boolean sameOffset = offset == cache.request_offset;
+
+ Calendar nowMinus2Seconds = java.util.Calendar.getInstance();
+ nowMinus2Seconds.roll(Calendar.SECOND, -1 * EXPIRE_CACHE_IN_SECONDS);
+ timeExpired = cache.request_lastUpdated.before(nowMinus2Seconds.getTime());
+
+ isSameRequest = sameFile && (withinOffSetRange || sameOffset);
+
+ }
+ if (isSameRequest && !timeExpired) {
+
+ } else {
+ cache.request_filePath = fileObject.getPath();
+ cache.request_offset = offset;
+
+ cache.request_lastUpdated = new Date();
+ ResultTO matches = findResources(doc, offset);
+ cache.matches = matches;
+ System.out.println(String.format("cacheMiss = %s %s", offset, fileObject));
+
+ }
+
+ }
+
@Override
public void performClickAction(Document doc, int position, HyperlinkType type) {
- ResultTO matches = findResources(doc, position);
+ updateCacheIfNecessary(doc, position);
+ if (null == cache.matches) {
+ return;
+ }
+
+ ResultTO matches = cache.matches;
if (matches.isValid()) {
Collection foundMatches = matches.foundFiles;
final Project project = FileOwnerQuery.getOwner(NbEditorUtilities.getFileObject(doc));
@@ -378,7 +424,9 @@ public Set getSupportedHyperlinkTypes() {
@Override
public String getTooltipText(Document doc, int offset, HyperlinkType type) {
- ResultTO result = findResources(doc, offset);
+ updateCacheIfNecessary(doc, offset);
+
+ ResultTO result = cache.matches;
if (!result.isValid()) {
return null;
}
@@ -397,6 +445,9 @@ private Collection findByClassName(FileObject fo, String fqnClassNam
ClassPath bootCp = ClassPath.getClassPath(fo, ClassPath.BOOT);
ClassPath compileCp = ClassPath.getClassPath(fo, ClassPath.COMPILE);
ClassPath sourcePath = ClassPath.getClassPath(fo, ClassPath.SOURCE);
+ if (null == bootCp || null == compileCp || null == sourcePath) {
+ return files;
+ }
final ClasspathInfo info = ClasspathInfo.create(bootCp, compileCp, sourcePath);
int lastIndexOfDot = fqnClassName.lastIndexOf(".");
String simpleClassName;
@@ -455,7 +506,7 @@ private Collection extends FileObject> getMatchingFilesFromOtherSourceRootsBut
String packageName = null;
for (SourceGroup sourceGroup : getAllSourceGroups(p)) {
//SourceGroup: c:/myprojects/project/src/main/java/
- //OriginFolder: c:/myprojects/project/src/main/java/com/foo/impl
+ //OriginFolder: c:/myprojects/project/src/main/java/com/foo/impl
//Result: com/foo/impl (!=null so we found the source root)
final FileObject rootFolder = sourceGroup.getRootFolder();
if (null == rootFolder) {
@@ -501,6 +552,14 @@ private List getAllSourceGroups(Project p) {
return list;
}
+ static class Cache {
+
+ int request_offset;
+ Date request_lastUpdated;
+ String request_filePath;
+ T matches;
+ }
+
private static class FileObjectTuple extends Pair {
public FileObjectTuple(FileObject first, String second) {
diff --git a/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResultTO.java b/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResultTO.java
index 5e92d3f..c0e10c1 100644
--- a/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResultTO.java
+++ b/src/main/java/de/markiewb/netbeans/plugins/resourcehyperlink/ResultTO.java
@@ -25,28 +25,31 @@
* @author markiewb
*/
class ResultTO {
+
+ static ResultTO createEmpty(int startOffset, int endOffset) {
+ return new ResultTO(startOffset, endOffset, null, Collections.emptySet());
+ }
+ static ResultTO createEmpty() {
+ return new ResultTO(-1, -1, null, Collections.emptySet());
+ }
+ static ResultTO create(int startOffset, int endOffset, String linkTarget, Collection foundFiles) {
+ return new ResultTO(startOffset, endOffset, linkTarget, foundFiles);
+ }
int startOffsetInLiteral;
int endOffsetInLiteral;
String linkTarget;
+ Collection foundFiles;
ResultTO(int startOffset, int endOffset, String linkTarget, Collection foundFiles) {
this.startOffsetInLiteral = startOffset;
this.endOffsetInLiteral = endOffset;
this.linkTarget = linkTarget;
this.foundFiles = foundFiles;
}
- Collection foundFiles;
boolean isValid() {
return !foundFiles.isEmpty();
}
- static ResultTO createEmpty() {
- return new ResultTO(-1, -1, null, Collections.emptySet());
- }
-
- static ResultTO create(int startOffset, int endOffset, String linkTarget, Collection foundFiles) {
- return new ResultTO(startOffset, endOffset, linkTarget, foundFiles);
- }
}