Skip to content

Commit

Permalink
Navigator Support for HCL Files (#5954)
Browse files Browse the repository at this point in the history
* Improve HCL AST to block and attribute level.

* Do not generate HCLExpressionParser, use HCLParser.expression instead

* Added basic Navigator support for HCL

* Fixed attribute offset, added structure tests

* Template and interpolation nesting in HereDoc

* Do not mark HCL template tokens as error
  • Loading branch information
lkishalmi authored May 21, 2023
1 parent 5193dfa commit e7a5419
Show file tree
Hide file tree
Showing 30 changed files with 671 additions and 111 deletions.
1 change: 0 additions & 1 deletion ide/languages.hcl/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
<arg value="org.netbeans.modules.languages.hcl.grammar"/>
<arg value="HCLLexer.g4"/>
<arg value="TerraformLexer.g4"/>
<arg value="HCLExpressionParser.g4"/>
<arg value="HCLParser.g4"/>
</java>

Expand Down
44 changes: 43 additions & 1 deletion ide/languages.hcl/nbproject/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,49 @@
<code-name-base>org.netbeans.libs.junit4</code-name-base>
<compile-dependency/>
</test-dependency>
</test-type>
<test-dependency>
<code-name-base>org.netbeans.modules.csl.api</code-name-base>
<recursive/>
<compile-dependency/>
<test/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.editor.mimelookup.impl</code-name-base>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.editor.util</code-name-base>
<recursive/>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.lexer</code-name-base>
<compile-dependency/>
<test/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.masterfs</code-name-base>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
<recursive/>
<compile-dependency/>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.parsing.nb</code-name-base>
</test-dependency>
<test-dependency>
<code-name-base>org.netbeans.modules.projectapi.nb</code-name-base>
</test-dependency>
<test-dependency>
<code-name-base>org.openide.util.lookup</code-name-base>
<compile-dependency/>
<test/>
</test-dependency>
</test-type>
</test-dependencies>
<public-packages/>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ protected Token<HCLTokenId> mapToken(org.antlr.v4.runtime.Token antlrToken) {
return groupToken(INTERPOLATION, INTERPOLATION_CONTENT);

case TEMPLATE_CONTENT:
return groupToken(ERROR, TEMPLATE_CONTENT);
return groupToken(INTERPOLATION, TEMPLATE_CONTENT);
case WS:
case NL:
return token(WHITESPACE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.languages.hcl.ast.ASTBuilderListener;
import org.netbeans.modules.languages.hcl.ast.HCLDocument;
import org.netbeans.modules.languages.hcl.ast.SourceRef;
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 @@ -59,6 +60,7 @@ public class HCLParserResult extends ParserResult {
public final Map<String,List<OffsetRange>> folds = new HashMap<>();

private HCLDocument document;
private SourceRef references;

public HCLParserResult(Snapshot snapshot) {
super(snapshot);
Expand All @@ -84,7 +86,7 @@ public void compute() {
lexer.reset();

}
processDocument(document);
processDocument(document, references);

finished = true;
}
Expand Down Expand Up @@ -116,6 +118,14 @@ public List<? extends Error> getDiagnostics() {
return errors;
}

public final HCLDocument getDocument() {
return document;
}

public final SourceRef getReferences() {
return references;
}

@Override
protected void invalidate() {
}
Expand All @@ -126,13 +136,14 @@ protected void configureParser(HCLParser parser) {

parser.addParseListener(createFoldListener());

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

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

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

private void addFold(FoldType ft, Token token) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* 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.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.swing.ImageIcon;
import org.netbeans.modules.csl.api.ElementHandle;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.HtmlFormatter;
import org.netbeans.modules.csl.api.Modifier;
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.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;

/**
*
* @author lkishalmi
*/
public class HCLStructureItem implements ElementHandle, StructureItem {

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

public HCLStructureItem(HCLElement element, SourceRef references) {
this.element = element;
this.references = references;
}

@Override
public FileObject getFileObject() {
return references.getFileObject();
}

@Override
public String getMimeType() {
return getFileObject().getMIMEType();
}

@Override
public String getName() {
return element.id();
}

@Override
public String getIn() {
return null;
}


@Override
public Set<Modifier> getModifiers() {
return Collections.emptySet();
}

@Override
public boolean signatureEquals(ElementHandle handle) {
return false;
}

@Override
public OffsetRange getOffsetRange(ParserResult result) {
return references.getOffsetRange(element).orElse(OffsetRange.NONE);
}

@Override
public String getSortText() {
return getName();
}

@Override
public String getHtml(HtmlFormatter formatter) {
return getName();
}

@Override
public ElementHandle getElementHandle() {
return this;
}

@Override
public boolean isLeaf() {
return element instanceof HCLAttribute;
}

@Override
public List<? extends StructureItem> getNestedItems() {
if (nestedCache == null) {
if (element instanceof HCLContainer) {
HCLContainer c = (HCLContainer) element;
List<HCLStructureItem> nested = new ArrayList<>();
for (HCLBlock block : c.getBlocks()) {
nested.add(new HCLStructureItem(block, references));
}
for (HCLAttribute attribute : c.getAttributes()) {
nested.add(new HCLStructureItem(attribute, references));
}
nestedCache = nested;
} else {
nestedCache = Collections.emptyList();
}
}
return nestedCache;
}

@Override
public long getPosition() {
return getOffsetRange(null).getStart();
}

@Override
public long getEndPosition() {
return getOffsetRange(null).getEnd();
}

@Override
public ImageIcon getCustomIcon() {
return null;
}

@Override
public ElementKind getKind() {
return element instanceof HCLAttribute ? ElementKind.ATTRIBUTE : ElementKind.TAG;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,25 @@
*/
package org.netbeans.modules.languages.hcl;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.netbeans.api.editor.fold.FoldType;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.api.StructureItem;
import org.netbeans.modules.csl.api.StructureScanner;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.languages.hcl.HCLParserResult;
import org.netbeans.spi.editor.fold.FoldTypeProvider;

/**
*
* @author Laszlo Kishalmi
*/
public class HCLStructureScanner implements StructureScanner{
public class HCLStructureScanner implements StructureScanner {
@Override
public List<? extends StructureItem> scan(ParserResult info) {
return Collections.emptyList();
HCLParserResult hclInfo = (HCLParserResult) info;

HCLStructureItem root = new HCLStructureItem(hclInfo.getDocument(), hclInfo.getReferences());
return root.getNestedItems();
}

@Override
Expand Down
Loading

0 comments on commit e7a5419

Please sign in to comment.