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 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); - } }