feat: Zon lazy tag and better autocomplete
This commit is contained in:
parent
e2e13e5f84
commit
817453fbef
10 changed files with 113 additions and 31 deletions
|
@ -20,8 +20,14 @@ Changelog structure reference:
|
|||
### Added
|
||||
|
||||
- Zon
|
||||
- Support for .lazy dependency property
|
||||
- Comment/uncomment hotkey support
|
||||
|
||||
### Fixed
|
||||
|
||||
- Zon
|
||||
- More reliable autocomplete
|
||||
|
||||
## [16.0.0]
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -17,7 +17,8 @@ pluginVersion=16.0.1-dev
|
|||
gradleVersion=8.9
|
||||
|
||||
# Enable Gradle Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html
|
||||
org.gradle.caching=true
|
||||
# TODO grammarkit breaks with this
|
||||
org.gradle.caching=false
|
||||
|
||||
# Enable Gradle Kotlin DSL Lazy Property Assignment -> https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:assignment
|
||||
systemProp.org.gradle.unsafe.kotlin.assignment=true
|
||||
|
|
|
@ -38,23 +38,25 @@
|
|||
STRING_LITERAL_SINGLE='string'
|
||||
LINE_STRING='multiline string'
|
||||
BAD_STRING='unterminated string'
|
||||
BOOL_TRUE='true'
|
||||
BOOL_FALSE='false'
|
||||
]
|
||||
|
||||
//Mixins
|
||||
mixin("struct")="com.falsepattern.zigbrains.zon.psi.impl.mixins.ZonStructMixinImpl"
|
||||
implements("struct")="com.falsepattern.zigbrains.zon.psi.mixins.ZonStructMixin"
|
||||
mixin("entry")="com.falsepattern.zigbrains.zon.psi.impl.mixins.ZonEntryMixinImpl"
|
||||
implements("entry")="com.falsepattern.zigbrains.zon.psi.mixins.ZonEntryMixin"
|
||||
|
||||
mixin("identifier")="com.falsepattern.zigbrains.zon.psi.impl.mixins.ZonIdentifierMixinImpl"
|
||||
implements("identifier")="com.falsepattern.zigbrains.zon.psi.mixins.ZonIdentifierMixin"
|
||||
}
|
||||
|
||||
zonFile ::= struct
|
||||
zonFile ::= entry
|
||||
|
||||
struct ::= DOT LBRACE (struct_string_list | struct_map | ()) RBRACE
|
||||
entry ::= DOT LBRACE (list | struct | ()) RBRACE
|
||||
|
||||
struct_map ::= (property | property_placeholder) (COMMA (property_placeholder? property property_placeholder? | property_placeholder))* COMMA?
|
||||
struct ::= (property | property_placeholder) (COMMA (property_placeholder? property property_placeholder? | property_placeholder))* COMMA?
|
||||
|
||||
struct_string_list ::= STRING_LITERAL (COMMA STRING_LITERAL)* COMMA?
|
||||
list ::= value (COMMA value)* COMMA?
|
||||
|
||||
property ::= DOT identifier EQ value
|
||||
|
||||
|
@ -62,6 +64,10 @@ identifier ::= ID
|
|||
|
||||
property_placeholder ::= DOT? INTELLIJ_COMPLETION_DUMMY
|
||||
|
||||
private value ::= struct | STRING_LITERAL
|
||||
private value ::= entry | boolean | STRING_LITERAL | value_placeholder
|
||||
|
||||
value_placeholder ::= INTELLIJ_COMPLETION_DUMMY
|
||||
|
||||
boolean ::= BOOL_TRUE | BOOL_FALSE
|
||||
|
||||
STRING_LITERAL ::= STRING_LITERAL_SINGLE | LINE_STRING+
|
||||
|
|
|
@ -62,6 +62,8 @@ LINE_STRING=("\\\\" [^\n]* [ \n]*)+
|
|||
<YYINITIAL> "}" { return RBRACE; }
|
||||
<YYINITIAL> "=" { return EQ; }
|
||||
<YYINITIAL> "," { return COMMA; }
|
||||
<YYINITIAL> "true" { return BOOL_TRUE; }
|
||||
<YYINITIAL> "false" { return BOOL_FALSE; }
|
||||
<YYINITIAL> {COMMENT} { return COMMENT; }
|
||||
<YYINITIAL> {LINE_COMMENT} { return COMMENT; }
|
||||
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
package com.falsepattern.zigbrains.zon.completion;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.parser.ZonFile;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonEntry;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonProperty;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonPropertyPlaceholder;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonStruct;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonTypes;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonValuePlaceholder;
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
|
@ -38,7 +40,7 @@ import static com.falsepattern.zigbrains.common.util.PsiElementUtil.parent;
|
|||
|
||||
public class ZonCompletionContributor extends CompletionContributor {
|
||||
private static final List<String> ZON_ROOT_KEYS = List.of("name", "version", "minimum_zig_version", "dependencies", "paths");
|
||||
private static final List<String> ZON_DEP_KEYS = List.of("url", "hash", "path");
|
||||
private static final List<String> ZON_DEP_KEYS = List.of("url", "hash", "path", "lazy");
|
||||
|
||||
public ZonCompletionContributor() {
|
||||
extend(CompletionType.BASIC,
|
||||
|
@ -48,12 +50,26 @@ public class ZonCompletionContributor extends CompletionContributor {
|
|||
new CompletionProvider<>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
var placeholder = parent(parameters.getPosition(), ZonPropertyPlaceholder.class).orElseThrow();
|
||||
var zonStruct = parent(placeholder, ZonStruct.class).orElseThrow();
|
||||
var keys = zonStruct.getKeys();
|
||||
doAddCompletions(placeholder.getText().startsWith("."), keys, ZON_ROOT_KEYS, result);
|
||||
}
|
||||
});
|
||||
var placeholder = parent(parameters.getPosition(), ZonPropertyPlaceholder.class).orElseThrow();
|
||||
var zonEntry = parent(placeholder, ZonEntry.class).orElseThrow();
|
||||
var keys = zonEntry.getKeys();
|
||||
doAddCompletions(placeholder.getText().startsWith("."), keys, ZON_ROOT_KEYS, result);
|
||||
}
|
||||
});
|
||||
extend(CompletionType.BASIC,
|
||||
PlatformPatterns.psiElement()
|
||||
.withParent(PlatformPatterns.psiElement(ZonTypes.VALUE_PLACEHOLDER))
|
||||
.withSuperParent(2, PlatformPatterns.psiElement(ZonTypes.LIST))
|
||||
.withSuperParent(4, PlatformPatterns.psiElement(ZonFile.class)),
|
||||
new CompletionProvider<>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
var placeholder = parent(parameters.getPosition(), ZonValuePlaceholder.class).orElseThrow();
|
||||
var zonEntry = parent(placeholder, ZonEntry.class).orElseThrow();
|
||||
var keys = zonEntry.getKeys();
|
||||
doAddCompletions(false, Set.of(), ZON_ROOT_KEYS, result);
|
||||
}
|
||||
});
|
||||
extend(CompletionType.BASIC,
|
||||
PlatformPatterns.psiElement()
|
||||
.withParent(PlatformPatterns.psiElement(ZonTypes.PROPERTY_PLACEHOLDER))
|
||||
|
@ -64,14 +80,59 @@ public class ZonCompletionContributor extends CompletionContributor {
|
|||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
var placeholder = parent(parameters.getPosition(), ZonPropertyPlaceholder.class).orElseThrow();
|
||||
var depStruct = parent(placeholder, ZonStruct.class).orElseThrow();
|
||||
var parentProperty = parent(depStruct, ZonProperty.class).flatMap(e -> parent(e, ZonProperty.class)).orElseThrow();
|
||||
if (!"dependencies".equals(parentProperty.getIdentifier().getName())) {
|
||||
var depEntry = parent(placeholder, ZonEntry.class).orElseThrow();
|
||||
if (!isADependency(depEntry))
|
||||
return;
|
||||
}
|
||||
doAddCompletions(placeholder.getText().startsWith("."), depStruct.getKeys(), ZON_DEP_KEYS, result);
|
||||
doAddCompletions(placeholder.getText().startsWith("."), depEntry.getKeys(), ZON_DEP_KEYS, result);
|
||||
}
|
||||
});
|
||||
extend(CompletionType.BASIC,
|
||||
PlatformPatterns.psiElement()
|
||||
.withParent(PlatformPatterns.psiElement(ZonTypes.VALUE_PLACEHOLDER))
|
||||
.withSuperParent(2, PlatformPatterns.psiElement(ZonTypes.LIST))
|
||||
.withSuperParent(4, PlatformPatterns.psiElement(ZonTypes.PROPERTY))
|
||||
.withSuperParent(7, PlatformPatterns.psiElement(ZonTypes.PROPERTY))
|
||||
.withSuperParent(10, PlatformPatterns.psiElement(ZonFile.class)),
|
||||
new CompletionProvider<>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
var placeholder = parent(parameters.getPosition(), ZonValuePlaceholder.class).orElseThrow();
|
||||
var depEntry = parent(placeholder, ZonEntry.class).orElseThrow();
|
||||
if (!isADependency(depEntry))
|
||||
return;
|
||||
doAddCompletions(false, Set.of(), ZON_DEP_KEYS, result);
|
||||
}
|
||||
});
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement()
|
||||
.withParent(PlatformPatterns.psiElement(ZonTypes.VALUE_PLACEHOLDER))
|
||||
.withSuperParent(5, PlatformPatterns.psiElement(ZonTypes.PROPERTY))
|
||||
.withSuperParent(8, PlatformPatterns.psiElement(ZonTypes.PROPERTY))
|
||||
.withSuperParent(11, PlatformPatterns.psiElement(ZonFile.class)),
|
||||
new CompletionProvider<>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
var placeholder = parent(parameters.getPosition(), ZonValuePlaceholder.class).orElseThrow();
|
||||
var valueProperty = parent(placeholder, ZonProperty.class).orElseThrow();
|
||||
if (!"lazy".equals(valueProperty.getIdentifier().getName())) {
|
||||
return;
|
||||
}
|
||||
if (!isADependency(valueProperty))
|
||||
return;
|
||||
|
||||
result.addElement(LookupElementBuilder.create("true"));
|
||||
result.addElement(LookupElementBuilder.create("false"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isADependency(ZonProperty property) {
|
||||
var depEntry = parent(property, ZonEntry.class).orElseThrow();
|
||||
return isADependency(depEntry);
|
||||
}
|
||||
|
||||
private static boolean isADependency(ZonEntry entry) {
|
||||
var parentProperty = parent(entry, ZonProperty.class).flatMap(e -> parent(e, ZonProperty.class)).orElseThrow();
|
||||
return "dependencies".equals(parentProperty.getIdentifier().getName());
|
||||
}
|
||||
|
||||
private static void doAddCompletions(boolean hasDot, Set<String> current, List<String> expected, CompletionResultSet result) {
|
||||
|
|
|
@ -62,7 +62,7 @@ public class ZonBlock extends AbstractBlock {
|
|||
return Indent.getNoneIndent();
|
||||
|
||||
val myElementType = myNode.getElementType();
|
||||
if (parent.getElementType() == ZonTypes.STRUCT &&
|
||||
if (parent.getElementType() == ZonTypes.ENTRY &&
|
||||
!(myElementType == ZonTypes.DOT ||
|
||||
myElementType == ZonTypes.LBRACE ||
|
||||
myElementType == ZonTypes.RBRACE)) {
|
||||
|
@ -86,7 +86,7 @@ public class ZonBlock extends AbstractBlock {
|
|||
|
||||
@Override
|
||||
protected @Nullable Indent getChildIndent() {
|
||||
if (myNode.getElementType() == ZonTypes.STRUCT) {
|
||||
if (myNode.getElementType() == ZonTypes.ENTRY) {
|
||||
return Indent.getNormalIndent();
|
||||
} else {
|
||||
return Indent.getNoneIndent();
|
||||
|
|
|
@ -36,7 +36,9 @@ public class ZonColorSettingsPage implements ColorSettingsPage {
|
|||
desc("Comment", ZonSyntaxHighlighter.COMMENT),
|
||||
desc("Bad Value", ZonSyntaxHighlighter.BAD_CHAR),
|
||||
desc("String", ZonSyntaxHighlighter.STRING),
|
||||
desc("Comma", ZonSyntaxHighlighter.COMMA), desc("Dot", ZonSyntaxHighlighter.DOT),
|
||||
desc("Comma", ZonSyntaxHighlighter.COMMA),
|
||||
desc("Dot", ZonSyntaxHighlighter.DOT),
|
||||
desc("Boolean", ZonSyntaxHighlighter.BOOLEAN),
|
||||
desc("Braces", ZonSyntaxHighlighter.BRACE)};
|
||||
|
||||
private static AttributesDescriptor desc(String name, TextAttributesKey key) {
|
||||
|
@ -60,11 +62,12 @@ public class ZonColorSettingsPage implements ColorSettingsPage {
|
|||
//This is an example file with some random data
|
||||
.name = "zls",
|
||||
.version = "0.11.0",
|
||||
|
||||
|
||||
.dependencies = .{
|
||||
.known_folders = .{
|
||||
.url = "https://github.com/ziglibs/known-folders/archive/fa75e1bc672952efa0cf06160bbd942b47f6d59b.tar.gz",
|
||||
.hash = "122048992ca58a78318b6eba4f65c692564be5af3b30fbef50cd4abeda981b2e7fa5",
|
||||
.lazy = true,
|
||||
},
|
||||
.diffz = .{
|
||||
.url = "https://github.com/ziglibs/diffz/archive/90353d401c59e2ca5ed0abe5444c29ad3d7489aa.tar.gz",
|
||||
|
@ -75,6 +78,7 @@ public class ZonColorSettingsPage implements ColorSettingsPage {
|
|||
.hash = "1220363c7e27b2d3f39de6ff6e90f9537a0634199860fea237a55ddb1e1717f5d6a5",
|
||||
},
|
||||
},
|
||||
.paths = .{""},
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ public class ZonSyntaxHighlighter extends SyntaxHighlighterBase {
|
|||
BAD_CHAR = createKey("BAD_CHARACTER", HighlighterColors.BAD_CHARACTER ),
|
||||
STRING = createKey("STRING" , DefaultLanguageHighlighterColors.STRING ),
|
||||
COMMA = createKey("COMMA" , DefaultLanguageHighlighterColors.COMMA ),
|
||||
BOOLEAN = createKey("BOOLEAN" , DefaultLanguageHighlighterColors.KEYWORD ),
|
||||
DOT = createKey("DOT" , DefaultLanguageHighlighterColors.DOT ),
|
||||
BRACE = createKey("BRACE" , DefaultLanguageHighlighterColors.BRACES );
|
||||
// @formatter:on
|
||||
|
@ -57,6 +58,7 @@ public class ZonSyntaxHighlighter extends SyntaxHighlighterBase {
|
|||
addMapping(COMMENT , ZonTypes.COMMENT);
|
||||
addMapping(ID , ZonTypes.ID);
|
||||
addMapping(EQ , ZonTypes.EQ);
|
||||
addMapping(BOOLEAN , ZonTypes.BOOL_FALSE, ZonTypes.BOOL_TRUE);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.falsepattern.zigbrains.zon.psi.impl.mixins;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonStruct;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonEntry;
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import lombok.val;
|
||||
|
@ -26,18 +26,18 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class ZonStructMixinImpl extends ASTWrapperPsiElement implements ZonStruct {
|
||||
public ZonStructMixinImpl(@NotNull ASTNode node) {
|
||||
public abstract class ZonEntryMixinImpl extends ASTWrapperPsiElement implements ZonEntry {
|
||||
public ZonEntryMixinImpl(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
val structMap = getStructMap();
|
||||
if (structMap == null)
|
||||
val struct = getStruct();
|
||||
if (struct == null)
|
||||
return Collections.emptySet();
|
||||
var result = new HashSet<String>();
|
||||
for (var property : structMap.getPropertyList()) {
|
||||
for (var property : struct.getPropertyList()) {
|
||||
result.add(property.getIdentifier().getName());
|
||||
}
|
||||
return result;
|
|
@ -20,6 +20,6 @@ import com.intellij.psi.PsiElement;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
public interface ZonStructMixin extends PsiElement {
|
||||
public interface ZonEntryMixin extends PsiElement {
|
||||
Set<String> getKeys();
|
||||
}
|
Loading…
Add table
Reference in a new issue