Skip to content

Commit 650d552

Browse files
committed
Reapply "LSP: Speed up publish diagnostics on project scan."
This reverts commit 90aeca3.
1 parent e38f618 commit 650d552

File tree

12 files changed

+291
-46
lines changed

12 files changed

+291
-46
lines changed

enterprise/micronaut/src/org/netbeans/modules/micronaut/hints/MicronautConfigErrorProvider.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,11 @@ public void run(ResultIterator it) throws Exception {
109109
scan(text, scanner.scan((ParserResult) result), structure -> {
110110
int start = (int) structure.getPosition();
111111
int end = (int) structure.getEndPosition();
112+
String[] startLines = text.substring(0, start).split("\n");
113+
String[] endLines = text.substring(0, end).split("\n");
112114
diags.add(Diagnostic.Builder.create(() -> start, () -> end, Bundle.ERR_PropertyWithoutValue())
113115
.setSeverity(Diagnostic.Severity.Warning)
114-
.setCode(ERR_CODE_PREFIX + text.substring(0, start).split("\n").length)
116+
.setCode(ERR_CODE_PREFIX + startLines.length + ',' + (startLines[startLines.length - 1].length() + 1) + '-' + endLines.length + ',' + (endLines[endLines.length - 1].length() + 1))
115117
.build());
116118
});
117119
}
@@ -135,7 +137,7 @@ public void run(ResultIterator it) throws Exception {
135137
int end = offset + line.length();
136138
diags.add(Diagnostic.Builder.create(() -> start, () -> end, Bundle.ERR_PropertyWithoutValue())
137139
.setSeverity(Diagnostic.Severity.Warning)
138-
.setCode(ERR_CODE_PREFIX + (i + 1))
140+
.setCode(ERR_CODE_PREFIX + (i + 1) + ",1-" + (i + 1) + "," + line.length() + 1)
139141
.build());
140142
}
141143
}
@@ -205,7 +207,19 @@ public ErrorsCache.ErrorKind getKind(Diagnostic t) {
205207
}
206208
@Override
207209
public int getLineNumber(Diagnostic t) {
208-
return Integer.parseInt(t.getCode().substring(ERR_CODE_PREFIX.length()));
210+
String text = t.getCode().substring(ERR_CODE_PREFIX.length());
211+
int idx = text.indexOf(',');
212+
return Integer.parseInt(text.substring(0, idx));
213+
}
214+
@Override
215+
public ErrorsCache.Range getRange(Diagnostic t) {
216+
String text = t.getCode().substring(ERR_CODE_PREFIX.length());
217+
int idx1 = text.indexOf(',');
218+
int idx2 = text.indexOf('-');
219+
int idx3 = text.indexOf(',', idx2);
220+
ErrorsCache.Position start = new ErrorsCache.Position(Integer.parseInt(text.substring(0, idx1)), Integer.parseInt(text.substring(idx1 + 1, idx2)));
221+
ErrorsCache.Position end = new ErrorsCache.Position(Integer.parseInt(text.substring(idx2 + 1, idx3)), Integer.parseInt(text.substring(idx3 + 1, text.length())));
222+
return new ErrorsCache.Range(start, end);
209223
}
210224
@Override
211225
public String getMessage(Diagnostic t) {

ide/csl.api/src/org/netbeans/modules/csl/core/TLIndexerFactory.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,29 @@ public int getLineNumber(SimpleError error) {
178178
return lineNumber;
179179
}
180180
@Override
181+
public ErrorsCache.Range getRange(SimpleError error) {
182+
int originalOffset = error.getStartPosition(); //snapshot offset
183+
int lineNumber = 1;
184+
int colNumber = 1;
185+
if (originalOffset >= 0) {
186+
int idx = Collections.binarySearch(lineStartOffsets, originalOffset);
187+
if (idx < 0) {
188+
// idx == (-(insertion point) - 1) -> (insertion point) == -idx - 1
189+
int ln = -idx - 1;
190+
assert ln >= 1 && ln <= lineStartOffsets.size() :
191+
"idx=" + idx + ", lineNumber=" + ln + ", lineStartOffsets.size()=" + lineStartOffsets.size(); //NOI18N
192+
if (ln >= 1 && ln <= lineStartOffsets.size()) {
193+
lineNumber = ln;
194+
colNumber = originalOffset - lineStartOffsets.get(ln - 1);
195+
}
196+
} else {
197+
lineNumber = idx + 1;
198+
}
199+
}
200+
201+
return new ErrorsCache.Range(new ErrorsCache.Position(lineNumber, colNumber), null);
202+
}
203+
@Override
181204
public String getMessage(SimpleError error) {
182205
return error.getDisplayName();
183206
}

ide/parsing.indexing/apichanges.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,20 @@ is the proper place.
8787
<!-- ACTUAL CHANGES BEGIN HERE: -->
8888

8989
<changes>
90+
<change id="ErrorsCache.getErrors">
91+
<api name="IndexingAPI"/>
92+
<summary>Added method to ErrorsCache to return all errors or warnings for the given file</summary>
93+
<version major="9" minor="39"/>
94+
<date day="6" month="9" year="2024"/>
95+
<author login="dbalek"/>
96+
<compatibility source="compatible" binary="compatible" semantic="compatible" addition="yes"/>
97+
<description>
98+
<p>
99+
Added the <a href="@TOP@/org/netbeans/modules/parsing/spi/indexing/ErrorsCache.html#getErrors-org.openide.filesystems.FileObject-org.netbeans.modules.parsing.spi.indexing.ErrorsCache.ReverseConvertor-">getErrors()</a> method to return errors or warnings for the given file.
100+
</p>
101+
</description>
102+
<class package="org.netbeans.modules.parsing.spi.indexing" name="ErrorsCache"/>
103+
</change>
90104
<change id="ErrorsCache.getAllFilesWithRecord">
91105
<api name="IndexingAPI"/>
92106
<summary>Added method to ErrorsCache to return all files with error or warning</summary>

ide/parsing.indexing/nbproject/project.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
javac.source=1.8
17+
javac.release=17
1818
javac.compilerargs=-Xlint -Xlint:-serial
1919
spec.version.base=9.39.0
2020
is.autoload=true

ide/parsing.indexing/src/org/netbeans/modules/parsing/impl/indexing/errors/TaskCache.java

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import java.util.Set;
4646
import java.util.logging.Level;
4747
import java.util.logging.Logger;
48+
import java.util.regex.Matcher;
49+
import java.util.regex.Pattern;
4850
import org.netbeans.api.annotations.common.NonNull;
4951
import org.netbeans.api.java.classpath.ClassPath;
5052
import org.netbeans.api.project.FileOwnerQuery;
@@ -53,8 +55,10 @@
5355
import org.netbeans.modules.parsing.impl.indexing.PathRegistry;
5456
import org.netbeans.modules.parsing.impl.indexing.URLCache;
5557
import org.netbeans.modules.parsing.impl.indexing.implspi.CacheFolderProvider;
58+
import org.netbeans.modules.parsing.spi.indexing.ErrorsCache;
5659
import org.netbeans.modules.parsing.spi.indexing.ErrorsCache.Convertor;
5760
import org.netbeans.modules.parsing.spi.indexing.ErrorsCache.ErrorKind;
61+
import org.netbeans.modules.parsing.spi.indexing.ErrorsCache.ReverseConvertor;
5862
import org.netbeans.modules.parsing.spi.indexing.Indexable;
5963
import org.netbeans.spi.tasklist.Task;
6064
import org.openide.filesystems.FileObject;
@@ -77,6 +81,10 @@ public class TaskCache {
7781

7882
private static final Logger LOG = Logger.getLogger(TaskCache.class.getName());
7983

84+
// Matches the diagnostic range with both the start and the end positions specified (e.g. 1,2-1,7)
85+
// or with only the start position specified (e.g. 1,2) where positions are written in a form line,column
86+
private static final Pattern PATTERN = Pattern.compile("(\\d*),(\\d*)(?:-(\\d*),(\\d*))?");
87+
8088
static {
8189
// LOG.setLevel(Level.FINEST);
8290
}
@@ -103,17 +111,31 @@ private String getTaskType( ErrorKind k ) {
103111
}
104112
return null;
105113
}
106-
114+
115+
private ReverseConvertor<Task> getTaskConvertor(FileObject file) {
116+
return (kind, range, message) -> {
117+
String severity = getTaskType(kind);
118+
if (null != severity) {
119+
return Task.create(file, severity, message, range.start().line());
120+
}
121+
return null;
122+
};
123+
}
124+
107125
public List<Task> getErrors(FileObject file) {
108-
List<Task> result = new LinkedList<Task>();
126+
return getErrors(file, getTaskConvertor(file));
127+
}
128+
129+
public <T> List<T> getErrors(FileObject file, ReverseConvertor<T> convertor) {
130+
List<T> result = new LinkedList<>();
109131

110-
result.addAll(getErrors(file, ERR_EXT));
111-
result.addAll(getErrors(file, WARN_EXT));
132+
result.addAll(getErrors(file, convertor, ERR_EXT));
133+
result.addAll(getErrors(file, convertor, WARN_EXT));
112134

113135
return result;
114136
}
115137

116-
private List<Task> getErrors(FileObject file, String ext) {
138+
private <T> List<T> getErrors(FileObject file, ReverseConvertor<T> convertor, String ext) {
117139
LOG.log(Level.FINE, "getErrors, file={0}, ext={1}", new Object[] {FileUtil.getFileDisplayName(file), ext}); //NOI18N
118140

119141
try {
@@ -122,16 +144,16 @@ private List<Task> getErrors(FileObject file, String ext) {
122144
LOG.log(Level.FINE, "getErrors, error file={0}", input == null ? "null" : input.getAbsolutePath()); //NOI18N
123145

124146
if (input == null || !input.canRead())
125-
return Collections.<Task>emptyList();
147+
return Collections.emptyList();
126148

127149
input.getParentFile().mkdirs();
128150

129-
return loadErrors(input, file);
151+
return loadErrors(input, convertor);
130152
} catch (IOException e) {
131153
LOG.log(Level.FINE, null, e);
132154
}
133155

134-
return Collections.<Task>emptyList();
156+
return Collections.emptyList();
135157
}
136158

137159
private <T> boolean dumpErrors(File output, Iterable<? extends T> errors, Convertor<T> convertor, boolean interestedInReturnValue) throws IOException {
@@ -144,7 +166,15 @@ private <T> boolean dumpErrors(File output, Iterable<? extends T> errors, Conver
144166
for (T err : errors) {
145167
pw.print(convertor.getKind(err).name());
146168
pw.print(':'); //NOI18N
147-
pw.print(convertor.getLineNumber(err));
169+
ErrorsCache.Range range = convertor.getRange(err);
170+
if (range != null) {
171+
pw.print(String.format("%d,%d", range.start().line(), range.start().column()));
172+
if (range.end() != null) {
173+
pw.print(String.format("-%d,%d", range.end().line(), range.end().column()));
174+
}
175+
} else {
176+
pw.print(convertor.getLineNumber(err));
177+
}
148178
pw.print(':'); //NOI18N
149179

150180
String description = convertor.getMessage(err);
@@ -200,6 +230,7 @@ public <T> void dumpErrors(final URL root, final Indexable i, final Iterable<? e
200230
}
201231
});
202232
} catch (IOException ex) {
233+
Exceptions.attachMessage(ex, "can't dump errors for: " + String.valueOf(i));
203234
Exceptions.printStackTrace(ex);
204235
}
205236
}
@@ -255,8 +286,8 @@ private <T> void dumpErrors(TransactionContext c, URL root, Indexable i, Iterabl
255286
c.rootsToRefresh.add(root);
256287
}
257288

258-
private List<Task> loadErrors(File input, FileObject file) throws IOException {
259-
List<Task> result = new LinkedList<Task>();
289+
private <T> List<T> loadErrors(File input, ReverseConvertor<T> convertor) throws IOException {
290+
List<T> result = new LinkedList<>();
260291
BufferedReader pw = new BufferedReader(new InputStreamReader(new FileInputStream(input), StandardCharsets.UTF_8));
261292
String line;
262293

@@ -277,18 +308,26 @@ private List<Task> loadErrors(File input, FileObject file) throws IOException {
277308
continue;
278309
}
279310

280-
int lineNumber = Integer.parseInt(parts[1]);
281-
String message = parts[2];
311+
ErrorsCache.Range range;
312+
Matcher matcher = PATTERN.matcher(parts[1]);
313+
if (matcher.matches()) {
314+
ErrorsCache.Position start = new ErrorsCache.Position(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)));
315+
ErrorsCache.Position end = matcher.group(3) != null && matcher.group(4) != null ? new ErrorsCache.Position(Integer.parseInt(matcher.group(3)), Integer.parseInt(matcher.group(4))) : null;
316+
range = new ErrorsCache.Range(start, end);
317+
} else {
318+
int lineNumber = Integer.parseInt(parts[1]);
319+
range = new ErrorsCache.Range(new ErrorsCache.Position(lineNumber, 1), null);
320+
}
282321

283-
message = message.replaceAll("\\\\d", ":"); //NOI18N
284-
message = message.replaceAll("\\\\n", " "); //NOI18N
285-
message = message.replaceAll("\\\\\\\\", "\\\\"); //NOI18N
322+
String message = parts[2];
286323

287-
String severity = getTaskType(kind);
324+
message = message.replace("\\d", ":") //NOI18N
325+
.replace("\\n", "\n") //NOI18N
326+
.replace("\\\\", "\\"); //NOI18N
288327

289-
if (null != severity) {
290-
Task err = Task.create(file, severity, message, lineNumber);
291-
result.add(err);
328+
T item = convertor.get(kind, range, message);
329+
if (null != item) {
330+
result.add(item);
292331
}
293332
}
294333

@@ -351,12 +390,12 @@ private List<URL> getAllFilesWithRecord(URL root, boolean onlyErrors) throws IOE
351390
public List<URL> getAllFilesInError(URL root) throws IOException {
352391
return getAllFilesWithRecord(root, true);
353392
}
354-
393+
355394
public boolean isInError(FileObject file, boolean recursive) {
356395
LOG.log(Level.FINE, "file={0}, recursive={1}", new Object[] {file, Boolean.valueOf(recursive)}); //NOI18N
357396

358397
if (file.isData()) {
359-
return !getErrors(file, ERR_EXT).isEmpty();
398+
return !getErrors(file, getTaskConvertor(file), ERR_EXT).isEmpty();
360399
} else {
361400
try {
362401
ClassPath cp = Utilities.getSourceClassPathFor (file);

ide/parsing.indexing/src/org/netbeans/modules/parsing/spi/indexing/ErrorsCache.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.net.URL;
2424
import java.util.Collection;
2525
import java.util.Collections;
26+
import java.util.List;
2627
import org.netbeans.modules.parsing.impl.indexing.errors.TaskCache;
2728
import org.openide.filesystems.FileObject;
2829

@@ -74,12 +75,46 @@ public static Collection<? extends URL> getAllFilesWithRecord(URL root) throws I
7475
return Collections.unmodifiableCollection(TaskCache.getDefault().getAllFilesWithRecord(root));
7576
}
7677

77-
/**Getter for properties of the given error description.
78+
/**Return all errors or warnings for the given file
79+
*
80+
* @param file file for which the errors are being retrieved
81+
* @param convertor constructor of {@code T} instances from error description properties
82+
* @return errors or warnings
83+
* @since 9.39
84+
*/
85+
public static <T> List<T> getErrors(FileObject file, ReverseConvertor<T> convertor) throws IOException {
86+
return Collections.unmodifiableList(TaskCache.getDefault().getErrors(file, convertor));
87+
}
88+
89+
/**Position in a text expressed as 1-based line and character offset.
90+
* @since 9.39
91+
*/
92+
public record Position(int line, int column) {}
93+
94+
/**Range in a text expressed as (1-based) start and end positions.
95+
* @since 9.39
96+
*/
97+
public record Range(Position start, Position end) {}
98+
99+
/**Getter for properties of the given error description including the range.
78100
*/
79101
public static interface Convertor<T> {
80102
public ErrorKind getKind(T t);
81103
public int getLineNumber(T t);
82104
public String getMessage(T t);
105+
/**
106+
* @since 9.39
107+
*/
108+
public default Range getRange(T t) {
109+
return null;
110+
}
111+
}
112+
113+
/**Constructor of error description from the properties.
114+
* @since 9.39
115+
*/
116+
public static interface ReverseConvertor<T> {
117+
public T get(ErrorKind kind, Range range, String message);
83118
}
84119

85120
public static enum ErrorKind {

0 commit comments

Comments
 (0)