Merge branch 'master' of https://github.com/spring-projects/sts4
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
eclipse.preferences.version=1
|
||||
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
|
||||
sp_cleanup.add_default_serial_version_id=true
|
||||
sp_cleanup.add_generated_serial_version_id=false
|
||||
sp_cleanup.add_missing_annotations=true
|
||||
sp_cleanup.add_missing_deprecated_annotations=true
|
||||
sp_cleanup.add_missing_methods=false
|
||||
sp_cleanup.add_missing_nls_tags=false
|
||||
sp_cleanup.add_missing_override_annotations=true
|
||||
sp_cleanup.add_missing_override_annotations_interface_methods=true
|
||||
sp_cleanup.add_serial_version_id=false
|
||||
sp_cleanup.always_use_blocks=true
|
||||
sp_cleanup.always_use_parentheses_in_expressions=false
|
||||
sp_cleanup.always_use_this_for_non_static_field_access=false
|
||||
sp_cleanup.always_use_this_for_non_static_method_access=false
|
||||
sp_cleanup.convert_functional_interfaces=false
|
||||
sp_cleanup.convert_to_enhanced_for_loop=false
|
||||
sp_cleanup.correct_indentation=false
|
||||
sp_cleanup.format_source_code=false
|
||||
sp_cleanup.format_source_code_changes_only=false
|
||||
sp_cleanup.insert_inferred_type_arguments=false
|
||||
sp_cleanup.make_local_variable_final=true
|
||||
sp_cleanup.make_parameters_final=false
|
||||
sp_cleanup.make_private_fields_final=true
|
||||
sp_cleanup.make_type_abstract_if_missing_method=false
|
||||
sp_cleanup.make_variable_declarations_final=false
|
||||
sp_cleanup.never_use_blocks=false
|
||||
sp_cleanup.never_use_parentheses_in_expressions=true
|
||||
sp_cleanup.on_save_use_additional_actions=true
|
||||
sp_cleanup.organize_imports=true
|
||||
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
|
||||
sp_cleanup.remove_private_constructors=true
|
||||
sp_cleanup.remove_redundant_type_arguments=false
|
||||
sp_cleanup.remove_trailing_whitespaces=true
|
||||
sp_cleanup.remove_trailing_whitespaces_all=true
|
||||
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
|
||||
sp_cleanup.remove_unnecessary_casts=true
|
||||
sp_cleanup.remove_unnecessary_nls_tags=false
|
||||
sp_cleanup.remove_unused_imports=false
|
||||
sp_cleanup.remove_unused_local_variables=false
|
||||
sp_cleanup.remove_unused_private_fields=true
|
||||
sp_cleanup.remove_unused_private_members=false
|
||||
sp_cleanup.remove_unused_private_methods=true
|
||||
sp_cleanup.remove_unused_private_types=true
|
||||
sp_cleanup.sort_members=false
|
||||
sp_cleanup.sort_members_all=false
|
||||
sp_cleanup.use_anonymous_class_creation=false
|
||||
sp_cleanup.use_blocks=false
|
||||
sp_cleanup.use_blocks_only_for_return_and_throw=false
|
||||
sp_cleanup.use_lambda=true
|
||||
sp_cleanup.use_parentheses_in_expressions=false
|
||||
sp_cleanup.use_this_for_non_static_field_access=false
|
||||
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
|
||||
sp_cleanup.use_this_for_non_static_method_access=false
|
||||
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
|
||||
@@ -24,18 +24,19 @@
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<jackson-2-version>2.5.0</jackson-2-version>
|
||||
<jersey-2-version>2.10</jersey-2-version>
|
||||
<lsapi-version>0.3.0</lsapi-version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>util-commons</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- testing -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>language-server-test-harness</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Java implementation of VS Code language server protocol -->
|
||||
<dependency>
|
||||
<groupId>io.typefox.lsapi</groupId>
|
||||
|
||||
@@ -95,7 +95,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
public final int start;
|
||||
public final int end;
|
||||
public final String newText;
|
||||
|
||||
|
||||
public TextReplace(int start, int end, String newText) {
|
||||
super();
|
||||
this.start = start;
|
||||
@@ -119,7 +119,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
*/
|
||||
BEFORE,
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Transform positions around inserts to stick to the end of the inserted block.
|
||||
*/
|
||||
AFTER
|
||||
@@ -159,6 +159,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
public abstract int getStart();
|
||||
public abstract int getEnd();
|
||||
abstract void apply(DocumentState doc) throws BadLocationException;
|
||||
@Override
|
||||
public abstract String toString();
|
||||
}
|
||||
|
||||
@@ -228,13 +229,14 @@ public class DocumentEdits implements ProposalApplier {
|
||||
}
|
||||
final OffsetTransformer parent = org2new;
|
||||
org2new = new OffsetTransformer() {
|
||||
@Override
|
||||
public int transform(int org, Direction dir) {
|
||||
int tOffset = parent.transform(org, dir);
|
||||
if (tOffset<tStart) {
|
||||
return tOffset;
|
||||
} else if (tOffset>tStart) {
|
||||
return tOffset + text.length();
|
||||
} else /* tOffset==tStart*/ {
|
||||
} else /* tOffset==tStart*/ {
|
||||
if (dir==Direction.BEFORE) {
|
||||
return tOffset;
|
||||
} else {
|
||||
@@ -258,6 +260,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
|
||||
final OffsetTransformer parent = org2new;
|
||||
org2new = new OffsetTransformer() {
|
||||
@Override
|
||||
public int transform(int org, Direction dir) {
|
||||
int tOffset = parent.transform(org, dir);
|
||||
if (tOffset<=tStart) {
|
||||
@@ -308,7 +311,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRegion getSelection(IDocument doc) throws Exception {
|
||||
public IRegion getSelection() throws Exception {
|
||||
DocumentState selectionState = new DocumentState(null);
|
||||
for (Edit edit : edits) {
|
||||
edit.apply(selectionState);
|
||||
@@ -318,12 +321,12 @@ public class DocumentEdits implements ProposalApplier {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public TextReplace asReplacement(IDocument doc) throws BadLocationException {
|
||||
if (!edits.isEmpty()) {
|
||||
int start = edits.stream().mapToInt(Edit::getStart).min().getAsInt();
|
||||
int end = edits.stream().mapToInt(Edit::getEnd).max().getAsInt();
|
||||
|
||||
|
||||
DocumentState state = new DocumentState(doc);
|
||||
for (Edit edit : edits) {
|
||||
edit.apply(state);
|
||||
|
||||
@@ -25,12 +25,12 @@ public interface ProposalApplier {
|
||||
* {@link ProposalApplier} that does nothing whatsoever.
|
||||
*/
|
||||
static ProposalApplier NULL = new ProposalApplier() {
|
||||
@Override public IRegion getSelection(IDocument document) { return null; }
|
||||
@Override public IRegion getSelection() { return null; }
|
||||
@Override public void apply(IDocument doc) {}
|
||||
@Override public String toString() { return "NULL";};
|
||||
};
|
||||
|
||||
IRegion getSelection(IDocument document) throws Exception;
|
||||
IRegion getSelection() throws Exception;
|
||||
void apply(IDocument doc) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -12,22 +12,22 @@ import io.typefox.lsapi.impl.PositionImpl;
|
||||
import io.typefox.lsapi.impl.RangeImpl;
|
||||
|
||||
public class TextDocument implements IDocument {
|
||||
|
||||
|
||||
//TODO: This representiation of 'document content' is simplistic and inefficient
|
||||
// for large documents.
|
||||
// for large documents.
|
||||
// Making any change, such as inserting a character a user typed, works by copying the String that represents the
|
||||
// contents. This could really become problematic for largish-documents when there are frequent changes.
|
||||
|
||||
|
||||
Pattern NEWLINE = Pattern.compile("\\r|\\n|\\r\\n|\\n\\r");
|
||||
private int[] _lineStarts;
|
||||
|
||||
|
||||
private final String uri;
|
||||
private String text = "";
|
||||
|
||||
|
||||
public TextDocument(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
|
||||
private TextDocument(TextDocument other) {
|
||||
this.uri = other.uri;
|
||||
this.text = other.text;
|
||||
@@ -37,15 +37,16 @@ public class TextDocument implements IDocument {
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
|
||||
public synchronized String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void setText(String text) {
|
||||
this.text = text;
|
||||
this._lineStarts = null;
|
||||
@@ -62,7 +63,7 @@ public class TextDocument implements IDocument {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a simple offset+length pair into a vscode range. This is a method on
|
||||
* Convert a simple offset+length pair into a vscode range. This is a method on
|
||||
* TextDocument because it requires splitting document into lines to determine
|
||||
* line numbers from offsets.
|
||||
*/
|
||||
@@ -73,7 +74,7 @@ public class TextDocument implements IDocument {
|
||||
range.setEnd(toPosition(end));
|
||||
return range;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the line-number a given offset (i.e. what line is the offset inside of?)
|
||||
*/
|
||||
@@ -200,7 +201,7 @@ public class TextDocument implements IDocument {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int len = end - start;
|
||||
if (len<0) {
|
||||
len = 0;
|
||||
@@ -222,7 +223,7 @@ public class TextDocument implements IDocument {
|
||||
public int getLineOffset(int line) {
|
||||
return lineStarts()[line];
|
||||
}
|
||||
|
||||
|
||||
public int toOffset(Position position) {
|
||||
int line = position.getLine();
|
||||
int lineStart = lineStarts()[line];
|
||||
@@ -243,4 +244,9 @@ public class TextDocument implements IDocument {
|
||||
return get(start, end-start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TextDocument(uri="+uri+",\n"+this.text+"\n)";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015 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.commons.completion;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.testharness.Editor;
|
||||
import org.springframework.ide.vscode.testharness.LanguageServerHarness;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.util.IRegion;
|
||||
import org.springframework.ide.vscode.util.TextDocument;
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class DocumentEditsTest {
|
||||
|
||||
private LanguageServerHarness harness;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
harness = new LanguageServerHarness(null);
|
||||
}
|
||||
|
||||
class TestSubject {
|
||||
private Editor editor;
|
||||
private DocumentEdits edits;
|
||||
private String orgText;
|
||||
|
||||
public TestSubject(String contents) throws Exception {
|
||||
this.orgText = contents;
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset() throws Exception {
|
||||
this.editor = harness.newEditor(orgText);
|
||||
this.edits = new DocumentEdits(getFreshDocument(editor));
|
||||
}
|
||||
|
||||
private IDocument getFreshDocument(Editor editor) throws Exception {
|
||||
TextDocument doc = new TextDocument(null);
|
||||
doc.setText(editor.getRawText());
|
||||
return doc;
|
||||
}
|
||||
|
||||
public void del(String snippet) {
|
||||
int start = orgText.indexOf(snippet);
|
||||
assertTrue(start>=0);
|
||||
int end = start + snippet.length();
|
||||
edits.delete(start, end);
|
||||
}
|
||||
|
||||
public void expect(String expect) throws Exception {
|
||||
apply(editor, edits);
|
||||
assertEquals(expect, editor.getText());
|
||||
}
|
||||
|
||||
private void apply(Editor editor, DocumentEdits edit) throws Exception {
|
||||
IDocument document = getFreshDocument(editor);
|
||||
edits.apply(document);
|
||||
editor.setRawText(document.get());
|
||||
IRegion sel = edit.getSelection();
|
||||
int selectionStart = sel.getOffset();
|
||||
int selectionEnd = selectionStart+sel.getLength();
|
||||
editor.setSelection(selectionStart, selectionEnd);
|
||||
}
|
||||
|
||||
public void insBefore(String before, String insert) {
|
||||
int offset = orgText.indexOf(before);
|
||||
assertTrue(offset>=0);
|
||||
edits.insert(offset, insert);
|
||||
}
|
||||
|
||||
public void delLineAt(String snippet) throws Exception {
|
||||
int offset = orgText.indexOf(snippet);
|
||||
assertTrue(offset>=0);
|
||||
edits.deleteLineBackwardAtOffset(offset);
|
||||
}
|
||||
|
||||
public void delLine(int i) throws Exception {
|
||||
edits.deleteLineBackward(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test public void testDeletes() throws Exception {
|
||||
TestSubject it;
|
||||
|
||||
it = new TestSubject("0123456789<*>");
|
||||
it.del("123");
|
||||
it.del("567");
|
||||
it.expect("04<*>89");
|
||||
|
||||
it = new TestSubject("0123456789<*>");
|
||||
it.del("567");
|
||||
it.del("123");
|
||||
it.expect("0<*>489");
|
||||
|
||||
it = new TestSubject("0123456789<*>");
|
||||
it.del("012345");
|
||||
it.del("345");
|
||||
it.expect("<*>6789");
|
||||
|
||||
it = new TestSubject("0123456789<*>");
|
||||
it.del("345");
|
||||
it.del("012345");
|
||||
it.expect("<*>6789");
|
||||
|
||||
it = new TestSubject("0123456789<*>");
|
||||
it.del("2345");
|
||||
it.del("34567");
|
||||
it.expect("01<*>89");
|
||||
|
||||
it = new TestSubject("0123456789<*>");
|
||||
it.del("123");
|
||||
it.del("234");
|
||||
it.del("7");
|
||||
it.expect("056<*>89");
|
||||
}
|
||||
|
||||
@Test public void testInserts() throws Exception {
|
||||
TestSubject it;
|
||||
|
||||
it = new TestSubject("The fox jumps over the dog!");
|
||||
it.insBefore("fox", "quick ");
|
||||
it.insBefore("fox", "brown ");
|
||||
it.insBefore("dog", "lazy ");
|
||||
it.expect("The quick brown fox jumps over the lazy <*>dog!");
|
||||
}
|
||||
|
||||
@Test public void testInsertAndDelete() throws Exception {
|
||||
TestSubject it;
|
||||
|
||||
it = new TestSubject("The fox jumps over the dog!");
|
||||
|
||||
it.insBefore("fox", "quick "); //"The quick fox jumps..."
|
||||
it.del("The fox"); //" jumps..."
|
||||
it.insBefore("fox", "A rabbit");//"A rabbit jumps ..."
|
||||
|
||||
it.expect("A rabbit<*> jumps over the dog!");
|
||||
}
|
||||
|
||||
@Test public void testDeleteLine() throws Exception {
|
||||
TestSubject it;
|
||||
|
||||
it = new TestSubject(
|
||||
"Line 0\n" +
|
||||
"Line 1\n" +
|
||||
"Line 2"
|
||||
);
|
||||
|
||||
it.delLineAt("0");
|
||||
it.expect(
|
||||
"<*>Line 1\n" +
|
||||
"Line 2"
|
||||
);
|
||||
|
||||
it.reset();
|
||||
it.delLineAt("1");
|
||||
it.expect(
|
||||
"Line 0<*>\n" +
|
||||
"Line 2"
|
||||
);
|
||||
|
||||
it.reset();
|
||||
it.delLineAt("2");
|
||||
it.expect(
|
||||
"Line 0\n" +
|
||||
"Line 1<*>"
|
||||
);
|
||||
|
||||
it = new TestSubject("Line 0"); //special case: no newlines in document
|
||||
it.delLineAt("0");
|
||||
it.expect("<*>");
|
||||
|
||||
it = new TestSubject("");
|
||||
it.delLine(0);
|
||||
it.expect("<*>");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
eclipse.preferences.version=1
|
||||
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
|
||||
sp_cleanup.add_default_serial_version_id=true
|
||||
sp_cleanup.add_generated_serial_version_id=false
|
||||
sp_cleanup.add_missing_annotations=true
|
||||
sp_cleanup.add_missing_deprecated_annotations=true
|
||||
sp_cleanup.add_missing_methods=false
|
||||
sp_cleanup.add_missing_nls_tags=false
|
||||
sp_cleanup.add_missing_override_annotations=true
|
||||
sp_cleanup.add_missing_override_annotations_interface_methods=true
|
||||
sp_cleanup.add_serial_version_id=false
|
||||
sp_cleanup.always_use_blocks=true
|
||||
sp_cleanup.always_use_parentheses_in_expressions=false
|
||||
sp_cleanup.always_use_this_for_non_static_field_access=false
|
||||
sp_cleanup.always_use_this_for_non_static_method_access=false
|
||||
sp_cleanup.convert_functional_interfaces=false
|
||||
sp_cleanup.convert_to_enhanced_for_loop=false
|
||||
sp_cleanup.correct_indentation=false
|
||||
sp_cleanup.format_source_code=false
|
||||
sp_cleanup.format_source_code_changes_only=false
|
||||
sp_cleanup.insert_inferred_type_arguments=false
|
||||
sp_cleanup.make_local_variable_final=true
|
||||
sp_cleanup.make_parameters_final=false
|
||||
sp_cleanup.make_private_fields_final=true
|
||||
sp_cleanup.make_type_abstract_if_missing_method=false
|
||||
sp_cleanup.make_variable_declarations_final=false
|
||||
sp_cleanup.never_use_blocks=false
|
||||
sp_cleanup.never_use_parentheses_in_expressions=true
|
||||
sp_cleanup.on_save_use_additional_actions=true
|
||||
sp_cleanup.organize_imports=false
|
||||
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
|
||||
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
|
||||
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
|
||||
sp_cleanup.remove_private_constructors=true
|
||||
sp_cleanup.remove_redundant_type_arguments=false
|
||||
sp_cleanup.remove_trailing_whitespaces=true
|
||||
sp_cleanup.remove_trailing_whitespaces_all=true
|
||||
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
|
||||
sp_cleanup.remove_unnecessary_casts=true
|
||||
sp_cleanup.remove_unnecessary_nls_tags=false
|
||||
sp_cleanup.remove_unused_imports=false
|
||||
sp_cleanup.remove_unused_local_variables=false
|
||||
sp_cleanup.remove_unused_private_fields=true
|
||||
sp_cleanup.remove_unused_private_members=false
|
||||
sp_cleanup.remove_unused_private_methods=true
|
||||
sp_cleanup.remove_unused_private_types=true
|
||||
sp_cleanup.sort_members=false
|
||||
sp_cleanup.sort_members_all=false
|
||||
sp_cleanup.use_anonymous_class_creation=false
|
||||
sp_cleanup.use_blocks=false
|
||||
sp_cleanup.use_blocks_only_for_return_and_throw=false
|
||||
sp_cleanup.use_lambda=true
|
||||
sp_cleanup.use_parentheses_in_expressions=false
|
||||
sp_cleanup.use_this_for_non_static_field_access=false
|
||||
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
|
||||
sp_cleanup.use_this_for_non_static_method_access=false
|
||||
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
|
||||
@@ -13,10 +13,21 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- Java implementation of VS Code language server protocol -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>language-server-commons</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<groupId>io.typefox.lsapi</groupId>
|
||||
<artifactId>io.typefox.lsapi</artifactId>
|
||||
<version>${lsapi-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.typefox.lsapi</groupId>
|
||||
<artifactId>io.typefox.lsapi.services</artifactId>
|
||||
<version>${lsapi-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.typefox.lsapi</groupId>
|
||||
<artifactId>io.typefox.lsapi.annotations</artifactId>
|
||||
<version>${lsapi-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
||||
@@ -10,6 +10,8 @@ import java.util.List;
|
||||
|
||||
import javax.swing.text.BadLocationException;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import io.typefox.lsapi.CompletionItem;
|
||||
@@ -21,12 +23,12 @@ import io.typefox.lsapi.Range;
|
||||
import io.typefox.lsapi.TextEdit;
|
||||
|
||||
public class Editor {
|
||||
|
||||
|
||||
static class EditorState {
|
||||
String documentContents;
|
||||
int selectionStart;
|
||||
int selectionEnd;
|
||||
|
||||
|
||||
public EditorState(String text) {
|
||||
selectionStart = text.indexOf(CURSOR);
|
||||
if (selectionStart>=0) {
|
||||
@@ -45,10 +47,10 @@ public class Editor {
|
||||
this.documentContents = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final String CURSOR = "<*>"; // used by our test harness
|
||||
private static final String VS_CODE_CURSOR_MARKER = "{{}}"; //vscode uses this in edits to mark cursor position
|
||||
|
||||
|
||||
private static final Comparator<Diagnostic> PROBLEM_COMPARATOR = new Comparator<Diagnostic>() {
|
||||
@Override
|
||||
public int compare(Diagnostic o1, Diagnostic o2) {
|
||||
@@ -123,7 +125,7 @@ public class Editor {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the editor text, with cursor markers inserted (for easy textual comparison
|
||||
* after applying a proposal)
|
||||
@@ -136,7 +138,7 @@ public class Editor {
|
||||
}
|
||||
return deWindowsify(text);
|
||||
}
|
||||
|
||||
|
||||
public void setText(String content) throws Exception {
|
||||
EditorState state = new EditorState(content);
|
||||
document = harness.changeDocument(document.getUri(), state.documentContents);
|
||||
@@ -144,6 +146,13 @@ public class Editor {
|
||||
this.selectionEnd = state.selectionEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The 'raw' text in the editor, i.e. without the cursor markers.
|
||||
*/
|
||||
public String getRawText() throws Exception {
|
||||
return document.getText();
|
||||
}
|
||||
|
||||
public void setRawText(String newContent) throws Exception {
|
||||
document = harness.changeDocument(document.getUri(), newContent);
|
||||
}
|
||||
@@ -164,7 +173,7 @@ public class Editor {
|
||||
String messageSnippet = parts[1];
|
||||
boolean spaceSensitive = badSnippet.trim().length()<badSnippet.length();
|
||||
boolean emptyRange = problem.getRange().getStart().equals(problem.getRange().getEnd());
|
||||
String actualBadSnippet = emptyRange
|
||||
String actualBadSnippet = emptyRange
|
||||
? editor.getCharAt(problem.getRange().getStart())
|
||||
: editor.getText(problem.getRange());
|
||||
if (!spaceSensitive) {
|
||||
@@ -214,7 +223,7 @@ public class Editor {
|
||||
String docText = document.getText();
|
||||
if (edit!=null) {
|
||||
String replaceWith = edit.getNewText();
|
||||
//Apply indentfix, this is magic vscode seems to apply to edits returned by language server. So our harness has to
|
||||
//Apply indentfix, this is magic vscode seems to apply to edits returned by language server. So our harness has to
|
||||
// mimick that behavior. I'm not sure this fix is really emulating it faithfully as its undocumented :-(
|
||||
int indentFix = edit.getRange().getStart().getCharacter();
|
||||
replaceWith = replaceWith.replaceAll("\\n", "\n"+Strings.repeat(" ", indentFix));
|
||||
@@ -225,7 +234,7 @@ public class Editor {
|
||||
} else {
|
||||
cursorReplaceOffset = replaceWith.length();
|
||||
}
|
||||
|
||||
|
||||
Range rng = edit.getRange();
|
||||
int start = document.toOffset(rng.getStart());
|
||||
int end = document.toOffset(rng.getEnd());
|
||||
@@ -235,7 +244,7 @@ public class Editor {
|
||||
} else {
|
||||
String insertText = getInsertText(completion);
|
||||
String newText = docText.substring(0, selectionStart) + insertText + docText.substring(selectionStart);
|
||||
|
||||
|
||||
selectionStart+= insertText.length();
|
||||
selectionEnd += insertText.length();
|
||||
setRawText(newText);
|
||||
@@ -251,6 +260,7 @@ public class Editor {
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor clone() {
|
||||
try {
|
||||
return new Editor(harness, getText());
|
||||
@@ -292,4 +302,17 @@ public class Editor {
|
||||
throw new UnsupportedOperationException("Not implemented yet!");
|
||||
}
|
||||
|
||||
public void setSelection(int start, int end) {
|
||||
Assert.assertTrue(start>=0);
|
||||
Assert.assertTrue(end>=start);
|
||||
Assert.assertTrue(end<=document.getText().length());
|
||||
this.selectionStart = start;
|
||||
this.selectionEnd = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Editor(\n"+getText()+"\n)";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class LanguageServerHarness {
|
||||
private LanguageServer server;
|
||||
|
||||
private InitializeResult initResult;
|
||||
|
||||
|
||||
private Map<String,TextDocumentInfo> documents = new HashMap<>();
|
||||
private Map<String, PublishDiagnosticsParams> diagnostics = new HashMap<>();
|
||||
|
||||
@@ -71,7 +71,7 @@ public class LanguageServerHarness {
|
||||
document.setLanguageId(getLanguageId());
|
||||
return new TextDocumentInfo(document);
|
||||
}
|
||||
|
||||
|
||||
private synchronized TextDocumentItemImpl setDocumentContent(String uri, String newContent) {
|
||||
TextDocumentInfo o = documents.get(uri);
|
||||
TextDocumentItemImpl n = new TextDocumentItemImpl();
|
||||
@@ -90,11 +90,11 @@ public class LanguageServerHarness {
|
||||
protected String getLanguageId() {
|
||||
return "plaintext";
|
||||
}
|
||||
|
||||
|
||||
protected String getFileExtension() {
|
||||
return ".txt";
|
||||
}
|
||||
|
||||
|
||||
private synchronized void receiveDiagnostics(PublishDiagnosticsParams diags) {
|
||||
this.diagnostics.put(diags.getUri(), diags);
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class LanguageServerHarness {
|
||||
ClientCapabilitiesImpl clientCap = new ClientCapabilitiesImpl();
|
||||
initParams.setCapabilities(clientCap);
|
||||
initResult = server.initialize(initParams).get();
|
||||
|
||||
|
||||
server.getTextDocumentService().onPublishDiagnostics(this::receiveDiagnostics);
|
||||
return initResult;
|
||||
}
|
||||
@@ -118,10 +118,12 @@ public class LanguageServerHarness {
|
||||
didOpen.setTextDocument(documentInfo.getDocument());
|
||||
didOpen.setText(documentInfo.getText());
|
||||
didOpen.setUri(documentInfo.getUri());
|
||||
server.getTextDocumentService().didOpen(didOpen);
|
||||
if (server!=null) {
|
||||
server.getTextDocumentService().didOpen(didOpen);
|
||||
}
|
||||
return documentInfo;
|
||||
}
|
||||
|
||||
|
||||
public TextDocumentInfo openDocument(File file) throws Exception {
|
||||
return openDocument(getOrReadFile(file));
|
||||
}
|
||||
@@ -146,31 +148,38 @@ public class LanguageServerHarness {
|
||||
default:
|
||||
throw new IllegalStateException("Unkown SYNC mode: "+getDocumentSyncMode());
|
||||
}
|
||||
server.getTextDocumentService().didChange(didChange);
|
||||
if (server!=null) {
|
||||
server.getTextDocumentService().didChange(didChange);
|
||||
}
|
||||
return documents.get(uri);
|
||||
}
|
||||
|
||||
private TextDocumentSyncKind getDocumentSyncMode() {
|
||||
TextDocumentSyncKind mode = initResult.getCapabilities().getTextDocumentSync();
|
||||
return mode==null ? TextDocumentSyncKind.None : mode;
|
||||
if (initResult!=null) {
|
||||
TextDocumentSyncKind mode = initResult.getCapabilities().getTextDocumentSync();
|
||||
if (mode!=null) {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
return TextDocumentSyncKind.None;
|
||||
}
|
||||
|
||||
public PublishDiagnosticsParams getDiagnostics(TextDocumentInfo doc) {
|
||||
return diagnostics.get(doc.getUri());
|
||||
}
|
||||
|
||||
|
||||
public static Condition<Diagnostic> isDiagnosticWithSeverity(DiagnosticSeverity severity) {
|
||||
return new Condition<>(
|
||||
(d) -> d.getSeverity()==severity,
|
||||
"Diagnostic with severity '"+severity+"'"
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
public static Condition<Diagnostic> isDiagnosticCovering(TextDocumentInfo doc, String string) {
|
||||
return new Condition<>(
|
||||
(d) -> isDiagnosticCovering(d, doc, string),
|
||||
"Diagnostic covering '"+string+"'"
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
public static final Condition<Diagnostic> isWarning = isDiagnosticWithSeverity(DiagnosticSeverity.Warning);
|
||||
@@ -185,7 +194,7 @@ public class LanguageServerHarness {
|
||||
return new Condition<>(
|
||||
(d) -> d.getRange().getStart().getLine()==line,
|
||||
"Diagnostic on line "+line
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
public CompletionList getCompletions(TextDocumentInfo doc, Position cursor) throws Exception {
|
||||
@@ -213,7 +222,7 @@ public class LanguageServerHarness {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<CompletionItem> resolveCompletions(CompletionList completions) {
|
||||
return completions.getItems().stream()
|
||||
.map(this::resolveCompletionItem)
|
||||
|
||||
@@ -11,12 +11,16 @@ import io.typefox.lsapi.impl.PositionImpl;
|
||||
import io.typefox.lsapi.impl.TextDocumentIdentifierImpl;
|
||||
import io.typefox.lsapi.impl.TextDocumentItemImpl;
|
||||
|
||||
/**
|
||||
* Deprecated, we should get rid of this class and use {@link TextDocument}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class TextDocumentInfo {
|
||||
|
||||
Pattern NEWLINE = Pattern.compile("\\r|\\n|\\r\\n|\\n\\r");
|
||||
|
||||
|
||||
private final TextDocumentItemImpl document;
|
||||
|
||||
|
||||
private int[] _lineStarts;
|
||||
|
||||
public TextDocumentInfo(TextDocumentItemImpl document) {
|
||||
@@ -83,7 +87,7 @@ public class TextDocumentInfo {
|
||||
/**
|
||||
* 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) {
|
||||
@@ -126,5 +130,5 @@ public class TextDocumentInfo {
|
||||
id.setUri(getUri());
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
<assertj-version>3.5.2</assertj-version>
|
||||
<slf4j-version>1.7.21</slf4j-version>
|
||||
<guava-version>19.0</guava-version>
|
||||
<jackson-2-version>2.5.0</jackson-2-version>
|
||||
<jersey-2-version>2.10</jersey-2-version>
|
||||
<lsapi-version>0.3.0</lsapi-version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
||||
18
vscode-extensions/pom.xml
Normal file
18
vscode-extensions/pom.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>aggregator</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>aggregator</name>
|
||||
|
||||
<modules>
|
||||
<module>commons</module>
|
||||
<module>vscode-application-properties</module>
|
||||
<module>vscode-application-yaml</module>
|
||||
<module>vscode-manifest-yaml</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -20,9 +20,11 @@ import org.springframework.ide.vscode.util.SimpleTextDocumentService;
|
||||
import org.springframework.ide.vscode.util.TextDocument;
|
||||
|
||||
import io.typefox.lsapi.Diagnostic;
|
||||
import io.typefox.lsapi.DiagnosticImpl;
|
||||
import io.typefox.lsapi.DiagnosticSeverity;
|
||||
import io.typefox.lsapi.ServerCapabilities;
|
||||
import io.typefox.lsapi.ServerCapabilitiesImpl;
|
||||
import io.typefox.lsapi.TextDocumentSyncKind;
|
||||
import io.typefox.lsapi.impl.DiagnosticImpl;
|
||||
import io.typefox.lsapi.impl.ServerCapabilitiesImpl;
|
||||
|
||||
/**
|
||||
* Language Server for Spring Boot Application Properties files
|
||||
@@ -57,7 +59,7 @@ public class ApplicationPropertiesLanguageServer extends SimpleLanguageServer {
|
||||
DiagnosticImpl diagnostic = new DiagnosticImpl();
|
||||
diagnostic.setMessage(createSyntaxErrorMessage(problem.getMessage()));
|
||||
diagnostic.setCode(problem.getCode());
|
||||
diagnostic.setSeverity(Diagnostic.SEVERITY_ERROR);
|
||||
diagnostic.setSeverity(DiagnosticSeverity.Error);
|
||||
diagnostic.setSource("java-properties");
|
||||
diagnostic.setRange(doc.toRange(problem.getOffset(), problem.getLength()));
|
||||
return diagnostic;
|
||||
@@ -78,7 +80,7 @@ public class ApplicationPropertiesLanguageServer extends SimpleLanguageServer {
|
||||
protected ServerCapabilitiesImpl getServerCapabilities() {
|
||||
ServerCapabilitiesImpl c = new ServerCapabilitiesImpl();
|
||||
|
||||
c.setTextDocumentSync(ServerCapabilities.SYNC_FULL);
|
||||
c.setTextDocumentSync(TextDocumentSyncKind.Full);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -135,11 +135,6 @@ public class Main {
|
||||
|
||||
server.onError(message, err);
|
||||
});
|
||||
|
||||
try {
|
||||
jsonServer.join();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
jsonServer.join();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.ide.vscode.testharness.LanguageServerHarness;
|
||||
|
||||
import io.typefox.lsapi.InitializeResult;
|
||||
import io.typefox.lsapi.ServerCapabilities;
|
||||
import io.typefox.lsapi.TextDocumentSyncKind;
|
||||
|
||||
/**
|
||||
* Boot app properties file language server tests
|
||||
@@ -50,7 +51,7 @@ public class ApplicationPropertiesLanguageServerTest {
|
||||
}
|
||||
|
||||
private void assertExpectedInitResult(InitializeResult initResult) {
|
||||
assertThat(initResult.getCapabilities().getTextDocumentSync()).isEqualTo(ServerCapabilities.SYNC_FULL);
|
||||
assertThat(initResult.getCapabilities().getTextDocumentSync()).isEqualTo(TextDocumentSyncKind.Full);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class Main {
|
||||
|
||||
try {
|
||||
jsonServer.join();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,19 @@ import org.yaml.snakeyaml.nodes.Node;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import io.typefox.lsapi.CompletionItem;
|
||||
import io.typefox.lsapi.CompletionItemImpl;
|
||||
import io.typefox.lsapi.CompletionItemKind;
|
||||
import io.typefox.lsapi.CompletionList;
|
||||
import io.typefox.lsapi.CompletionListImpl;
|
||||
import io.typefox.lsapi.CompletionOptionsImpl;
|
||||
import io.typefox.lsapi.Diagnostic;
|
||||
import io.typefox.lsapi.DiagnosticImpl;
|
||||
import io.typefox.lsapi.PositionImpl;
|
||||
import io.typefox.lsapi.RangeImpl;
|
||||
import io.typefox.lsapi.DiagnosticSeverity;
|
||||
import io.typefox.lsapi.ServerCapabilities;
|
||||
import io.typefox.lsapi.ServerCapabilitiesImpl;
|
||||
import io.typefox.lsapi.TextDocumentSyncKind;
|
||||
import io.typefox.lsapi.impl.CompletionItemImpl;
|
||||
import io.typefox.lsapi.impl.CompletionListImpl;
|
||||
import io.typefox.lsapi.impl.CompletionOptionsImpl;
|
||||
import io.typefox.lsapi.impl.DiagnosticImpl;
|
||||
import io.typefox.lsapi.impl.PositionImpl;
|
||||
import io.typefox.lsapi.impl.RangeImpl;
|
||||
import io.typefox.lsapi.impl.ServerCapabilitiesImpl;
|
||||
|
||||
public class YamlLanguageServer extends SimpleLanguageServer {
|
||||
|
||||
@@ -66,7 +69,7 @@ public class YamlLanguageServer extends SimpleLanguageServer {
|
||||
// },
|
||||
CompletionItemImpl item = new CompletionItemImpl();
|
||||
item.setLabel("TypeScript");
|
||||
item.setKind(CompletionItem.KIND_TEXT);
|
||||
item.setKind(CompletionItemKind.Text);
|
||||
item.setData(1);
|
||||
items.add(item);
|
||||
}
|
||||
@@ -79,7 +82,7 @@ public class YamlLanguageServer extends SimpleLanguageServer {
|
||||
// }
|
||||
CompletionItemImpl item = new CompletionItemImpl();
|
||||
item.setLabel("JavaScript");
|
||||
item.setKind(CompletionItem.KIND_TEXT);
|
||||
item.setKind(CompletionItemKind.Text);
|
||||
item.setData(2);
|
||||
items.add(item);
|
||||
}
|
||||
@@ -124,7 +127,7 @@ public class YamlLanguageServer extends SimpleLanguageServer {
|
||||
DiagnosticImpl d = new DiagnosticImpl();
|
||||
d.setMessage(getMessage(e));
|
||||
d.setRange(getRange(e));
|
||||
d.setSeverity(Diagnostic.SEVERITY_ERROR);
|
||||
d.setSeverity(DiagnosticSeverity.Error);
|
||||
d.setCode(ErrorCodes.YAML_SYNTAX_ERROR);
|
||||
d.setSource("yaml");
|
||||
return d;
|
||||
@@ -157,7 +160,7 @@ public class YamlLanguageServer extends SimpleLanguageServer {
|
||||
protected ServerCapabilitiesImpl getServerCapabilities() {
|
||||
ServerCapabilitiesImpl c = new ServerCapabilitiesImpl();
|
||||
|
||||
c.setTextDocumentSync(ServerCapabilities.SYNC_FULL);
|
||||
c.setTextDocumentSync(TextDocumentSyncKind.Full);
|
||||
|
||||
CompletionOptionsImpl completionProvider = new CompletionOptionsImpl();
|
||||
completionProvider.setResolveProvider(true);
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.typefox.lsapi.CompletionItem;
|
||||
import io.typefox.lsapi.CompletionList;
|
||||
import io.typefox.lsapi.InitializeResult;
|
||||
import io.typefox.lsapi.ServerCapabilities;
|
||||
import io.typefox.lsapi.TextDocumentSyncKind;
|
||||
|
||||
public class YamlLanguageServerTest {
|
||||
|
||||
@@ -68,7 +69,7 @@ public class YamlLanguageServerTest {
|
||||
|
||||
private void assertExpectedInitResult(InitializeResult initResult) {
|
||||
assertThat(initResult.getCapabilities().getCompletionProvider().getResolveProvider()).isTrue();
|
||||
assertThat(initResult.getCapabilities().getTextDocumentSync()).isEqualTo(ServerCapabilities.SYNC_FULL);
|
||||
assertThat(initResult.getCapabilities().getTextDocumentSync()).isEqualTo(TextDocumentSyncKind.Full);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user