/*******************************************************************************
* Copyright (c) 2015, 2017 Open Analytics NV and others.
* 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
*******************************************************************************/
package org.eclipse.linuxtools.internal.docker.editor.syntax;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.linuxtools.internal.docker.editor.scanner.DockerCommentScanner;
import org.eclipse.linuxtools.internal.docker.editor.scanner.InstructionWordRule;
public class SyntaxProblemReporter {
private static final String LINE_SEP = System.getProperty("line.separator");
public void checkAndApply(IDocument document, int offset, int length, IResource resource)
throws CoreException, BadLocationException {
// We can't do problem report when file is external (no IResource)
if (resource == null) {
return;
}
boolean fullScan = (offset == 0 && length == document.getLength());
// Clear any existing markers in the affected region.
IMarker[] markers = resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO);
List<IMarker> markersToDelete = new ArrayList<>();
for (IMarker marker : markers) {
int markerLineNr = (Integer) marker.getAttribute(IMarker.LINE_NUMBER);
int regionLineNr = document.getLineOfOffset(offset);
if (fullScan || markerLineNr == regionLineNr)
markersToDelete.add(marker);
}
for (IMarker marker : markersToDelete)
marker.delete();
// Apply new problems as needed.
List<SyntaxProblem> problems = check(document, offset, length);
for (SyntaxProblem problem : problems) {
IMarker marker = resource.createMarker(IMarker.PROBLEM);
marker.setAttribute(IMarker.SEVERITY, problem.severity);
marker.setAttribute(IMarker.MESSAGE, problem.message);
marker.setAttribute(IMarker.LINE_NUMBER, document.getLineOfOffset(problem.offset));
marker.setAttribute(IMarker.CHAR_START, problem.offset);
marker.setAttribute(IMarker.CHAR_END, problem.offset + problem.length);
}
}
public List<SyntaxProblem> check(IDocument document, int offset, int length) throws BadLocationException {
String region = document.get(offset, length);
int lineCount = region.split(LINE_SEP).length;
int startingLineNr = document.getLineOfOffset(offset);
List<SyntaxProblem> problems = new ArrayList<>();
for (int lineNr = startingLineNr; lineNr < startingLineNr + lineCount; lineNr++) {
int lineOffset = document.getLineOffset(lineNr);
int lineEnd = document.getLength();
if (lineNr + startingLineNr + 1 < lineCount)
lineEnd = document.getLineOffset(lineNr + 1);
int endOfFirstWord = 0;
for (; endOfFirstWord < lineEnd - lineOffset; endOfFirstWord++) {
if (Character.isWhitespace(document.getChar(lineOffset + endOfFirstWord)))
break;
}
String firstWord = document.get(lineOffset, endOfFirstWord);
if (firstWord.trim().isEmpty())
continue;
if (firstWord.trim().startsWith(DockerCommentScanner.COMMENT_SEQUENCE))
continue;
String matchingInstruction = null;
for (String instr : InstructionWordRule.INSTRUCTIONS) {
if (instr.equalsIgnoreCase(firstWord)) {
matchingInstruction = instr;
break;
}
}
if (matchingInstruction == null) {
// Error: unknown instruction
problems.add(new SyntaxProblem(IMarker.SEVERITY_ERROR, lineOffset, firstWord.length(),
"Unknown instruction: " + firstWord));
} else if (!matchingInstruction.equals(firstWord)) {
// Warning: case incorrect
problems.add(new SyntaxProblem(IMarker.SEVERITY_WARNING, lineOffset, firstWord.length(),
"Instructions should be upper case"));
}
}
return problems;
}
public static class SyntaxProblem {
public int severity;
public int offset;
public int length;
public String message;
public SyntaxProblem(int severity, int offset, int length, String message) {
this.severity = severity;
this.offset = offset;
this.length = length;
this.message = message;
}
}
}