Skip to content

Commit

Permalink
Work on HCL Expression AST
Browse files Browse the repository at this point in the history
  • Loading branch information
lkishalmi committed Sep 23, 2023
1 parent b386c4e commit fbdda86
Show file tree
Hide file tree
Showing 40 changed files with 3,776 additions and 313 deletions.
1 change: 1 addition & 0 deletions ide/languages.hcl/manifest.mf
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ OpenIDE-Module: org.netbeans.modules.languages.hcl
OpenIDE-Module-Layer: org/netbeans/modules/languages/hcl/layer.xml
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/languages/hcl/Bundle.properties
OpenIDE-Module-Specification-Version: 1.2
OpenIDE-Module-Java-Dependencies: Java > 11
AutoUpdate-Show-In-Client: true
3 changes: 2 additions & 1 deletion ide/languages.hcl/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
javac.source=1.8
javac.source=11
javac.target=11

9 changes: 9 additions & 0 deletions ide/languages.hcl/nbproject/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@
<specification-version>1.20</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.libs.json_simple</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>0.33</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.csl.api</code-name-base>
<build-prerequisite/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.netbeans.api.lexer.Token;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.netbeans.core.spi.multiview.text.MultiViewEditorElement;
import org.netbeans.modules.csl.api.SemanticAnalyzer;
import org.netbeans.modules.csl.api.StructureScanner;
import org.netbeans.modules.csl.spi.DefaultLanguageConfig;
import org.netbeans.modules.csl.spi.LanguageRegistration;
Expand Down Expand Up @@ -152,6 +153,11 @@ public Parser getParser() {
return new NbHCLParser<HCLParserResult>(HCLParserResult::new);
}

@Override
public SemanticAnalyzer getSemanticAnalyzer() {
return new HCLSemanticAnalyzer();
}

