Use proper snippet syntax so placeholders work in vscode

This commit is contained in:
Kris De Volder
2017-09-20 17:41:27 -07:00
parent cdd390f048
commit 830f2e9879
3 changed files with 90 additions and 16 deletions

View File

@@ -10,25 +10,58 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.snippets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion;
import org.springframework.ide.vscode.commons.languageserver.util.SnippetBuilder;
import com.google.common.base.Supplier;
/**
* Respobsible for converting eclipse-like template string into lsp snippet text.
* @author Kris De Volder
*/
public class JavaSnippetBuilder{
private Supplier<SnippetBuilder> snippetBuilderFactory;
private static final Pattern PLACE_HOLDER = Pattern.compile("\\$\\{(.+?)\\}");
public JavaSnippetBuilder(Supplier<SnippetBuilder> snippetBuilderFactory) {
this.snippetBuilderFactory = snippetBuilderFactory;
}
public DocumentEdits createEdit(DocumentRegion query, String template) {
DocumentEdits edit = new DocumentEdits(query.getDocument());
edit.replace(query.getStart(), query.getEnd(), template);
edit.replace(query.getStart(), query.getEnd(), createSnippet(template));
return edit;
}
private String createSnippet(String template) {
Matcher matcher = PLACE_HOLDER.matcher(template);
int start = 0;
SnippetBuilder snippet = snippetBuilderFactory.get();
while (matcher.find(start)) {
int matchStart = matcher.start();
snippet.text(template.substring(start, matchStart));
int matchEnd = matcher.end();
String placeHolderImage = template.substring(matcher.start(1), matcher.end(1));
int colon = placeHolderImage.indexOf(':');
String id, value;
if (colon>=0) {
id = placeHolderImage.substring(0, colon);
value = placeHolderImage.substring(colon+1);
} else {
id = placeHolderImage;
value = id;
}
snippet.placeHolder(id, value);
start = matchEnd;
}
snippet.text(template.substring(start));
return snippet.build().toString();
}
}

View File

@@ -10,12 +10,12 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.util;
import java.util.Map;
import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.text.IRegion;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
/**
* Represents a string with placeholder inside. Provides methods to retrieve
@@ -68,12 +68,12 @@ public class PlaceHolderString {
}
private final ImmutableMap<Object, PlaceHolder> placeHolders;
private final ImmutableMultimap<Object, PlaceHolder> placeHolders;
private final String string;
public PlaceHolderString(Map<Object, PlaceHolder> placeHolders, String string) {
public PlaceHolderString(Multimap<Object, PlaceHolder> placeHolders, String string) {
super();
this.placeHolders = ImmutableMap.copyOf(placeHolders);
this.placeHolders = ImmutableMultimap.copyOf(placeHolders);
this.string = string;
}
@@ -90,7 +90,11 @@ public class PlaceHolderString {
}
public PlaceHolder getPlaceHolder(Object id) {
return placeHolders.get(id);
ImmutableCollection<PlaceHolder> all = placeHolders.get(id);
if (all!=null && !all.isEmpty()) {
return all.iterator().next();
}
return null;
}
}

View File

@@ -11,10 +11,16 @@
package org.springframework.ide.vscode.commons.languageserver.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString.PlaceHolder;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.text.Region;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
public class SnippetBuilder {
/**
@@ -25,7 +31,10 @@ public class SnippetBuilder {
public static SnippetBuilder gimped() {
return new SnippetBuilder() {
@Override
protected String createPlaceHolder(int id) {
protected String createPlaceHolder(Object id, Optional<String> value) {
if (value.isPresent()) {
return value.get();
}
return "";
}
};
@@ -34,7 +43,9 @@ public class SnippetBuilder {
private static final int FIRST_PLACE_HOLDER_ID = 1;
private int nextPlaceHolderId = FIRST_PLACE_HOLDER_ID;
private StringBuilder buf = new StringBuilder();
private HashMap<Object, PlaceHolder> placeHolders = new HashMap<>();
private Multimap<Object, PlaceHolder> placeHolders = MultimapBuilder.hashKeys().arrayListValues().build();
private Map<String,Object> idMap = new HashMap<>();
public SnippetBuilder text(String text) {
buf.append(text);
@@ -47,7 +58,29 @@ public class SnippetBuilder {
public SnippetBuilder placeHolder() {
int offset = buf.length();
int id = nextPlaceHolderId++;
buf.append(createPlaceHolder(id));
buf.append(createPlaceHolder(id, Optional.empty()));
int end = buf.length();
placeHolders.put(id, new PlaceHolderString.PlaceHolder(id, new Region(offset, end-offset)));
return this;
}
public SnippetBuilder placeHolder(String name, String _value) {
Assert.isNotNull(_value);
int offset = buf.length();
Object id;
Optional<String> value;
if (name.equals("cursor")) {
id = 0;
value = Optional.empty();
} else {
id = idMap.get(name);
if (id==null) {
id = nextPlaceHolderId++;
idMap.put(name, id);
}
value = Optional.of(_value);
}
buf.append(createPlaceHolder(id, value));
int end = buf.length();
placeHolders.put(id, new PlaceHolderString.PlaceHolder(id, new Region(offset, end-offset)));
return this;
@@ -62,8 +95,12 @@ public class SnippetBuilder {
* The default implementation creates place holder strings that
* match format specified by LSP 3.0.
*/
protected String createPlaceHolder(int id) {
return "$"+id;
protected String createPlaceHolder(Object id, Optional<String> value) {
if (!value.isPresent()) {
return "$"+id;
} else {
return "${"+id+":"+value.get()+"}";
}
}
public PlaceHolderString build() {
@@ -74,7 +111,7 @@ public class SnippetBuilder {
public String toString() {
String str = buf.toString();
if (getPlaceholderCount()==1 ) {
String placeHolder = createPlaceHolder(FIRST_PLACE_HOLDER_ID);
String placeHolder = createPlaceHolder(FIRST_PLACE_HOLDER_ID, Optional.empty());
if (str.endsWith(placeHolder)) {
str = str.substring(0, str.length()-placeHolder.length());
}
@@ -99,7 +136,7 @@ public class SnippetBuilder {
* @return The number of placeholder that where inserted in the snippet.
*/
public int getPlaceholderCount() {
return nextPlaceHolderId-1;
return placeHolders.size();
}
}