feat(zon): Code completion
This commit is contained in:
parent
211f2c8065
commit
b0b7a2cc7b
6 changed files with 171 additions and 20 deletions
|
@ -25,6 +25,7 @@ Changelog structure reference:
|
|||
- Basic syntax highlighting
|
||||
- Color settings page
|
||||
- Brace matching
|
||||
- Code completion
|
||||
|
||||
## [0.4.0]
|
||||
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright 2023 FalsePattern
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.falsepattern.zigbrains.zon.completion;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.parser.ZonFile;
|
||||
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.impl.ZonPsiImplUtil;
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ZonCompletionContributor extends CompletionContributor {
|
||||
private static final List<String> ZON_ROOT_KEYS = List.of("name", "version", "dependencies");
|
||||
private static final List<String> ZON_DEP_KEYS = List.of("url", "hash");
|
||||
public ZonCompletionContributor() {
|
||||
extend(CompletionType.BASIC,
|
||||
PlatformPatterns.psiElement()
|
||||
.withParent(PlatformPatterns.psiElement(ZonTypes.PROPERTY_PLACEHOLDER))
|
||||
.withSuperParent(3, PlatformPatterns.psiElement(ZonFile.class)),
|
||||
new CompletionProvider<>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
var placeholder = (ZonPropertyPlaceholder) parameters.getPosition().getParent();
|
||||
var zonStruct = (ZonStruct) placeholder.getParent();
|
||||
var keys = ZonPsiImplUtil.getKeys(zonStruct);
|
||||
doAddCompletions(placeholder.getText().startsWith("."), keys, ZON_ROOT_KEYS, result);
|
||||
}
|
||||
});
|
||||
extend(CompletionType.BASIC,
|
||||
PlatformPatterns.psiElement()
|
||||
.withParent(PlatformPatterns.psiElement(ZonTypes.PROPERTY_PLACEHOLDER))
|
||||
.withSuperParent(3, PlatformPatterns.psiElement(ZonTypes.VALUE))
|
||||
.withSuperParent(6, PlatformPatterns.psiElement(ZonTypes.VALUE))
|
||||
.withSuperParent(9, PlatformPatterns.psiElement(ZonFile.class)),
|
||||
new CompletionProvider<>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
var placeholder = (ZonPropertyPlaceholder) parameters.getPosition().getParent();
|
||||
var depStruct = (ZonStruct) placeholder.getParent();
|
||||
var parentProperty = (ZonProperty) depStruct.getParent()
|
||||
.getParent()
|
||||
.getParent()
|
||||
.getParent()
|
||||
.getParent();
|
||||
if (!"dependencies".equals(ZonPsiImplUtil.getText(parentProperty.getIdentifier()))) {
|
||||
return;
|
||||
}
|
||||
doAddCompletions(placeholder.getText().startsWith("."), ZonPsiImplUtil.getKeys(depStruct), ZON_DEP_KEYS, result);
|
||||
}
|
||||
});
|
||||
}
|
||||
private static void doAddCompletions(boolean hasDot, Set<String> current, List<String> expected, CompletionResultSet result) {
|
||||
for (var key: expected) {
|
||||
if (current.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
result.addElement(LookupElementBuilder.create(hasDot ? key : "." + key));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,27 +34,42 @@ WHITE_SPACE=[\s]+
|
|||
LINE_COMMENT="//" [^\n]* | "////" [^\n]*
|
||||
COMMENT="///".*
|
||||
|
||||
ID=[A-Za-z_][A-Za-z0-9_]* | "@\"" {STRING_CHAR}* \"
|
||||
ID=[A-Za-z_][A-Za-z0-9_]*
|
||||
|
||||
STRING_CHAR=( [^\\\"] | \\[^] )
|
||||
STRING_LITERAL_SINGLE=\"{STRING_CHAR}*\"
|
||||
LINE_STRING=(\\\\ [^\n]* [ \n]*)+
|
||||
hex=[0-9a-fA-F]
|
||||
char_escape
|
||||
= "\\x" {hex} {hex}
|
||||
| "\\u{" {hex}+ "}"
|
||||
| "\\" [nr\\t'\"]
|
||||
|
||||
string_char
|
||||
= {char_escape}
|
||||
| [^\\\"\n]
|
||||
|
||||
LINE_STRING=("\\\\" [^\n]* [ \n]*)+
|
||||
|
||||
%state STRING_LITERAL
|
||||
%state ID_STRING
|
||||
%%
|
||||
|
||||
<YYINITIAL> {
|
||||
{WHITE_SPACE} { return WHITE_SPACE; }
|
||||
"." { return DOT; }
|
||||
"{" { return LBRACE; }
|
||||
"}" { return RBRACE; }
|
||||
"=" { return EQ; }
|
||||
"," { return COMMA; }
|
||||
{COMMENT} { return COMMENT; }
|
||||
{LINE_COMMENT} { return COMMENT; }
|
||||
|
||||
{ID} { return ID; }
|
||||
{STRING_LITERAL_SINGLE} { return STRING_LITERAL_SINGLE; }
|
||||
{LINE_STRING} { return LINE_STRING; }
|
||||
}
|
||||
<YYINITIAL> {WHITE_SPACE} { return WHITE_SPACE; }
|
||||
<YYINITIAL> "." { return DOT; }
|
||||
<YYINITIAL> "IntellijIdeaRulezzz" { return INTELLIJ_COMPLETION_DUMMY; }
|
||||
<YYINITIAL> "{" { return LBRACE; }
|
||||
<YYINITIAL> "}" { return RBRACE; }
|
||||
<YYINITIAL> "=" { return EQ; }
|
||||
<YYINITIAL> "," { return COMMA; }
|
||||
<YYINITIAL> {COMMENT} { return COMMENT; }
|
||||
<YYINITIAL> {LINE_COMMENT} { return COMMENT; }
|
||||
|
||||
[^] { return BAD_CHARACTER; }
|
||||
<YYINITIAL> {ID} { return ID; }
|
||||
<YYINITIAL> "@\"" { yybegin(ID_STRING); }
|
||||
<ID_STRING> {string_char}*"\"" { yybegin(YYINITIAL); return ID; }
|
||||
|
||||
<YYINITIAL> "\"" { yybegin(STRING_LITERAL); }
|
||||
<STRING_LITERAL> {string_char}*"\"" { yybegin(YYINITIAL); return STRING_LITERAL_SINGLE; }
|
||||
<YYINITIAL> {LINE_STRING} { return LINE_STRING; }
|
||||
|
||||
|
||||
[^] { yybegin(YYINITIAL); return BAD_CHARACTER; }
|
||||
|
|
|
@ -42,9 +42,13 @@
|
|||
|
||||
zonFile ::= struct
|
||||
|
||||
struct ::= DOT LBRACE (property (COMMA property)* COMMA?)? RBRACE
|
||||
struct ::= DOT LBRACE (property COMMA | property_placeholder COMMA?)* property? RBRACE
|
||||
|
||||
property ::= DOT ID EQ value
|
||||
property ::= DOT identifier EQ value
|
||||
|
||||
identifier ::= ID
|
||||
|
||||
property_placeholder ::= DOT? INTELLIJ_COMPLETION_DUMMY
|
||||
|
||||
value ::= struct | STRING_LITERAL
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2023 FalsePattern
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.falsepattern.zigbrains.zon.psi.impl;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonIdentifier;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonStruct;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class ZonPsiImplUtil {
|
||||
public static Set<String> getKeys(ZonStruct struct) {
|
||||
var result = new HashSet<String>();
|
||||
for (var property: struct.getPropertyList()) {
|
||||
result.add(getText(property.getIdentifier()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getText(ZonIdentifier identifier) {
|
||||
var idStr = identifier.getText();
|
||||
if (idStr.startsWith("@")) {
|
||||
return idStr.substring(2, idStr.length() - 2);
|
||||
} else {
|
||||
return idStr;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -96,6 +96,9 @@
|
|||
|
||||
<lang.braceMatcher language="Zon"
|
||||
implementationClass="com.falsepattern.zigbrains.zon.braces.ZonBraceMatcher"/>
|
||||
|
||||
<completion.contributor language="Zon"
|
||||
implementationClass="com.falsepattern.zigbrains.zon.completion.ZonCompletionContributor"/>
|
||||
<!-- endregion Zon -->
|
||||
|
||||
</extensions>
|
||||
|
|
Loading…
Add table
Reference in a new issue