[568668] JSFileTaskScanner consumes a lot of CPU
diff --git a/web/bundles/org.eclipse.wst.jsdt.web.ui/META-INF/MANIFEST.MF b/web/bundles/org.eclipse.wst.jsdt.web.ui/META-INF/MANIFEST.MF
index 9046401..6788dab 100644
--- a/web/bundles/org.eclipse.wst.jsdt.web.ui/META-INF/MANIFEST.MF
+++ b/web/bundles/org.eclipse.wst.jsdt.web.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name.0
Bundle-SymbolicName: org.eclipse.wst.jsdt.web.ui; singleton:=true
-Bundle-Version: 1.2.100.qualifier
+Bundle-Version: 1.2.200.qualifier
Bundle-Activator: org.eclipse.wst.jsdt.web.ui.internal.JsUIPlugin
Bundle-Vendor: %Bundle-Vendor.0
Bundle-Localization: plugin
diff --git a/web/bundles/org.eclipse.wst.jsdt.web.ui/pom.xml b/web/bundles/org.eclipse.wst.jsdt.web.ui/pom.xml
index f4ac255..0170a2c 100644
--- a/web/bundles/org.eclipse.wst.jsdt.web.ui/pom.xml
+++ b/web/bundles/org.eclipse.wst.jsdt.web.ui/pom.xml
@@ -21,7 +21,7 @@
<groupId>org.eclipse.webtools.sourceediting</groupId>
<artifactId>org.eclipse.wst.jsdt.web.ui</artifactId>
- <version>1.2.100-SNAPSHOT</version>
+ <version>1.2.200-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<!-- added this "constraint" for bug 458962 -->
diff --git a/web/bundles/org.eclipse.wst.jsdt.web.ui/src/org/eclipse/wst/jsdt/web/ui/internal/tasks/JSFileTaskScanner.java b/web/bundles/org.eclipse.wst.jsdt.web.ui/src/org/eclipse/wst/jsdt/web/ui/internal/tasks/JSFileTaskScanner.java
index bd39155..147b515 100644
--- a/web/bundles/org.eclipse.wst.jsdt.web.ui/src/org/eclipse/wst/jsdt/web/ui/internal/tasks/JSFileTaskScanner.java
+++ b/web/bundles/org.eclipse.wst.jsdt.web.ui/src/org/eclipse/wst/jsdt/web/ui/internal/tasks/JSFileTaskScanner.java
@@ -1,8 +1,14 @@
/*******************************************************************************
- * Licensed Materials - Property of IBM
- * © Copyright IBM Corporation 2020. All Rights Reserved.
- * U.S. Government Users Restricted Rights - Use, duplication or disclosure
- * restricted by GSA ADP Schedule Contract with IBM Corp.
+ * Copyright (c) 2020 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.web.ui.internal.tasks;
@@ -10,6 +16,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import org.eclipse.core.filebuffers.FileBuffers;
@@ -22,7 +29,6 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.IRegion;
@@ -94,45 +100,84 @@
textFileBufferManager.connect(file.getFullPath(), LocationKind.IFILE, localMonitor.newChild(1));
IDocument document = textFileBufferManager.getTextFileBuffer(file.getFullPath(), LocationKind.IFILE).getDocument();
IDocumentPartitioner partitioner = JavaScriptPlugin.getDefault().getJavaTextTools().createDocumentPartitioner();
- FindReplaceDocumentAdapter finder = new FindReplaceDocumentAdapter(document);
partitioner.connect(document);
ITypedRegion[] partitions = partitioner.computePartitioning(0, document.getLength());
SubMonitor partitionMonitor = localMonitor.newChild(1);
partitionMonitor.beginTask("", partitions.length);
+ String[] lowerTags = new String[taskTags.length];
+ for (int i = 0; i < taskTags.length; i++) {
+ lowerTags[i] = taskTags[i].getTag().toLowerCase(Locale.US);
+ }
for (int i = 0; i < partitions.length; i++) {
- for (int j = 0; j < taskTags.length; j++) {
- switch (partitions[i].getType()) {
- case IJavaScriptPartitions.JAVA_SINGLE_LINE_COMMENT : {
- IRegion lineMatch = finder.find(partitions[i].getOffset(), taskTags[j].getTag(), true, false, true, false);
- if (lineMatch != null) {
- IRegion lineInfo = document.getLineInformationOfOffset(lineMatch.getOffset());
- int start = lineMatch.getOffset();
- int lengthToEndOfLine = lineInfo.getLength() - (lineMatch.getOffset() - lineInfo.getOffset());
- String text = document.get(start, lengthToEndOfLine).trim();
- Map<String, Object> attributesForNewTaskMarker = createInitialMarkerAttributes(text, document.getLineOfOffset(lineMatch.getOffset()), start, text.length(), taskTags[j].getPriority());
+ int openingLength = 2;
+ switch (partitions[i].getType()) {
+ case IJavaScriptPartitions.JAVA_SINGLE_LINE_COMMENT : {
+ // includes the // leading characters
+ IRegion lineInfo = document.getLineInformationOfOffset(partitions[i].getOffset());
+ int start = partitions[i].getOffset() + openingLength;
+ int lengthToEndOfLine = lineInfo.getOffset() + lineInfo.getLength() - start;
+ String text = document.get(start, lengthToEndOfLine);
+ String lowerText = text.toLowerCase(Locale.US);
+ for (int j = 0; j < lowerTags.length; j++) {
+ if ((lowerText.indexOf(lowerTags[j])) >= 0) {
+ while (start < lineInfo.getOffset() + lineInfo.getLength() && Character.isWhitespace(text.charAt(start - partitions[i].getOffset() - openingLength))) {
+ start++;
+ }
+ Map<String, Object> attributesForNewTaskMarker = createInitialMarkerAttributes(text.trim(), document.getLineOfOffset(partitions[i].getOffset()), start, lineInfo.getOffset() + lineInfo.getLength() - start, taskTags[j].getPriority());
newMarkers.add(attributesForNewTaskMarker);
}
- break;
}
- case IJavaScriptPartitions.JAVA_DOC :
- case IJavaScriptPartitions.JAVA_MULTI_LINE_COMMENT : {
- IRegion tagMatch = finder.find(partitions[i].getOffset(), taskTags[j].getTag(), true, false, true, false);
- while (tagMatch != null && tagMatch.getOffset() + tagMatch.getLength() < partitions[i].getOffset() + partitions[i].getLength()) {
- int start = tagMatch.getOffset();
- IRegion lineInfo = document.getLineInformationOfOffset(tagMatch.getOffset());
- int lengthToEndOfLine = lineInfo.getLength() - (tagMatch.getOffset() - lineInfo.getOffset());
- // shorter of end of line or all but the close of the comment
- lengthToEndOfLine = Math.min(lengthToEndOfLine, partitions[i].getOffset() + partitions[i].getLength() - 2 - start);
- String text = document.get(start, lengthToEndOfLine).trim();
- int lineNumber = document.getLineOfOffset(tagMatch.getOffset());
- Map<String, Object> attributesForNewTaskMarker = createInitialMarkerAttributes(text, lineNumber, start, text.length(), taskTags[j].getPriority());
+ break;
+ }
+ case IJavaScriptPartitions.JAVA_DOC :
+ openingLength = 3;
+ //$FALL-THROUGH$
+ case IJavaScriptPartitions.JAVA_MULTI_LINE_COMMENT : {
+ // first line is possibly only partially a comment, act much like a single line comment
+ int partitionEnd = partitions[i].getOffset() + partitions[i].getLength();
+ // partition includes the opening 2 or 3 /**? and closing two */
+ IRegion lineInformation = document.getLineInformationOfOffset(partitions[i].getOffset());
+ int start = partitions[i].getOffset() + openingLength;
+ int lengthToEndOfCommentLine = Math.min(lineInformation.getOffset() + lineInformation.getLength() - start, partitionEnd);
+ String text = document.get(start, lengthToEndOfCommentLine);
+ String lowerText = text.toLowerCase(Locale.US);
+ for (int j = 0; j < lowerTags.length; j++) {
+ if ((lowerText.indexOf(lowerTags[j])) >= 0) {
+ while (start < lineInformation.getOffset() + lineInformation.getLength() && Character.isWhitespace(text.charAt(start - partitions[i].getOffset() - openingLength))) {
+ start++;
+ }
+ Map<String, Object> attributesForNewTaskMarker = createInitialMarkerAttributes(text.trim(), document.getLineOfOffset(partitions[i].getOffset()), start, lengthToEndOfCommentLine, taskTags[j].getPriority());
newMarkers.add(attributesForNewTaskMarker);
+ }
+ }
+ // subsequent lines
+ int secondLineNumber = document.getLineOfOffset(start) + 1;
+ int lastLineNumber = document.getLineOfOffset(partitionEnd);
+ for (int currentLineNumber = secondLineNumber; currentLineNumber <= lastLineNumber; currentLineNumber++) {
+ lineInformation = document.getLineInformation(currentLineNumber);
+ int applicableLength = lineInformation.getLength();
+ text = document.get(lineInformation.getOffset(), applicableLength);
- tagMatch = finder.find(lineInfo.getOffset() + lineInfo.getLength(), taskTags[j].getTag(), true, false, true, false);
+ // handle a last line that has more after the comment ends
+ if (lineInformation.getOffset() + lineInformation.getLength() > partitionEnd) {
+ applicableLength = partitionEnd - lineInformation.getOffset();
+ text = document.get(lineInformation.getOffset(), applicableLength);
+ while (text.length() > 2 && (text.charAt(text.length() - 1) == '/' || text.charAt(text.length() - 1) == '*')) {
+ text = text.substring(0, text.length() - 1);
+ applicableLength--;
+ }
}
- break;
+
+ lowerText = text.toLowerCase(Locale.US);
+ for (int j = 0; j < lowerTags.length; j++) {
+ int index = 0;
+ if ((index = lowerText.indexOf(lowerTags[j])) >= 0) {
+ Map<String, Object> attributesForNewTaskMarker = createInitialMarkerAttributes(text.substring(index).trim(), currentLineNumber, lineInformation.getOffset() + index, applicableLength - index, taskTags[j].getPriority());
+ newMarkers.add(attributesForNewTaskMarker);
+ }
+ }
}
- default :
+ break;
}
}
partitionMonitor.worked(1);