From 5e666ef37dda683dc72cdecba7be839924432b9d Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Thu, 22 Sep 2016 17:34:36 -0700 Subject: [PATCH] Port over all manifest.yml editr tests (still failing) --- .../language-server-test-harness/.classpath | 36 ++ .../language-server-test-harness/.project | 23 ++ .../.settings/org.eclipse.jdt.core.prefs | 5 + .../.settings/org.eclipse.m2e.core.prefs | 4 + .../language-server-test-harness/pom.xml | 33 ++ .../ide/vscode/testharness/Editor.java | 12 + .../testharness/LanguageServerHarness.java | 0 .../vscode/testharness/TextDocumentInfo.java | 0 vscode-extensions/commons/pom.xml | 12 +- .../vscode-application-yaml/pom.xml | 7 + .../vscode-manifest-yaml/pom.xml | 9 +- .../ide/vscode/testharness/Editor.java | 131 ------ .../testharness/LanguageServerHarness.java | 246 ----------- .../vscode/testharness/TextDocumentInfo.java | 130 ------ .../yaml/ApplicationYamlEditorTest.java | 52 --- .../vscode/yaml/ManifestYamlEditorTest.java | 381 ++++++++++++++++++ 16 files changed, 518 insertions(+), 563 deletions(-) create mode 100644 vscode-extensions/commons/language-server-test-harness/.classpath create mode 100644 vscode-extensions/commons/language-server-test-harness/.project create mode 100644 vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.jdt.core.prefs create mode 100644 vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.m2e.core.prefs create mode 100644 vscode-extensions/commons/language-server-test-harness/pom.xml rename vscode-extensions/{vscode-application-yaml/src/test => commons/language-server-test-harness/src/main}/java/org/springframework/ide/vscode/testharness/Editor.java (92%) rename vscode-extensions/{vscode-application-yaml/src/test => commons/language-server-test-harness/src/main}/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java (100%) rename vscode-extensions/{vscode-application-yaml/src/test => commons/language-server-test-harness/src/main}/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java (100%) delete mode 100644 vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/Editor.java delete mode 100644 vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java delete mode 100644 vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java delete mode 100644 vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ApplicationYamlEditorTest.java create mode 100644 vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ManifestYamlEditorTest.java diff --git a/vscode-extensions/commons/language-server-test-harness/.classpath b/vscode-extensions/commons/language-server-test-harness/.classpath new file mode 100644 index 000000000..fae1a2b37 --- /dev/null +++ b/vscode-extensions/commons/language-server-test-harness/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vscode-extensions/commons/language-server-test-harness/.project b/vscode-extensions/commons/language-server-test-harness/.project new file mode 100644 index 000000000..a03ca7c45 --- /dev/null +++ b/vscode-extensions/commons/language-server-test-harness/.project @@ -0,0 +1,23 @@ + + + language-server-test-harness + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.jdt.core.prefs b/vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..714351aec --- /dev/null +++ b/vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.m2e.core.prefs b/vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 000000000..f897a7f1c --- /dev/null +++ b/vscode-extensions/commons/language-server-test-harness/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/vscode-extensions/commons/language-server-test-harness/pom.xml b/vscode-extensions/commons/language-server-test-harness/pom.xml new file mode 100644 index 000000000..d10989b19 --- /dev/null +++ b/vscode-extensions/commons/language-server-test-harness/pom.xml @@ -0,0 +1,33 @@ + + 4.0.0 + language-server-test-harness + language-server-test-harness + Test harness for testing language server functionaltity implemented in Java + + + org.springframework.ide.vscode + commons-parent + 0.0.1-SNAPSHOT + ../pom.xml + + + + + org.springframework.ide.vscode + language-server-commons + ${project.version} + + + junit + junit + ${junit-version} + + + org.assertj + assertj-core + ${assertj-version} + + + + \ No newline at end of file diff --git a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/testharness/Editor.java b/vscode-extensions/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/testharness/Editor.java similarity index 92% rename from vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/testharness/Editor.java rename to vscode-extensions/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/testharness/Editor.java index 46a3a6209..ad341bfae 100644 --- a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/testharness/Editor.java +++ b/vscode-extensions/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/testharness/Editor.java @@ -128,4 +128,16 @@ public class Editor { return Collections.emptyList(); } + public void assertCompletions(String... specs) { + throw new UnsupportedOperationException("Not implemented yet!"); + } + + public void assertIsHoverRegion(String string) { + throw new UnsupportedOperationException("Not implemented yet!"); + } + + public void assertHoverContains(String string, String string2) { + throw new UnsupportedOperationException("Not implemented yet!"); + } + } diff --git a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java b/vscode-extensions/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java similarity index 100% rename from vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java rename to vscode-extensions/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java diff --git a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java b/vscode-extensions/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java similarity index 100% rename from vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java rename to vscode-extensions/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java diff --git a/vscode-extensions/commons/pom.xml b/vscode-extensions/commons/pom.xml index 01c573a06..930625f5c 100644 --- a/vscode-extensions/commons/pom.xml +++ b/vscode-extensions/commons/pom.xml @@ -7,12 +7,18 @@ commons-parent pom 0.0.1-SNAPSHOT - Parent pom for headless services written in Java + commons-parent language-server-commons + language-server-test-harness + + 4.11 + 3.5.2 + + @@ -32,13 +38,13 @@ junit junit - 4.11 + ${junit-version} test org.assertj assertj-core - 3.5.2 + ${assertj-version} test diff --git a/vscode-extensions/vscode-application-yaml/pom.xml b/vscode-extensions/vscode-application-yaml/pom.xml index 9debdb749..e4d278e72 100644 --- a/vscode-extensions/vscode-application-yaml/pom.xml +++ b/vscode-extensions/vscode-application-yaml/pom.xml @@ -58,6 +58,13 @@ guava 18.0 + + + org.springframework.ide.vscode + language-server-test-harness + ${project.version} + test + diff --git a/vscode-extensions/vscode-manifest-yaml/pom.xml b/vscode-extensions/vscode-manifest-yaml/pom.xml index 270ec1a1a..134110bc1 100644 --- a/vscode-extensions/vscode-manifest-yaml/pom.xml +++ b/vscode-extensions/vscode-manifest-yaml/pom.xml @@ -34,7 +34,7 @@ org.springframework.ide.vscode language-server-commons - 0.0.1-SNAPSHOT + ${project.version} @@ -48,6 +48,13 @@ guava 18.0 + + + org.springframework.ide.vscode + language-server-test-harness + ${project.version} + test + diff --git a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/Editor.java b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/Editor.java deleted file mode 100644 index 46a3a6209..000000000 --- a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/Editor.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.springframework.ide.vscode.testharness; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import javax.swing.text.BadLocationException; - -import io.typefox.lsapi.Diagnostic; -import io.typefox.lsapi.Position; -import io.typefox.lsapi.PublishDiagnosticsParams; -import io.typefox.lsapi.Range; - -public class Editor { - - private static final Comparator PROBLEM_COMPARATOR = new Comparator() { - @Override - public int compare(Diagnostic o1, Diagnostic o2) { - int diff = compare(o1.getRange().getStart(), o2.getRange().getStart()); - if (diff!=0) return diff; - return compare(o1.getRange().getEnd(), o2.getRange().getEnd()); - } - - private int compare(Position p1, Position p2) { - int d = p1.getLine() - p2.getLine(); - if (d!=0) return d; - return p1.getCharacter() - p2.getCharacter(); - } - }; - - private LanguageServerHarness harness; - private TextDocumentInfo document; - - public Editor(LanguageServerHarness harness, String contents) throws Exception { - this.harness = harness; - this.document = harness.openDocument(harness.createWorkingCopy(contents)); - } - - /** - * Check that a 'expectedProblems' are found by the reconciler. Expected problems are - * specified by string of the form "${badSnippet}|${messageSnippet}". The badSnippet - * is the text expected to be covered by the marker's region and the message snippet must - * be found in the error marker's message. - *

- * The expected problems are matched one-to-one in the order given (so markers in the - * editor must appear in the expected order for the assert to pass). - * - * @param editor - * @param expectedProblems - * @throws BadLocationException - */ - public void assertProblems(String... expectedProblems) throws Exception { - Editor editor = this; - List actualProblems = new ArrayList<>(editor.reconcile()); - Collections.sort(actualProblems, PROBLEM_COMPARATOR); - String bad = null; - if (actualProblems.size()!=expectedProblems.length) { - bad = "Wrong number of problems (expecting "+expectedProblems.length+" but found "+actualProblems.size()+")"; - } else { - for (int i = 0; i < expectedProblems.length; i++) { - if (!matchProblem(editor, actualProblems.get(i), expectedProblems[i])) { - bad = "First mismatch at index "+i+": "+expectedProblems[i]+"\n"; - break; - } - } - } - if (bad!=null) { - fail(bad+problemSumary(editor, actualProblems)); - } - } - - private String problemSumary(Editor editor, List actualProblems) throws Exception { - StringBuilder buf = new StringBuilder(); - for (Diagnostic p : actualProblems) { - buf.append("\n----------------------\n"); - - String snippet = editor.getText(p.getRange()); - buf.append("("+p.getRange().getStart().getLine()+", "+p.getRange().getStart().getCharacter()+")["+snippet+"]:\n"); - buf.append(" "+p.getMessage()); - } - return buf.toString(); - } - - public String getText(Range range) { - return document.getText(range); - } - - public void setText(String newContent) throws Exception { - document = harness.changeDocument(document.getUri(), newContent); - } - - private boolean matchProblem(Editor editor, Diagnostic problem, String expect) { - String[] parts = expect.split("\\|"); - assertEquals(2, parts.length); - String badSnippet = parts[0]; - String messageSnippet = parts[1]; - boolean spaceSensitive = badSnippet.trim().length() reconcile() { - // We assume the language server works synchronously for now and it does an immediate reconcile - // when the document changes. In the future this is probably not going to be the case though and then this - // method will need to somehow ensure the linter is done working before retrieving the problems from the - // test harness. - PublishDiagnosticsParams diagnostics = harness.getDiagnostics(document); - if (diagnostics!=null) { - return (List) diagnostics.getDiagnostics(); - } - return Collections.emptyList(); - } - -} diff --git a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java deleted file mode 100644 index d7e81a611..000000000 --- a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/LanguageServerHarness.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.springframework.ide.vscode.testharness; - -import java.io.File; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.Callable; -import java.util.stream.Collectors; - -import org.assertj.core.api.Condition; - -import io.typefox.lsapi.ClientCapabilitiesImpl; -import io.typefox.lsapi.CompletionItem; -import io.typefox.lsapi.CompletionList; -import io.typefox.lsapi.Diagnostic; -import io.typefox.lsapi.DidChangeTextDocumentParamsImpl; -import io.typefox.lsapi.DidOpenTextDocumentParamsImpl; -import io.typefox.lsapi.InitializeParamsImpl; -import io.typefox.lsapi.InitializeResult; -import io.typefox.lsapi.Position; -import io.typefox.lsapi.PositionImpl; -import io.typefox.lsapi.PublishDiagnosticsParams; -import io.typefox.lsapi.Range; -import io.typefox.lsapi.ServerCapabilities; -import io.typefox.lsapi.TextDocumentContentChangeEventImpl; -import io.typefox.lsapi.TextDocumentItemImpl; -import io.typefox.lsapi.TextDocumentPositionParamsImpl; -import io.typefox.lsapi.VersionedTextDocumentIdentifierImpl; -import io.typefox.lsapi.services.LanguageServer; - -public class LanguageServerHarness { - - //Warning this 'harness' is not very good yet. It just implements bare minimum to - // be able to test the MyLanguageServer example. - - private Random random = new Random(); - - private Callable factory; - - private LanguageServer server; - - private InitializeResult initResult; - - private Map documents = new HashMap<>(); - private Map diagnostics = new HashMap<>(); - - public LanguageServerHarness(Callable factory) throws Exception { - this.factory = factory; - } - - public synchronized TextDocumentInfo getOrReadFile(File file) throws Exception { - String uri = file.toURI().toString(); - TextDocumentInfo d = documents.get(uri); - if (d==null) { - documents.put(uri, d = readFile(file)); - } - return d; - } - - public TextDocumentInfo readFile(File file) throws Exception { - byte[] encoded = Files.readAllBytes(file.toPath()); - String content = new String(encoded, getEncoding()); - TextDocumentItemImpl document = new TextDocumentItemImpl(); - document.setText(content); - document.setUri(file.toURI().toString()); - document.setVersion(getFirstVersion()); - document.setLanguageId(getLanguageId()); - return new TextDocumentInfo(document); - } - - private synchronized TextDocumentItemImpl setDocumentContent(String uri, String newContent) { - TextDocumentInfo o = documents.get(uri); - TextDocumentItemImpl n = new TextDocumentItemImpl(); - n.setLanguageId(o.getLanguageId()); - n.setText(newContent); - n.setVersion(o.getVersion()+1); - n.setUri(o.getUri()); - documents.put(uri, new TextDocumentInfo(n)); - return n; - } - - protected Charset getEncoding() { - return Charset.forName("utf8"); - } - - protected String getLanguageId() { - return "plaintext"; - } - - protected String getFileExtension() { - return ".txt"; - } - - private synchronized void receiveDiagnostics(PublishDiagnosticsParams diags) { - this.diagnostics.put(diags.getUri(), diags); - } - - public InitializeResult intialize(File workspaceRoot) throws Exception { - server = factory.call(); - int parentPid = random.nextInt(40000)+1000; - InitializeParamsImpl initParams = new InitializeParamsImpl(); - initParams.setRootPath(workspaceRoot== null?null:workspaceRoot.toString()); - initParams.setProcessId(parentPid); - ClientCapabilitiesImpl clientCap = new ClientCapabilitiesImpl(); - initParams.setCapabilities(clientCap); - initResult = server.initialize(initParams).get(); - - server.getTextDocumentService().onPublishDiagnostics(this::receiveDiagnostics); - return initResult; - } - - public TextDocumentInfo openDocument(TextDocumentInfo documentInfo) throws Exception { - DidOpenTextDocumentParamsImpl didOpen = new DidOpenTextDocumentParamsImpl(); - didOpen.setTextDocument(documentInfo.getDocument()); - didOpen.setText(documentInfo.getText()); - didOpen.setUri(documentInfo.getUri()); - server.getTextDocumentService().didOpen(didOpen); - return documentInfo; - } - - public TextDocumentInfo openDocument(File file) throws Exception { - return openDocument(getOrReadFile(file)); - } - - public TextDocumentInfo changeDocument(String uri, String newContent) throws Exception { - TextDocumentItemImpl textDocument = setDocumentContent(uri, newContent); - DidChangeTextDocumentParamsImpl didChange = new DidChangeTextDocumentParamsImpl(); - VersionedTextDocumentIdentifierImpl version = new VersionedTextDocumentIdentifierImpl(); - version.setUri(uri); - version.setVersion(textDocument.getVersion()); - didChange.setTextDocument(version); - switch (getDocumentSyncMode()) { - case ServerCapabilities.SYNC_NONE: - break; //nothing todo - case ServerCapabilities.SYNC_INCREMENTAL: - throw new IllegalStateException("Incremental sync not yet supported by this test harness"); - case ServerCapabilities.SYNC_FULL: - TextDocumentContentChangeEventImpl change = new TextDocumentContentChangeEventImpl(); - change.setText(newContent); - didChange.setContentChanges(Collections.singletonList(change)); - break; - default: - throw new IllegalStateException("Unkown SYNC mode: "+getDocumentSyncMode()); - } - server.getTextDocumentService().didChange(didChange); - return documents.get(uri); - } - - private int getDocumentSyncMode() { - Integer mode = initResult.getCapabilities().getTextDocumentSync(); - return mode==null ? ServerCapabilities.SYNC_NONE : mode; - } - - public PublishDiagnosticsParams getDiagnostics(TextDocumentInfo doc) { - return diagnostics.get(doc.getUri()); - } - - public static Condition isDiagnosticWithSeverity(int severity) { - return new Condition<>( - (d) -> d.getSeverity()==severity, - "Diagnostic with severity '"+severity+"'" - ); - } - - public static Condition isDiagnosticCovering(TextDocumentInfo doc, String string) { - return new Condition<>( - (d) -> isDiagnosticCovering(d, doc, string), - "Diagnostic covering '"+string+"'" - ); - } - - public static final Condition isWarning = isDiagnosticWithSeverity(Diagnostic.SEVERITY_WARNING); - - public static boolean isDiagnosticCovering(Diagnostic diag, TextDocumentInfo doc, String string) { - Range rng = diag.getRange(); - String actualText = doc.getText(rng); - return string.equals(actualText); - } - - public static Condition isDiagnosticOnLine(int line) { - return new Condition<>( - (d) -> d.getRange().getStart().getLine()==line, - "Diagnostic on line "+line - ); - } - - public CompletionList getCompletions(TextDocumentInfo doc, Position cursor) throws Exception { - TextDocumentPositionParamsImpl params = new TextDocumentPositionParamsImpl(); - params.setPosition(toImpl(cursor)); - params.setTextDocument(doc.getId()); - return server.getTextDocumentService().completion(params).get(); - } - - private PositionImpl toImpl(Position pos) { - if (pos instanceof PositionImpl) { - return (PositionImpl) pos; - } else { - PositionImpl imp = new PositionImpl(); - imp.setCharacter(pos.getCharacter()); - imp.setLine(pos.getLine()); - return imp; - } - } - - private CompletionItem resolveCompletionItem(CompletionItem unresolved) { - try { - return server.getTextDocumentService().resolveCompletionItem(unresolved).get(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public List resolveCompletions(CompletionList completions) { - return completions.getItems().stream() - .map(this::resolveCompletionItem) - .collect(Collectors.toList()); - } - - public Editor newEditor(String contents) throws Exception { - return new Editor(this, contents); - } - - public synchronized TextDocumentInfo createWorkingCopy(String contents) throws Exception { - TextDocumentItemImpl doc = new TextDocumentItemImpl(); - doc.setLanguageId(getLanguageId()); - doc.setText(contents); - doc.setUri(createTempUri()); - doc.setVersion(getFirstVersion()); - TextDocumentInfo docinfo = new TextDocumentInfo(doc); - documents.put(docinfo.getUri(), docinfo); - return docinfo; - } - - protected int getFirstVersion() { - return 1; - } - - protected String createTempUri() throws Exception { - return File.createTempFile("workingcopy", getFileExtension()).toURI().toString(); - } - -} diff --git a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java deleted file mode 100644 index 1062f6bfb..000000000 --- a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/testharness/TextDocumentInfo.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.springframework.ide.vscode.testharness; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.typefox.lsapi.Position; -import io.typefox.lsapi.PositionImpl; -import io.typefox.lsapi.Range; -import io.typefox.lsapi.TextDocumentIdentifierImpl; -import io.typefox.lsapi.TextDocumentItemImpl; - -public class TextDocumentInfo { - - Pattern NEWLINE = Pattern.compile("\\r|\\n|\\r\\n|\\n\\r"); - - private final TextDocumentItemImpl document; - - private int[] _lineStarts; - - public TextDocumentInfo(TextDocumentItemImpl document) { - this.document = document; - } - - public String getLanguageId() { - return getDocument().getLanguageId(); - } - - public int getVersion() { - return getDocument().getVersion(); - } - - public String getText() { - return getDocument().getText(); - } - - public String getUri() { - return getDocument().getUri(); - } - - public TextDocumentItemImpl getDocument() { - return document; - } - - public String getText(Range rng) { - int start = toOffset(rng.getStart()); - int end = toOffset(rng.getEnd()); - return getText().substring(start, end); - } - - public int toOffset(Position p) { - int startOfLine = startOfLine(p.getLine()); - return startOfLine+p.getCharacter(); - } - - private int startOfLine(int line) { - return lineStarts()[line]; - } - - private int[] lineStarts() { - if (_lineStarts==null) { - _lineStarts = parseLines(); - } - return _lineStarts; - } - - private int[] parseLines() { - List lineStarts = new ArrayList<>(); - lineStarts.add(0); - Matcher matcher = NEWLINE.matcher(getText()); - int pos = 0; - while (matcher.find(pos)) { - lineStarts.add(pos = matcher.end()); - } - int[] array = new int[lineStarts.size()]; - for (int i = 0; i < array.length; i++) { - array[i] = lineStarts.get(i); - } - return array; - } - - /** - * Find and return the (first) position of a given text snippet in the - * document. - * - * @return The position, or null if the snippet can't be found. - */ - public Position positionOf(String snippet) { - int offset = getText().indexOf(snippet); - if (offset>=0) { - return toPosition(offset); - } - return null; - } - - public Position toPosition(int offset) { - int line = lineNumber(offset); - int startOfLine = startOfLine(line); - int column = offset - startOfLine; - PositionImpl pos = new PositionImpl(); - pos.setCharacter(column); - pos.setLine(line); - return pos; - } - - /** - * Determine the line-number a given offset (i.e. what line is the offset inside of?) - */ - private int lineNumber(int offset) { - int[] lineStarts = lineStarts(); - // TODO Could use binary search which is faster - int lineNumber = 0; - for (int i = 0; i < lineStarts.length; i++) { - if (lineStarts[i]<=offset) { - lineNumber = i; - } else { - return lineNumber; - } - } - return lineNumber; - } - - public TextDocumentIdentifierImpl getId() { - TextDocumentIdentifierImpl id = new TextDocumentIdentifierImpl(); - id.setUri(getUri()); - return id; - } - -} diff --git a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ApplicationYamlEditorTest.java b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ApplicationYamlEditorTest.java deleted file mode 100644 index 11c33e3ca..000000000 --- a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ApplicationYamlEditorTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.springframework.ide.vscode.yaml; - -import org.junit.Test; -import org.springframework.ide.vscode.testharness.Editor; -import org.springframework.ide.vscode.testharness.LanguageServerHarness; -import org.springframework.ide.vscode.yaml.YamlLanguageServer; - -/** - * This class is a placeholder where we will attempt to copy and port - * as many tests a possible from - * org.springframework.ide.eclipse.boot.properties.editor.test.YamlEditorTests - * - * @author Kris De Volder - */ -public class ApplicationYamlEditorTest { - - @Test public void testReconcileCatchesParseError() throws Exception { - LanguageServerHarness harness = new LanguageServerHarness(YamlLanguageServer::new); - harness.intialize(null); - - Editor editor = harness.newEditor( - "somemap: val\n"+ - "- sequence" - ); - editor.assertProblems( - "-|expected " - ); - } - - @Test public void linterRunsOnDocumentOpenAndChange() throws Exception { - LanguageServerHarness harness = new LanguageServerHarness(YamlLanguageServer::new); - harness.intialize(null); - - Editor editor = harness.newEditor( - "somemap: val\n"+ - "- sequence" - ); - - editor.assertProblems( - "-|expected " - ); - - editor.setText( - "- sequence\n" + - "zomemap: val" - ); - - editor.assertProblems( - "z|expected " - ); - } -} diff --git a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ManifestYamlEditorTest.java b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ManifestYamlEditorTest.java new file mode 100644 index 000000000..f25187a38 --- /dev/null +++ b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/yaml/ManifestYamlEditorTest.java @@ -0,0 +1,381 @@ +/******************************************************************************* + * Copyright (c) 2016 Pivotal, Inc. + * 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: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.yaml; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.ide.vscode.testharness.Editor; +import org.springframework.ide.vscode.testharness.LanguageServerHarness; + +public class ManifestYamlEditorTest { + + LanguageServerHarness harness; + + @Before public void setup() throws Exception { + harness = new LanguageServerHarness(YamlLanguageServer::new); + harness.intialize(null); + } + + @Test public void testReconcileCatchesParseError() throws Exception { + + Editor editor = harness.newEditor( + "somemap: val\n"+ + "- sequence" + ); + editor.assertProblems( + "-|expected " + ); + } + + @Test public void linterRunsOnDocumentOpenAndChange() throws Exception { + LanguageServerHarness harness = new LanguageServerHarness(YamlLanguageServer::new); + harness.intialize(null); + + Editor editor = harness.newEditor( + "somemap: val\n"+ + "- sequence" + ); + + editor.assertProblems( + "-|expected " + ); + + editor.setText( + "- sequence\n" + + "zomemap: val" + ); + + editor.assertProblems( + "z|expected " + ); + } + + @Test + public void toplevelCompletions() throws Exception { + Editor editor; + editor = harness.newEditor("<*>"); + editor.assertCompletions( + "applications:\n"+ + " - <*>", + // --------------- + "buildpack: <*>", + // --------------- + "command: <*>", + // --------------- + "disk_quota: <*>", + // --------------- + "domain: <*>", + // --------------- + "domains:\n"+ + " - <*>", + // --------------- + "env:\n"+ + " <*>", + // --------------- +// "host: <*>", + // --------------- +// "hosts: \n"+ +// " - <*>", + // --------------- + "inherit: <*>", + // --------------- + "instances: <*>", + // --------------- + "memory: <*>", + // --------------- +// "name: <*>", + // --------------- + "no-hostname: <*>", + // --------------- + "no-route: <*>", + // --------------- + "path: <*>", + // --------------- + "random-route: <*>", + // --------------- + "services:\n"+ + " - <*>", + // --------------- + "stack: <*>", + // --------------- + "timeout: <*>" + ); + + editor = harness.newEditor("ranro<*>"); + editor.assertCompletions( + "random-route: <*>" + ); + } + + @Test + public void nestedCompletions() throws Exception { + Editor editor; + editor = harness.newEditor( + "applications:\n" + + " - <*>" + ); + editor.assertCompletions( + // --------------- + "applications:\n" + + " - buildpack: <*>", + // --------------- + "applications:\n" + + " - command: <*>", + // --------------- + "applications:\n" + + " - disk_quota: <*>", + // --------------- + "applications:\n" + + " - domain: <*>", + // --------------- + "applications:\n" + + " - domains:\n"+ + " - <*>", + // --------------- + "applications:\n" + + " - env:\n"+ + " <*>", + // --------------- + "applications:\n" + + " - host: <*>", + // --------------- + "applications:\n" + + " - hosts:\n"+ + " - <*>", + // --------------- + "applications:\n" + + " - instances: <*>", + // --------------- + "applications:\n" + + " - memory: <*>", + // --------------- + "applications:\n" + + " - name: <*>", + // --------------- + "applications:\n" + + " - no-hostname: <*>", + // --------------- + "applications:\n" + + " - no-route: <*>", + // --------------- + "applications:\n" + + " - path: <*>", + // --------------- + "applications:\n" + + " - random-route: <*>", + // --------------- + "applications:\n" + + " - services:\n"+ + " - <*>", + // --------------- + "applications:\n" + + " - stack: <*>", + // --------------- + "applications:\n" + + " - timeout: <*>" + ); + } + + @Test + public void valueCompletions() throws Exception { + assertCompletions("disk_quota: <*>", + "disk_quota: 1024M<*>", + "disk_quota: 256M<*>", + "disk_quota: 512M<*>" + ); + assertCompletions("memory: <*>", + "memory: 1024M<*>", + "memory: 256M<*>", + "memory: 512M<*>" + ); + assertCompletions("no-hostname: <*>", + "no-hostname: false<*>", + "no-hostname: true<*>" + ); + assertCompletions("no-route: <*>", + "no-route: false<*>", + "no-route: true<*>" + ); + assertCompletions("random-route: <*>", + "random-route: false<*>", + "random-route: true<*>" + ); + } + + @Test + public void hoverInfos() throws Exception { + Editor editor = harness.newEditor( + "memory: 1G\n" + + "applications:\n" + + " - buildpack: zbuildpack\n" + + " domain: zdomain\n" + + " name: foo" + ); + editor.assertIsHoverRegion("memory"); + editor.assertIsHoverRegion("applications"); + editor.assertIsHoverRegion("buildpack"); + editor.assertIsHoverRegion("domain"); + editor.assertIsHoverRegion("name"); + + editor.assertHoverContains("memory", "Use the memory attribute to specify the memory limit"); + editor.assertHoverContains("1G", "Use the memory attribute to specify the memory limit"); + editor.assertHoverContains("buildpack", "use the buildpack attribute to specify its URL or name"); + } + + @Test + public void reconcileMisSpelledPropertyNames() throws Exception { + Editor editor; + + editor = harness.newEditor( + "memory: 1G\n" + + "aplications:\n" + + " - buildpack: zbuildpack\n" + + " domain: zdomain\n" + + " name: foo" + ); + editor.assertProblems("aplications|Unknown property"); + + //mispelled or not allowed at toplevel + editor = harness.newEditor( + "name: foo\n" + + "buildpeck: yahah\n" + + "memory: 1G\n" + + "memori: 1G\n" + ); + editor.assertProblems( + "name|Unknown property", + "buildpeck|Unknown property", + "memori|Unknown property" + ); + + //mispelled or not allowed as nested + editor = harness.newEditor( + "applications:\n" + + "- name: fine\n" + + " buildpeck: yahah\n" + + " memory: 1G\n" + + " memori: 1G\n" + + " applications: bad\n" + ); + editor.assertProblems( + "buildpeck|Unknown property", + "memori|Unknown property", + "applications|Unknown property" + ); + } + + @Test + public void reconcileStructuralProblems() throws Exception { + Editor editor; + + //forgot the 'applications:' heading + editor = harness.newEditor( + "- name: foo" + ); + editor.assertProblems( + "- name: foo|Expecting a 'Map' but found a 'Sequence'" + ); + + //forgot to make the '-' after applications + editor = harness.newEditor( + "applications:\n" + + " name: foo" + ); + editor.assertProblems( + "name: foo|Expecting a 'Sequence' but found a 'Map'" + ); + + //Using a 'composite' element where a scalar type is expected + editor = harness.newEditor( + "memory:\n"+ + "- bad sequence\n" + + "buildpack:\n" + + " bad: map\n" + ); + editor.assertProblems( + "- bad sequence|Expecting a 'Memory' but found a 'Sequence'", + "bad: map|Expecting a 'Buildpack' but found a 'Map'" + ); + } + + @Test + public void reconcileSimpleTypes() throws Exception { + Editor editor; + + //check for 'format' errors: + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " instances: not a number\n" + + " no-route: notBool\n"+ + " memory: 1024\n" + + " disk_quota: 2048\n" + ); + editor.assertProblems( + "not a number|Positive Integer", + "notBool|boolean", + "1024|Memory", + "2048|Memory" + ); + + //check for 'range' errors: + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " instances: -3\n" + + " memory: -1024M\n" + + " disk_quota: -2048M\n" + ); + editor.assertProblems( + "-3|Positive Integer", + "-1024M|Memory", + "-2048M|Memory" + ); + + //check that correct values are indeed accepted + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " instances: 2\n" + + " no-route: true\n"+ + " memory: 1024M\n" + + " disk_quota: 2048MB\n" + ); + editor.assertProblems(/*none*/); + + //check that correct values are indeed accepted + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " instances: 2\n" + + " no-route: false\n" + + " memory: 1024m\n" + + " disk_quota: 2048mb\n" + ); + editor.assertProblems(/*none*/); + + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " instances: 2\n" + + " memory: 1G\n" + + " disk_quota: 2g\n" + ); + editor.assertProblems(/*none*/); + } + + ////////////////////////////////////////////////////////////////////////////// + + private void assertCompletions(String textBefore, String... textAfter) throws Exception { + Editor editor = harness.newEditor(textBefore); + editor.assertCompletions(textAfter); + } +}