|
| 1 | +/* -------------------------------------------------------------------------------------------- |
| 2 | + * Copyright (c) Microsoft Corporation. All rights reserved. |
| 3 | + * Licensed under the MIT License. See License.txt in the project root for license information. |
| 4 | + * ------------------------------------------------------------------------------------------ */ |
| 5 | + |
| 6 | + |
| 7 | +package com.microsoft.java.lsif.core.internal.visitors; |
| 8 | + |
| 9 | +import java.util.Arrays; |
| 10 | +import java.util.List; |
| 11 | +import java.util.stream.Collectors; |
| 12 | +import java.util.stream.Stream; |
| 13 | + |
| 14 | +import org.eclipse.core.resources.IMarker; |
| 15 | +import org.eclipse.core.resources.IResource; |
| 16 | +import org.eclipse.core.runtime.CoreException; |
| 17 | +import org.eclipse.jdt.core.IJavaModelMarker; |
| 18 | +import org.eclipse.jdt.core.dom.CompilationUnit; |
| 19 | +import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; |
| 20 | +import org.eclipse.jdt.ls.core.internal.handlers.JsonRpcHelpers; |
| 21 | +import org.eclipse.jface.text.BadLocationException; |
| 22 | +import org.eclipse.jface.text.IDocument; |
| 23 | +import org.eclipse.lsp4j.Diagnostic; |
| 24 | +import org.eclipse.lsp4j.DiagnosticSeverity; |
| 25 | +import org.eclipse.lsp4j.Position; |
| 26 | +import org.eclipse.lsp4j.Range; |
| 27 | +import org.eclipse.m2e.core.internal.IMavenConstants; |
| 28 | + |
| 29 | +import com.microsoft.java.lsif.core.internal.LanguageServerIndexerPlugin; |
| 30 | +import com.microsoft.java.lsif.core.internal.emitter.Emitter; |
| 31 | +import com.microsoft.java.lsif.core.internal.indexer.IndexerContext; |
| 32 | +import com.microsoft.java.lsif.core.internal.indexer.LsifService; |
| 33 | +import com.microsoft.java.lsif.core.internal.protocol.DiagnosticResult; |
| 34 | +import com.microsoft.java.lsif.core.internal.protocol.Document; |
| 35 | + |
| 36 | +public class DiagnosticVisitor extends ProtocolVisitor { |
| 37 | + |
| 38 | + private CompilationUnit cu; |
| 39 | + |
| 40 | + public DiagnosticVisitor(IndexerContext context, CompilationUnit cu) { |
| 41 | + this.setContext(context); |
| 42 | + this.cu = cu; |
| 43 | + } |
| 44 | + |
| 45 | + public void enlist() { |
| 46 | + Emitter emitter = this.getContext().getEmitter(); |
| 47 | + LsifService lsif = this.getContext().getLsif(); |
| 48 | + Document docVertex = this.getContext().getDocVertex(); |
| 49 | + IResource resource = cu.getJavaElement().getResource(); |
| 50 | + if (resource == null || !resource.exists()) { |
| 51 | + LanguageServerIndexerPlugin.logError("Cannot find resource for: " + cu.getJavaElement().getElementName()); |
| 52 | + return; |
| 53 | + } |
| 54 | + IMarker[] markers = null; |
| 55 | + IDocument document = null; |
| 56 | + try { |
| 57 | + IMarker[] javaMarkers = resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, |
| 58 | + IResource.DEPTH_ONE); |
| 59 | + IMarker[] taskMarkers = resource.findMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_ONE); |
| 60 | + int totalLength = javaMarkers.length + taskMarkers.length; |
| 61 | + if (totalLength == 0) { |
| 62 | + return; |
| 63 | + } |
| 64 | + markers = Arrays.copyOf(javaMarkers, javaMarkers.length + taskMarkers.length); |
| 65 | + System.arraycopy(taskMarkers, 0, markers, javaMarkers.length, taskMarkers.length); |
| 66 | + document = JsonRpcHelpers.toDocument(cu.getJavaElement().getOpenable().getBuffer()); |
| 67 | + } catch (CoreException ex) { |
| 68 | + LanguageServerIndexerPlugin.logException("Exception when dumping diagnostics ", ex); |
| 69 | + return; |
| 70 | + } |
| 71 | + |
| 72 | + if (document == null) { |
| 73 | + LanguageServerIndexerPlugin |
| 74 | + .logError("Cannot parse the document for: " + cu.getJavaElement().getElementName()); |
| 75 | + return; |
| 76 | + } |
| 77 | + |
| 78 | + List<Diagnostic> diagnostics = toDiagnosticsArray(document, markers); |
| 79 | + DiagnosticResult diagnosticResult = lsif.getVertexBuilder().diagnosticResult(diagnostics); |
| 80 | + emitter.emit(diagnosticResult); |
| 81 | + emitter.emit(lsif.getEdgeBuilder().diagnostic(docVertex, diagnosticResult)); |
| 82 | + } |
| 83 | + |
| 84 | + private List<Diagnostic> toDiagnosticsArray(IDocument document, IMarker[] markers) { |
| 85 | + List<Diagnostic> diagnostics = Stream.of(markers).map(m -> toDiagnostic(document, m)).filter(d -> d != null) |
| 86 | + .collect(Collectors.toList()); |
| 87 | + return diagnostics; |
| 88 | + } |
| 89 | + |
| 90 | + private static Diagnostic toDiagnostic(IDocument document, IMarker marker) { |
| 91 | + if (marker == null || !marker.exists()) { |
| 92 | + return null; |
| 93 | + } |
| 94 | + Diagnostic d = new Diagnostic(); |
| 95 | + d.setSource(JavaLanguageServerPlugin.SERVER_SOURCE_ID); |
| 96 | + d.setMessage(marker.getAttribute(IMarker.MESSAGE, "")); |
| 97 | + d.setCode(String.valueOf(marker.getAttribute(IJavaModelMarker.ID, 0))); |
| 98 | + d.setSeverity(convertSeverity(marker.getAttribute(IMarker.SEVERITY, -1))); |
| 99 | + d.setRange(convertRange(document, marker)); |
| 100 | + return d; |
| 101 | + } |
| 102 | + |
| 103 | + private static Range convertRange(IDocument document, IMarker marker) { |
| 104 | + int line = marker.getAttribute(IMarker.LINE_NUMBER, -1) - 1; |
| 105 | + int cStart = 0; |
| 106 | + int cEnd = 0; |
| 107 | + try { |
| 108 | + // Buildship doesn't provide markers for gradle files, Maven does |
| 109 | + if (marker.isSubtypeOf(IMavenConstants.MARKER_ID)) { |
| 110 | + cStart = marker.getAttribute(IMavenConstants.MARKER_COLUMN_START, -1); |
| 111 | + cEnd = marker.getAttribute(IMavenConstants.MARKER_COLUMN_END, -1); |
| 112 | + } else { |
| 113 | + int lineOffset = 0; |
| 114 | + try { |
| 115 | + lineOffset = document.getLineOffset(line); |
| 116 | + } catch (BadLocationException unlikelyException) { |
| 117 | + JavaLanguageServerPlugin.logException(unlikelyException.getMessage(), unlikelyException); |
| 118 | + return new Range(new Position(line, 0), new Position(line, 0)); |
| 119 | + } |
| 120 | + cEnd = marker.getAttribute(IMarker.CHAR_END, -1) - lineOffset; |
| 121 | + cStart = marker.getAttribute(IMarker.CHAR_START, -1) - lineOffset; |
| 122 | + } |
| 123 | + } catch (CoreException e) { |
| 124 | + LanguageServerIndexerPlugin.logException(e.getMessage(), e); |
| 125 | + } |
| 126 | + cStart = Math.max(0, cStart); |
| 127 | + cEnd = Math.max(0, cEnd); |
| 128 | + |
| 129 | + return new Range(new Position(line, cStart), new Position(line, cEnd)); |
| 130 | + } |
| 131 | + |
| 132 | + private static DiagnosticSeverity convertSeverity(int severity) { |
| 133 | + if (severity == IMarker.SEVERITY_ERROR) { |
| 134 | + return DiagnosticSeverity.Error; |
| 135 | + } |
| 136 | + if (severity == IMarker.SEVERITY_WARNING) { |
| 137 | + return DiagnosticSeverity.Warning; |
| 138 | + } |
| 139 | + return DiagnosticSeverity.Information; |
| 140 | + } |
| 141 | +} |
0 commit comments