diff --git a/.gitignore b/.gitignore index a5ff17a..904a7d0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ target/ bin/ **/lib/ -maven-wrapper.jar \ No newline at end of file +maven-wrapper.jar +cmd/repository/ +cmd/workspace/ \ No newline at end of file diff --git a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/EdgeBuilder.java b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/EdgeBuilder.java index 970ddb2..fcb650b 100644 --- a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/EdgeBuilder.java +++ b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/EdgeBuilder.java @@ -63,4 +63,8 @@ public Edge documentSymbols(Vertex from, Vertex to) { public Edge refersTo(Vertex from, Vertex to) { return new Edge(generator.next(), Edge.REFERSTO, from.getId(), to.getId()); } + + public Edge diagnostic(Vertex from, Vertex to) { + return new Edge(generator.next(), Edge.T_DIAGNOSTIC, from.getId(), to.getId()); + } } diff --git a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/Indexer.java b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/Indexer.java index 8ea8f63..b216a66 100644 --- a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/Indexer.java +++ b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/Indexer.java @@ -38,6 +38,7 @@ import com.microsoft.java.lsif.core.internal.protocol.Document; import com.microsoft.java.lsif.core.internal.protocol.Project; import com.microsoft.java.lsif.core.internal.visitors.DefinitionVisitor; +import com.microsoft.java.lsif.core.internal.visitors.DiagnosticVisitor; import com.microsoft.java.lsif.core.internal.visitors.DocumentVisitor; import com.microsoft.java.lsif.core.internal.visitors.HoverVisitor; import com.microsoft.java.lsif.core.internal.visitors.ImplementationsVisitor; @@ -136,6 +137,10 @@ private void buildIndex(IPath path, IProgressMonitor monitor, Emitter emitter) { vis.setContext(currentContext); cu.accept(vis); } + + // Dump diagnostic information + DiagnosticVisitor diagnosticVisitor = new DiagnosticVisitor(currentContext, cu); + diagnosticVisitor.enlist(); } } } diff --git a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/VertexBuilder.java b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/VertexBuilder.java index 362377a..7a08d4f 100644 --- a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/VertexBuilder.java +++ b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/indexer/VertexBuilder.java @@ -7,6 +7,7 @@ import java.util.List; +import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.DocumentSymbol; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.Location; @@ -14,6 +15,7 @@ import com.microsoft.java.lsif.core.internal.JdtlsUtils; import com.microsoft.java.lsif.core.internal.protocol.DefinitionResult; +import com.microsoft.java.lsif.core.internal.protocol.DiagnosticResult; import com.microsoft.java.lsif.core.internal.protocol.Document; import com.microsoft.java.lsif.core.internal.protocol.DocumentSymbolResult; import com.microsoft.java.lsif.core.internal.protocol.HoverResult; @@ -83,4 +85,8 @@ public ImplementationResult implementationResult(List> public DocumentSymbolResult documentSymbolResult(List symbols) { return new DocumentSymbolResult(generator.next(), symbols); } + + public DiagnosticResult diagnosticResult(List diagnostics) { + return new DiagnosticResult(generator.next(), diagnostics); + } } diff --git a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/protocol/DiagnosticResult.java b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/protocol/DiagnosticResult.java new file mode 100644 index 0000000..4ae5718 --- /dev/null +++ b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/protocol/DiagnosticResult.java @@ -0,0 +1,25 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + + +package com.microsoft.java.lsif.core.internal.protocol; + +import java.util.List; + +import org.eclipse.lsp4j.Diagnostic; + +public class DiagnosticResult extends Vertex { + + private List result; + + public DiagnosticResult(String id, List result) { + super(id, Vertex.DIAGNOSTICRESULT); + this.result = result; + } + + public List getResult() { + return this.result; + } +} diff --git a/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/visitors/DiagnosticVisitor.java b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/visitors/DiagnosticVisitor.java new file mode 100644 index 0000000..a26a6e2 --- /dev/null +++ b/com.microsoft.java.lsif.core/src/com/microsoft/java/lsif/core/internal/visitors/DiagnosticVisitor.java @@ -0,0 +1,141 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + + +package com.microsoft.java.lsif.core.internal.visitors; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.IJavaModelMarker; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; +import org.eclipse.jdt.ls.core.internal.handlers.JsonRpcHelpers; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DiagnosticSeverity; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.Range; +import org.eclipse.m2e.core.internal.IMavenConstants; + +import com.microsoft.java.lsif.core.internal.LanguageServerIndexerPlugin; +import com.microsoft.java.lsif.core.internal.emitter.Emitter; +import com.microsoft.java.lsif.core.internal.indexer.IndexerContext; +import com.microsoft.java.lsif.core.internal.indexer.LsifService; +import com.microsoft.java.lsif.core.internal.protocol.DiagnosticResult; +import com.microsoft.java.lsif.core.internal.protocol.Document; + +public class DiagnosticVisitor extends ProtocolVisitor { + + private CompilationUnit cu; + + public DiagnosticVisitor(IndexerContext context, CompilationUnit cu) { + this.setContext(context); + this.cu = cu; + } + + public void enlist() { + Emitter emitter = this.getContext().getEmitter(); + LsifService lsif = this.getContext().getLsif(); + Document docVertex = this.getContext().getDocVertex(); + IResource resource = cu.getJavaElement().getResource(); + if (resource == null || !resource.exists()) { + LanguageServerIndexerPlugin.logError("Cannot find resource for: " + cu.getJavaElement().getElementName()); + return; + } + IMarker[] markers = null; + IDocument document = null; + try { + IMarker[] javaMarkers = resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, + IResource.DEPTH_ONE); + IMarker[] taskMarkers = resource.findMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_ONE); + int totalLength = javaMarkers.length + taskMarkers.length; + if (totalLength == 0) { + return; + } + markers = Arrays.copyOf(javaMarkers, javaMarkers.length + taskMarkers.length); + System.arraycopy(taskMarkers, 0, markers, javaMarkers.length, taskMarkers.length); + document = JsonRpcHelpers.toDocument(cu.getJavaElement().getOpenable().getBuffer()); + } catch (CoreException ex) { + LanguageServerIndexerPlugin.logException("Exception when dumping diagnostics ", ex); + return; + } + + if (document == null) { + LanguageServerIndexerPlugin + .logError("Cannot parse the document for: " + cu.getJavaElement().getElementName()); + return; + } + + List diagnostics = toDiagnosticsArray(document, markers); + DiagnosticResult diagnosticResult = lsif.getVertexBuilder().diagnosticResult(diagnostics); + emitter.emit(diagnosticResult); + emitter.emit(lsif.getEdgeBuilder().diagnostic(docVertex, diagnosticResult)); + } + + private List toDiagnosticsArray(IDocument document, IMarker[] markers) { + List diagnostics = Stream.of(markers).map(m -> toDiagnostic(document, m)).filter(d -> d != null) + .collect(Collectors.toList()); + return diagnostics; + } + + private static Diagnostic toDiagnostic(IDocument document, IMarker marker) { + if (marker == null || !marker.exists()) { + return null; + } + Diagnostic d = new Diagnostic(); + d.setSource(JavaLanguageServerPlugin.SERVER_SOURCE_ID); + d.setMessage(marker.getAttribute(IMarker.MESSAGE, "")); + d.setCode(String.valueOf(marker.getAttribute(IJavaModelMarker.ID, 0))); + d.setSeverity(convertSeverity(marker.getAttribute(IMarker.SEVERITY, -1))); + d.setRange(convertRange(document, marker)); + return d; + } + + private static Range convertRange(IDocument document, IMarker marker) { + int line = marker.getAttribute(IMarker.LINE_NUMBER, -1) - 1; + int cStart = 0; + int cEnd = 0; + try { + // Buildship doesn't provide markers for gradle files, Maven does + if (marker.isSubtypeOf(IMavenConstants.MARKER_ID)) { + cStart = marker.getAttribute(IMavenConstants.MARKER_COLUMN_START, -1); + cEnd = marker.getAttribute(IMavenConstants.MARKER_COLUMN_END, -1); + } else { + int lineOffset = 0; + try { + lineOffset = document.getLineOffset(line); + } catch (BadLocationException unlikelyException) { + JavaLanguageServerPlugin.logException(unlikelyException.getMessage(), unlikelyException); + return new Range(new Position(line, 0), new Position(line, 0)); + } + cEnd = marker.getAttribute(IMarker.CHAR_END, -1) - lineOffset; + cStart = marker.getAttribute(IMarker.CHAR_START, -1) - lineOffset; + } + } catch (CoreException e) { + LanguageServerIndexerPlugin.logException(e.getMessage(), e); + } + cStart = Math.max(0, cStart); + cEnd = Math.max(0, cEnd); + + return new Range(new Position(line, cStart), new Position(line, cEnd)); + } + + private static DiagnosticSeverity convertSeverity(int severity) { + if (severity == IMarker.SEVERITY_ERROR) { + return DiagnosticSeverity.Error; + } + if (severity == IMarker.SEVERITY_WARNING) { + return DiagnosticSeverity.Warning; + } + return DiagnosticSeverity.Information; + } +}