Use proper snippet syntax so placeholders work in vscode
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user