/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.languageserver.ide.editor;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import org.eclipse.che.ide.api.editor.annotation.AnnotationModelImpl;
import org.eclipse.che.ide.api.editor.document.Document;
import org.eclipse.che.ide.api.editor.document.DocumentHandle;
import org.eclipse.che.ide.api.editor.partition.DocumentPositionMap;
import org.eclipse.che.ide.api.editor.text.Position;
import org.eclipse.che.ide.api.editor.text.TextPosition;
import org.eclipse.che.ide.api.editor.texteditor.EditorResources;
import org.eclipse.che.ide.editor.orion.client.OrionAnnotationSeverityProvider;
import org.eclipse.che.plugin.languageserver.ide.LanguageServerResources;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Range;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Evgen Vidolob
*/
public class LanguageServerAnnotationModel extends AnnotationModelImpl implements DiagnosticCollector, OrionAnnotationSeverityProvider {
private final LanguageServerResources.LSCss lsCss;
private final EditorResources.EditorCss editorCss;
private List<Diagnostic> diagnostics;
private List<DiagnosticAnnotation> generatedAnnotations = new ArrayList<>();
@AssistedInject
public LanguageServerAnnotationModel(@Assisted final DocumentPositionMap docPositionMap,
final LanguageServerResources resources,
final EditorResources editorResources) {
super(docPositionMap);
this.lsCss = resources.css();
this.editorCss = editorResources.editorCss();
}
protected Position createPositionFromDiagnostic(final Diagnostic diagnostic) {
DocumentHandle documentHandle = getDocumentHandle();
Document document = documentHandle.getDocument();
Range range = diagnostic.getRange();
int start = document.getIndexFromPosition(new TextPosition(range.getStart().getLine(), range.getStart().getCharacter()));
int end = document.getIndexFromPosition(new TextPosition(range.getEnd().getLine(), range.getEnd().getCharacter()));
if (start == -1 && end == -1) {
return new Position(0);
}
if (start == -1) {
return new Position(end);
}
if (end == -1) {
return new Position(start);
}
int length = end - start;
if (length < 0) {
return null;
}
return new Position(start, length);
}
@Override
public void acceptDiagnostic(final Diagnostic problem) {
diagnostics.add(problem);
}
@Override
public void beginReporting() {
diagnostics = new ArrayList<>();
}
@Override
public void endReporting() {
reportDiagnostic();
}
private void reportDiagnostic() {
boolean temporaryProblemsChanged = false;
if (!generatedAnnotations.isEmpty()) {
temporaryProblemsChanged = true;
super.clear();
generatedAnnotations.clear();
}
if (diagnostics != null && !diagnostics.isEmpty()) {
for (final Diagnostic diagnostic : diagnostics) {
final Position position = createPositionFromDiagnostic(diagnostic);
if (position != null) {
final DiagnosticAnnotation annotation = new DiagnosticAnnotation(diagnostic);
addAnnotation(annotation, position, false);
generatedAnnotations.add(annotation);
temporaryProblemsChanged = true;
}
}
}
if (temporaryProblemsChanged) {
fireModelChanged();
}
}
@Override
public Map<String, String> getAnnotationDecorations() {
final Map<String, String> decorations = new HashMap<>();
// TODO configure this
decorations.put(DiagnosticAnnotation.ERROR_ANNOTATION_TYPE, this.editorCss.lineError());
decorations.put(DiagnosticAnnotation.WARNING_ANNOTATION_TYPE, this.editorCss.lineWarning());
return decorations;
}
@Override
public Map<String, String> getAnnotationStyle() {
final Map<String, String> decorations = new HashMap<>();
// //TODO configure this
decorations.put(DiagnosticAnnotation.ERROR_ANNOTATION_TYPE, lsCss.overviewMarkError());
decorations.put(DiagnosticAnnotation.WARNING_ANNOTATION_TYPE, lsCss.overviewMarkWarning());
//TODO add differed styles for info and hint type
decorations.put(DiagnosticAnnotation.INFO_ANNOTATION_TYPE, lsCss.overviewMarkTask());
decorations.put(DiagnosticAnnotation.HINT_ANNOTATION_TYPE, lsCss.overviewMarkTask());
return decorations;
}
@Override
public String getSeverity(String annotationType) {
if (annotationType == null) {
return "error";
}
//TODO we need better integration with Orion annotation system
switch (annotationType) {
case DiagnosticAnnotation.WARNING_ANNOTATION_TYPE:
return "warning";
case DiagnosticAnnotation.HINT_ANNOTATION_TYPE:
case DiagnosticAnnotation.INFO_ANNOTATION_TYPE:
return "task";
case DiagnosticAnnotation.ERROR_ANNOTATION_TYPE:
default:
return "error";
}
}
}