@Override
public boolean hasStructureScanner() {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
import org.netbeans.modules.csl.api.Severity;
import org.netbeans.modules.csl.spi.DefaultError;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.languages.hcl.ast.ASTBuilderListener;
import org.netbeans.modules.languages.hcl.ast.HCLBlockFactory;
import org.netbeans.modules.languages.hcl.ast.HCLDocument;
import org.netbeans.modules.languages.hcl.ast.SourceRef;
import org.netbeans.modules.languages.hcl.ast.HCLElement;
import org.netbeans.modules.languages.hcl.grammar.HCLLexer;
import org.netbeans.modules.languages.hcl.grammar.HCLParser;
import org.netbeans.modules.languages.hcl.grammar.HCLParserBaseListener;
Expand All @@ -60,10 +60,11 @@ public class HCLParserResult extends ParserResult {
public final Map<String,List<OffsetRange>> folds = new HashMap<>();

private HCLDocument document;
private SourceRef references;
private final SourceRef references;

public HCLParserResult(Snapshot snapshot) {
super(snapshot);
references = new SourceRef(snapshot);
}

protected final FileObject getFileObject() {
Expand All @@ -82,7 +83,8 @@ public void compute() {
configureParser(parser);


parser.configFile();
HCLBlockFactory bf = new HCLBlockFactory(references::elementCreated);
document = bf.process(parser.configFile());
lexer.reset();

}
Expand Down Expand Up @@ -135,17 +137,20 @@ protected void configureParser(HCLParser parser) {
parser.addErrorListener(createErrorListener());

parser.addParseListener(createFoldListener());

ASTBuilderListener astListener = new ASTBuilderListener(getSnapshot());
parser.addParseListener(astListener);

document = astListener.getDocument();
references = astListener.getReferences();
}

protected void processDocument(HCLDocument doc, SourceRef references) {
}

protected void addError(HCLElement e, String message) {
references.getOffsetRange(e).ifPresent((range) -> addError(message, range));
}

private void addError(String message, OffsetRange range) {
DefaultError error = new DefaultError(null, message, null, getFileObject(), range.getStart() , range.getEnd(), false, Severity.ERROR);
errors.add(error);
}

private void addFold(FoldType ft, Token token) {
if (token.getText().contains("\n") && (token.getStartIndex() < token.getStopIndex())) {
List<OffsetRange> foldBag = folds.computeIfAbsent(ft.code(), (t) -> new ArrayList<>());
Expand Down Expand Up @@ -175,12 +180,14 @@ private ANTLRErrorListener createErrorListener() {
return new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
int errorPosition = 0;
int errorStart = 0;
int errorEnd = 0;
if (offendingSymbol instanceof Token) {
Token offendingToken = (Token) offendingSymbol;
errorPosition = offendingToken.getStartIndex();
errorStart = offendingToken.getStartIndex();
errorEnd = offendingToken.getStopIndex() + 1;
}
errors.add(new DefaultError(null, msg, null, getFileObject(), errorPosition, errorPosition, Severity.ERROR));
errors.add(new DefaultError(null, msg, null, getFileObject(), errorStart, errorEnd, errorStart == errorEnd, Severity.ERROR));
}

};
Expand All @@ -190,7 +197,7 @@ private ParseTreeListener createFoldListener() {
return new HCLParserBaseListener() {

@Override
public void exitHeredocTemplate(HCLParser.HeredocTemplateContext ctx) {
public void exitHeredoc(HCLParser.HeredocContext ctx) {
addFold(HCLLanguage.HCLFold.HEREDOC, ctx.HEREDOC_START(), ctx.HEREDOC_END());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.netbeans.modules.languages.hcl;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.netbeans.modules.csl.api.ColoringAttributes;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.api.SemanticAnalyzer;
import org.netbeans.modules.languages.hcl.ast.HCLAttribute;
import org.netbeans.modules.languages.hcl.ast.HCLBlock;
import org.netbeans.modules.languages.hcl.ast.HCLCollection;
import org.netbeans.modules.languages.hcl.ast.HCLDocument;
import org.netbeans.modules.languages.hcl.ast.HCLElement;
import org.netbeans.modules.languages.hcl.ast.HCLExpression;
import org.netbeans.modules.languages.hcl.ast.HCLFunction;
import org.netbeans.modules.languages.hcl.ast.HCLIdentifier;
import org.netbeans.modules.languages.hcl.ast.HCLVariable;
import org.netbeans.modules.parsing.spi.Scheduler;
import org.netbeans.modules.parsing.spi.SchedulerEvent;

/**
*
* @author lkishalmi
*/
public class HCLSemanticAnalyzer extends SemanticAnalyzer<HCLParserResult> {
private volatile boolean cancelled;
private Map<OffsetRange, Set<ColoringAttributes>> highlights = Collections.emptyMap();

@Override
public Map<OffsetRange, Set<ColoringAttributes>> getHighlights() {
return highlights;
}

protected final synchronized boolean isCancelled() {
return cancelled;
}

protected final synchronized void resume() {
cancelled = false;
}

@Override
public final void run(HCLParserResult result, SchedulerEvent event) {
resume();

Highlighter h = createHighlighter(result);
result.getDocument().accept(h);
highlights = h.work;
}

protected Highlighter createHighlighter(HCLParserResult result) {
return new DefaultHighlighter(result.getReferences());
}

@Override
public int getPriority() {
return 0;
}

@Override
public Class<? extends Scheduler> getSchedulerClass() {
return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
}

@Override
public void cancel() {
cancelled = true;
}

protected abstract class Highlighter extends HCLElement.BAEVisitor {
protected final Map<OffsetRange, Set<ColoringAttributes>> work = new HashMap<>();

protected final SourceRef refs;
protected Highlighter(SourceRef refs) {
this.refs = refs;
}

@Override
public final boolean visit(HCLElement e) {
if (isCancelled()) {
return true;
}
return super.visit(e);
}

protected final void mark(HCLElement e, Set<ColoringAttributes> attrs) {
refs.getOffsetRange(e).ifPresent((range) -> work.put(range, attrs));
}
}

protected class DefaultHighlighter extends Highlighter {

public DefaultHighlighter(SourceRef refs) {
super(refs);
}

@Override
protected boolean visitBlock(HCLBlock block) {
if (block.getParent() instanceof HCLDocument) {
List<HCLIdentifier> decl = block.getDeclaration();
HCLIdentifier type = decl.get(0);

mark(type, ColoringAttributes.CLASS_SET);
if (decl.size() > 1) {
for (int i = 1; i < decl.size(); i++) {
HCLIdentifier id = decl.get(i);
mark(id, ColoringAttributes.CONSTRUCTOR_SET);
}
}
} else {
//TODO: Handle nested Blocks...
}
return false;
}

@Override
protected boolean visitAttribute(HCLAttribute attr) {
mark(attr.getName(), ColoringAttributes.FIELD_SET);
return false;
}

@Override
protected boolean visitExpression(HCLExpression expr) {
if (expr instanceof HCLFunction) {
HCLFunction func = (HCLFunction) expr;
mark(func.getName(), ColoringAttributes.CONSTRUCTOR_SET);
}

if (expr instanceof HCLCollection.Object) {
HCLCollection.Object obj = (HCLCollection.Object) expr;
for (HCLExpression key : obj.getKeys()) {
if (key instanceof HCLVariable) {
mark(key, ColoringAttributes.FIELD_SET);
}
}
}
return false;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.api.StructureItem;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.languages.hcl.ast.HCLAddressableElement;
import org.netbeans.modules.languages.hcl.ast.HCLAttribute;
import org.netbeans.modules.languages.hcl.ast.HCLBlock;
import org.netbeans.modules.languages.hcl.ast.HCLContainer;
import org.netbeans.modules.languages.hcl.ast.HCLElement;
import org.netbeans.modules.languages.hcl.ast.SourceRef;
import org.openide.filesystems.FileObject;

/**
Expand All @@ -43,11 +42,11 @@
*/
public class HCLStructureItem implements ElementHandle, StructureItem {

final HCLElement element;
final HCLAddressableElement element;
final SourceRef references;
private List<? extends StructureItem> nestedCache;

public HCLStructureItem(HCLElement element, SourceRef references) {
public HCLStructureItem(HCLAddressableElement element, SourceRef references) {
this.element = element;
this.references = references;
}
Expand Down
Loading

0 comments on commit fbdda86

Please sign in to comment.