This is an automated email from the ASF dual-hosted git repository.
lkishalmi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new b1f2e5b4a0 Made HCL AST on records Use TextBlocks in formatting test,
minor enhancements
b1f2e5b4a0 is described below
commit b1f2e5b4a0e78b2194d59b7560d369ebb77f59ee
Author: Laszlo Kishalmi <[email protected]>
AuthorDate: Sun Mar 17 07:30:39 2024 -0700
Made HCL AST on records
Use TextBlocks in formatting test, minor enhancements
---
ide/languages.hcl/manifest.mf | 2 +-
ide/languages.hcl/nbproject/project.properties | 4 +-
.../modules/languages/hcl/HCLSemanticAnalyzer.java | 71 +++++-----
.../modules/languages/hcl/HCLStructureItem.java | 17 ++-
.../netbeans/modules/languages/hcl/SourceRef.java | 9 +-
.../languages/hcl/ast/HCLAddressableElement.java | 47 -------
.../languages/hcl/ast/HCLArithmeticOperation.java | 42 ++----
.../modules/languages/hcl/ast/HCLAttribute.java | 35 +----
.../modules/languages/hcl/ast/HCLBlock.java | 37 +++--
.../modules/languages/hcl/ast/HCLBlockFactory.java | 74 ++++------
.../modules/languages/hcl/ast/HCLCollection.java | 81 +++--------
.../languages/hcl/ast/HCLConditionalOperation.java | 14 +-
.../modules/languages/hcl/ast/HCLContainer.java | 55 +++-----
.../modules/languages/hcl/ast/HCLDocument.java | 23 +++-
.../modules/languages/hcl/ast/HCLElement.java | 75 +----------
.../languages/hcl/ast/HCLElementFactory.java | 75 +++++++++++
.../modules/languages/hcl/ast/HCLExpression.java | 35 +++--
.../languages/hcl/ast/HCLExpressionFactory.java | 123 ++++++-----------
.../languages/hcl/ast/HCLForExpression.java | 49 ++-----
.../modules/languages/hcl/ast/HCLFunction.java | 28 +---
.../modules/languages/hcl/ast/HCLIdentifier.java | 45 ++-----
.../modules/languages/hcl/ast/HCLLiteral.java | 41 +-----
.../languages/hcl/ast/HCLResolveOperation.java | 64 ++-------
.../modules/languages/hcl/ast/HCLTemplate.java | 89 +++---------
.../modules/languages/hcl/ast/HCLTreeWalker.java | 58 ++++++++
.../modules/languages/hcl/ast/HCLVariable.java | 18 +--
.../hcl/terraform/TerraformParserResult.java | 79 ++++++-----
.../hcl/terraform/TerraformSemanticAnalyzer.java | 41 ++----
.../languages/hcl/tfvars/TFVarsParserResult.java | 6 +-
.../modules/languages/hcl/HCLIndenterTest.java | 149 +++++++++++++++++++--
.../modules/languages/hcl/ReferenceTest.java | 7 +-
.../modules/languages/hcl/ast/HCLLiteralsTest.java | 8 +-
.../languages/hcl/ast/HCLOperationsTest.java | 34 ++---
33 files changed, 640 insertions(+), 895 deletions(-)
diff --git a/ide/languages.hcl/manifest.mf b/ide/languages.hcl/manifest.mf
index ac658e5249..642080e4ed 100644
--- a/ide/languages.hcl/manifest.mf
+++ b/ide/languages.hcl/manifest.mf
@@ -3,5 +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.4
-OpenIDE-Module-Java-Dependencies: Java > 11
+OpenIDE-Module-Java-Dependencies: Java > 17
AutoUpdate-Show-In-Client: true
diff --git a/ide/languages.hcl/nbproject/project.properties
b/ide/languages.hcl/nbproject/project.properties
index 5163ac1bd4..9d38ead391 100644
--- a/ide/languages.hcl/nbproject/project.properties
+++ b/ide/languages.hcl/nbproject/project.properties
@@ -14,6 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-javac.source=11
-javac.target=11
+javac.source=17
+javac.target=17
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLSemanticAnalyzer.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLSemanticAnalyzer.java
index 86581df92b..a320de27f4 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLSemanticAnalyzer.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLSemanticAnalyzer.java
@@ -29,11 +29,10 @@ 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.HCLTreeWalker;
import org.netbeans.modules.languages.hcl.ast.HCLVariable;
import org.netbeans.modules.parsing.spi.Scheduler;
import org.netbeans.modules.parsing.spi.SchedulerEvent;
@@ -64,8 +63,7 @@ public class HCLSemanticAnalyzer extends
SemanticAnalyzer<HCLParserResult> {
resume();
Highlighter h = createHighlighter(result);
- result.getDocument().accept(h);
- highlights = h.work;
+ highlights = h.process(result.getDocument());
}
protected Highlighter createHighlighter(HCLParserResult result) {
@@ -74,7 +72,7 @@ public class HCLSemanticAnalyzer extends
SemanticAnalyzer<HCLParserResult> {
@Override
public int getPriority() {
- return 0;
+ return 100;
}
@Override
@@ -87,7 +85,7 @@ public class HCLSemanticAnalyzer extends
SemanticAnalyzer<HCLParserResult> {
cancelled = true;
}
- protected abstract class Highlighter extends HCLElement.BAEVisitor {
+ protected abstract class Highlighter {
protected final Map<OffsetRange, Set<ColoringAttributes>> work = new
HashMap<>();
protected final SourceRef refs;
@@ -95,17 +93,25 @@ public class HCLSemanticAnalyzer extends
SemanticAnalyzer<HCLParserResult> {
this.refs = refs;
}
- @Override
- public final boolean visit(HCLElement e) {
+ protected abstract void highlight(HCLTreeWalker.Step step);
+
+ private boolean cancellableHighlight(HCLTreeWalker.Step step) {
if (isCancelled()) {
- return true;
+ return false;
}
- return super.visit(e);
+ highlight(step);
+ return true;
+ }
+
+ public Map<OffsetRange, Set<ColoringAttributes>> process(HCLElement
element) {
+ HCLTreeWalker.depthFirst(element, this::cancellableHighlight);
+ return work;
}
protected final void mark(HCLElement e, Set<ColoringAttributes> attrs)
{
refs.getOffsetRange(e).ifPresent((range) -> work.put(range,
attrs));
}
+
}
protected class DefaultHighlighter extends Highlighter {
@@ -115,9 +121,12 @@ public class HCLSemanticAnalyzer extends
SemanticAnalyzer<HCLParserResult> {
}
@Override
- protected boolean visitBlock(HCLBlock block) {
- if (block.getParent() instanceof HCLDocument) {
- List<HCLIdentifier> decl = block.getDeclaration();
+ protected void highlight(HCLTreeWalker.Step step) {
+
+ // TODO: Can use record patterns from Java 21
+ HCLElement e = step.node();
+ if (e instanceof HCLBlock block && step.depth() == 1) {
+ List<HCLIdentifier> decl = block.declaration();
HCLIdentifier type = decl.get(0);
mark(type, ColoringAttributes.CLASS_SET);
@@ -127,35 +136,17 @@ public class HCLSemanticAnalyzer extends
SemanticAnalyzer<HCLParserResult> {
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);
+ } else if (e instanceof HCLAttribute attr) {
+ mark(attr.name(), ColoringAttributes.FIELD_SET);
+ } else if (e instanceof HCLFunction func) {
+ mark(func.name(), ColoringAttributes.CONSTRUCTOR_SET);
+ } else if (e instanceof HCLCollection.Object obj) {
+ for (HCLCollection.ObjectElement oe : obj.elements()) {
+ if (oe.key() instanceof HCLVariable) {
+ mark(oe.key(), ColoringAttributes.FIELD_SET);
}
}
}
- return false;
- }
-
+ }
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLStructureItem.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLStructureItem.java
index 6c8b845fef..f269863e74 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLStructureItem.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/HCLStructureItem.java
@@ -30,10 +30,10 @@ 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.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.openide.filesystems.FileObject;
/**
@@ -42,11 +42,11 @@ import org.openide.filesystems.FileObject;
*/
public class HCLStructureItem implements ElementHandle, StructureItem {
- final HCLAddressableElement element;
+ final HCLElement element;
final SourceRef references;
private List<? extends StructureItem> nestedCache;
- public HCLStructureItem(HCLAddressableElement element, SourceRef
references) {
+ public HCLStructureItem(HCLElement element, SourceRef references) {
this.element = element;
this.references = references;
}
@@ -63,7 +63,12 @@ public class HCLStructureItem implements ElementHandle,
StructureItem {
@Override
public String getName() {
- return element.id();
+ if (element instanceof HCLAttribute a) {
+ return a.id();
+ } else if (element instanceof HCLBlock b) {
+ return b.id();
+ }
+ return "<" + element.getClass().getSimpleName() + ">";
}
@Override
@@ -113,10 +118,10 @@ public class HCLStructureItem implements ElementHandle,
StructureItem {
if (element instanceof HCLContainer) {
HCLContainer c = (HCLContainer) element;
List<HCLStructureItem> nested = new ArrayList<>();
- for (HCLBlock block : c.getBlocks()) {
+ for (HCLBlock block : c.blocks()) {
nested.add(new HCLStructureItem(block, references));
}
- for (HCLAttribute attribute : c.getAttributes()) {
+ for (HCLAttribute attribute : c.attributes()) {
nested.add(new HCLStructureItem(attribute, references));
}
nestedCache = nested;
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/SourceRef.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/SourceRef.java
index e83ba786e5..0e34fd9fcd 100644
--- a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/SourceRef.java
+++ b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/SourceRef.java
@@ -19,7 +19,7 @@
package org.netbeans.modules.languages.hcl;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -28,6 +28,7 @@ import java.util.Optional;
import java.util.TreeMap;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.languages.hcl.ast.HCLElement;
+import org.netbeans.modules.languages.hcl.ast.HCLElementFactory;
import org.netbeans.modules.parsing.api.Snapshot;
import org.openide.filesystems.FileObject;
@@ -37,7 +38,7 @@ import org.openide.filesystems.FileObject;
*/
public class SourceRef {
public final Snapshot source;
- private Map<HCLElement, OffsetRange> elementOffsets = new HashMap<>();
+ private Map<HCLElement, OffsetRange> elementOffsets = new
IdentityHashMap<>();
private TreeMap<OffsetRange, HCLElement> elementAt = new TreeMap<>((o1,
o2) -> o1.getStart() != o2.getStart() ? o1.getStart() - o2.getStart() :
o2.getEnd() - o1.getEnd());
@@ -53,8 +54,8 @@ public class SourceRef {
}
}
- void elementCreated(HCLElement.CreateContext ctx) {
- add(ctx.element, new OffsetRange(ctx.start.getStartIndex(),
ctx.stop.getStopIndex() + 1));
+ void elementCreated(HCLElementFactory.CreateContext ctx) {
+ add(ctx.element(), new OffsetRange(ctx.start().getStartIndex(),
ctx.stop().getStopIndex() + 1));
}
public FileObject getFileObject() {
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLAddressableElement.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLAddressableElement.java
deleted file mode 100644
index 407648d3d4..0000000000
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLAddressableElement.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.ast;
-
-/**
- *
- * @author lkishalmi
- */
-public abstract class HCLAddressableElement extends HCLElement {
-
- final HCLAddressableElement parent;
-
- public HCLAddressableElement(HCLAddressableElement parent) {
- this.parent = parent;
- }
-
- public final HCLAddressableElement getParent() {
- return parent;
- }
-
- public HCLContainer getContainer() {
- HCLAddressableElement e = parent;
- while (e != null && !(e instanceof HCLContainer)) {
- e = e.parent;
- }
- return (HCLContainer) e;
- }
-
- public abstract String id();
-
-}
\ No newline at end of file
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLArithmeticOperation.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLArithmeticOperation.java
index 3386a8fd79..c8b5468bea 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLArithmeticOperation.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLArithmeticOperation.java
@@ -18,15 +18,15 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
/**
*
* @author lkishalmi
*/
-public abstract class HCLArithmeticOperation extends HCLExpression {
+public sealed interface HCLArithmeticOperation extends HCLExpression {
+
+ Operator op();
public enum Operator {
NOT("!"),
@@ -61,51 +61,27 @@ public abstract class HCLArithmeticOperation extends
HCLExpression {
}
}
- public final Operator op;
-
- public HCLArithmeticOperation(Operator op) {
- this.op = op;
- }
-
- public final static class Binary extends HCLArithmeticOperation {
- public final HCLExpression left;
- public final HCLExpression right;
-
- public Binary(Operator op, HCLExpression left, HCLExpression right) {
- super(op);
- this.left = left;
- this.right = right;
- }
-
+ public record Binary(Operator op, HCLExpression left, HCLExpression right)
implements HCLArithmeticOperation {
@Override
public String asString() {
return left.toString() + op.toString() + right.toString();
}
@Override
- public List<? extends HCLExpression> getChildren() {
- return Arrays.asList(left, right);
+ public List<? extends HCLExpression> elements() {
+ return List.of(left, right);
}
-
}
- public final static class Unary extends HCLArithmeticOperation {
- public final HCLExpression operand;
-
- public Unary(Operator op, HCLExpression operand) {
- super(op);
- this.operand = operand;
- }
-
+ public record Unary(Operator op, HCLExpression operand) implements
HCLArithmeticOperation {
@Override
public String asString() {
return op.toString() + operand.toString();
}
@Override
- public List<? extends HCLExpression> getChildren() {
- return Collections.singletonList(operand);
+ public List<? extends HCLExpression> elements() {
+ return List.of(operand);
}
-
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLAttribute.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLAttribute.java
index 64ea0a16e9..0ad41a869a 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLAttribute.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLAttribute.java
@@ -18,46 +18,21 @@
*/
package org.netbeans.modules.languages.hcl.ast;
+import java.util.List;
+
/**
*
* @author Laszlo Kishalmi
*/
-public final class HCLAttribute extends HCLAddressableElement {
-
- final HCLIdentifier name;
- final HCLExpression value;
- final int group;
+public record HCLAttribute(HCLIdentifier name, HCLExpression value) implements
HCLElement {
- public HCLAttribute(HCLContainer parent, HCLIdentifier name, HCLExpression
value, int group) {
- super(parent);
- this.name = name;
- this.value = value;
- this.group = group;
- }
-
- @Override
public String id() {
return name.id();
}
- public HCLIdentifier getName() {
- return name;
- }
-
- public HCLExpression getValue() {
- return value;
- }
-
- public int getGroup() {
- return group;
- }
-
@Override
- public void accept(Visitor v) {
- if (!v.visit(this) && (value != null)) {
- value.accept(v);
- }
+ public List<? extends HCLElement> elements() {
+ return value != null ? List.of(name, value) : List.of(name);
}
-
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlock.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlock.java
index 7967d9af61..e6478044ac 100644
--- a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlock.java
+++ b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlock.java
@@ -18,35 +18,46 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
/**
*
* @author Laszlo Kishalmi
*/
-public class HCLBlock extends HCLContainer {
+public final class HCLBlock extends HCLContainer {
- private List<HCLIdentifier> declaration;
- private String id;
+ private final String id;
- public HCLBlock(HCLContainer parent) {
- super(parent);
+ private final List<HCLIdentifier> declaration;
+
+ public HCLBlock(List<HCLIdentifier> declaration, List<HCLElement>
elements) {
+ super(elements);
+ this.declaration = List.copyOf(declaration);
+ this.id = declaration.stream().map(d ->
d.id()).collect(Collectors.joining("."));
}
- void setDeclaration(List<HCLIdentifier> declaration) {
- this.declaration = Collections.unmodifiableList(declaration);
- id = declaration.stream().map(d ->
d.id()).collect(Collectors.joining("."));
+ public List<HCLIdentifier> declaration() {
+ return declaration;
}
-
- @Override
public String id() {
return id;
}
+ @Override
+ public String toString() {
+ return "HCLBlock[declaration=" + declaration + ", elements=" +
elements + "]";
+ }
- public List<HCLIdentifier> getDeclaration() {
- return declaration;
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof HCLBlock that ? Objects.equals(this.declaration,
that.declaration) && Objects.equals(this.elements, that.elements) : false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(declaration, elements);
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlockFactory.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlockFactory.java
index 3f3bed8773..b2474fc929 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlockFactory.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLBlockFactory.java
@@ -19,6 +19,7 @@
package org.netbeans.modules.languages.hcl.ast;
import java.util.ArrayList;
+import java.util.List;
import java.util.function.Consumer;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
@@ -32,16 +33,14 @@ import org.netbeans.modules.languages.hcl.grammar.HCLParser;
*
* @author lkishalmi
*/
-public class HCLBlockFactory {
-
- private final Consumer<HCLElement.CreateContext> createAction;
+public final class HCLBlockFactory extends HCLElementFactory {
private final HCLExpressionFactory exprFactory;
private int group = 0;
private ParserRuleContext prev = null;
- public HCLBlockFactory(Consumer<HCLElement.CreateContext> createAction) {
- this.createAction = createAction;
+ public HCLBlockFactory(Consumer<CreateContext> createAction) {
+ super(createAction);
this.exprFactory = new HCLExpressionFactory(createAction);
}
@@ -50,27 +49,23 @@ public class HCLBlockFactory {
}
public final HCLDocument process(HCLParser.ConfigFileContext ctx) {
- var ret = new HCLDocument();
- if (ctx.body() != null) {
- body(ret, ctx.body());
- }
- return ret;
+ return new HCLDocument(ctx.body() != null ? body(ctx.body()) :
List.of());
}
- protected HCLBlock block(HCLContainer parent, HCLParser.BlockContext ctx) {
- HCLBlock ret = created(new HCLBlock(parent), ctx);
+ protected HCLBlock block(HCLParser.BlockContext ctx) {
+ ArrayList<HCLElement> elements = new ArrayList<>();
if (ctx.body() != null) {
- body(ret, ctx.body());
+ elements.addAll(body(ctx.body()));
}
- ArrayList<HCLIdentifier> decl = new ArrayList<>(4);
+ List<HCLIdentifier> decl = new ArrayList<>(4);
if (ctx.children != null) {
for (ParseTree pt : ctx.children) {
- if (pt instanceof TerminalNode) {
- Token token = ((TerminalNode) pt).getSymbol();
+ if (pt instanceof TerminalNode tn) {
+ Token token = tn.getSymbol();
if (token.getType() == HCLLexer.IDENTIFIER) {
HCLIdentifier attrName = created(new
HCLIdentifier.SimpleId( token.getText()), token);
if (pt instanceof ErrorNode) {
@@ -78,15 +73,14 @@ public class HCLBlockFactory {
if (prev != null) {
group += prev.stop.getLine() + 1 <
token.getLine() ? 1 : 0;
}
- HCLAttribute attr = created(new HCLAttribute(ret,
attrName, null, group), token);
- ret.add(attr);
+ HCLAttribute attr = created(new
HCLAttribute(attrName, null), token, token, group);
+ elements.add(attr);
} else {
decl.add(attrName);
}
}
}
- if (pt instanceof HCLParser.StringLitContext) {
- HCLParser.StringLitContext slit =
(HCLParser.StringLitContext) pt;
+ if (pt instanceof HCLParser.StringLitContext slit) {
String sid = slit.getText();
if (sid.length() > 1) { // Do not process the '"' string
literal
sid = sid.substring(1, sid.length() -
(sid.endsWith("\"") ? 1 : 0));
@@ -97,59 +91,41 @@ public class HCLBlockFactory {
}
}
- ret.setDeclaration(decl);
-
- return ret;
+ return created(new HCLBlock(decl, elements), ctx);
}
- protected void body(HCLContainer c, HCLParser.BodyContext ctx) {
+ protected List<HCLElement> body(HCLParser.BodyContext ctx) {
+ List<HCLElement> c = new ArrayList<>();
if (ctx.children != null) {
for (ParseTree pt : ctx.children) {
- if (pt instanceof HCLParser.AttributeContext) {
- HCLParser.AttributeContext actx =
(HCLParser.AttributeContext) pt;
+ if (pt instanceof HCLParser.AttributeContext actx) {
if (prev != null) {
group += prev.stop.getLine() + 1 <
actx.start.getLine() ? 1 : 0;
}
HCLIdentifier attrName = created(new
HCLIdentifier.SimpleId(actx.IDENTIFIER().getText()),
actx.IDENTIFIER().getSymbol());
HCLExpression attrValue =
exprFactory.process(actx.expression());
- HCLAttribute attr = created(new HCLAttribute(c, attrName,
attrValue, group), actx);
+ HCLAttribute attr = created(new HCLAttribute(attrName,
attrValue), actx, group);
c.add(attr);
prev = actx;
continue;
}
- if (pt instanceof HCLParser.BlockContext) {
- c.add(block(c, (HCLParser.BlockContext) pt));
+ if (pt instanceof HCLParser.BlockContext bct) {
+ c.add(block(bct));
continue;
}
- if (pt instanceof ErrorNode) {
- Token token = ((ErrorNode) pt).getSymbol();
+ if (pt instanceof ErrorNode en) {
+ Token token = en.getSymbol();
if (token.getType() == HCLLexer.IDENTIFIER) {
if (prev != null) {
group += prev.stop.getLine() + 1 < token.getLine()
? 1 : 0;
}
HCLIdentifier attrName = created(new
HCLIdentifier.SimpleId(token.getText()), token);
- HCLAttribute attr = new HCLAttribute(c, attrName,
null, group);
+ HCLAttribute attr = new HCLAttribute(attrName, null);
//TODO: created?
c.add(attr);
}
}
}
}
+ return c;
}
-
- private <E extends HCLElement> E created(E element, Token token) {
- elementCreated(element, token, token);
- return element;
- }
-
- private <E extends HCLElement> E created(E element, ParserRuleContext ctx)
{
- elementCreated(element, ctx.start, ctx.stop);
- return element;
- }
-
- private void elementCreated(HCLElement element, Token start, Token stop) {
- if (createAction != null) {
- createAction.accept(new HCLElement.CreateContext(element, start,
stop));
- }
- }
-
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLCollection.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLCollection.java
index bbb740b8ff..02acecad40 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLCollection.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLCollection.java
@@ -18,8 +18,6 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;
@@ -27,21 +25,14 @@ import java.util.StringJoiner;
*
* @author lkishalmi
*/
-public abstract class HCLCollection<T> extends HCLExpression {
+public sealed interface HCLCollection<T> extends HCLExpression {
- public final List<T> elements;
+ public record Tuple(List<HCLExpression> elements) implements
HCLCollection<HCLExpression> {
- public HCLCollection(List<T> elements) {
- this.elements = Collections.unmodifiableList(elements);
- }
-
- public static final class Tuple extends HCLCollection<HCLExpression> {
-
-
- public Tuple(List<HCLExpression> elements) {
- super(elements);
+ public Tuple {
+ elements = List.copyOf(elements);
}
-
+
@Override
public String asString() {
StringJoiner sj = new StringJoiner(",", "[", "]");
@@ -51,52 +42,24 @@ public abstract class HCLCollection<T> extends
HCLExpression {
return sj.toString();
}
- @Override
- public List<? extends HCLExpression> getChildren() {
- return elements;
- }
-
}
-
- public static final class ObjectElement {
- public final HCLExpression key;
- public final HCLExpression value;
- public final int group;
- public ObjectElement(HCLExpression key, HCLExpression value, int
group) {
- this.key = key;
- this.value = value;
- this.group = group;
+ public record ObjectElement(HCLExpression key, HCLExpression value)
implements HCLExpression {
+ @Override
+ public String asString() {
+ return key.asString() + "=" + value.asString();
}
@Override
- public String toString() {
- return key.asString() + "=" + value.asString();
+ public List<? extends HCLExpression> elements() {
+ return List.of(key, value);
}
-
-
}
- public static final class Object extends HCLCollection<ObjectElement> {
+ public record Object(List<ObjectElement> elements) implements
HCLCollection<ObjectElement> {
- private final List<? extends HCLExpression> parts;
- private final List<? extends HCLExpression> keys;
- private final List<? extends HCLExpression> values;
-
- public Object(List<ObjectElement> elements) {
- super(elements);
- List<HCLExpression> p = new ArrayList<>(elements.size() * 2);
- List<HCLExpression> k = new ArrayList<>(elements.size());
- List<HCLExpression> v = new ArrayList<>(elements.size());
- for (ObjectElement e : elements) {
- k.add(e.key);
- v.add(e.value);
- p.add(e.key);
- p.add(e.value);
- }
- parts = Collections.unmodifiableList(p);
- keys = Collections.unmodifiableList(k);
- values = Collections.unmodifiableList(v);
+ public Object {
+ elements = List.copyOf(elements);
}
@Override
@@ -106,20 +69,6 @@ public abstract class HCLCollection<T> extends
HCLExpression {
sj.add(element.toString());
}
return sj.toString();
- }
-
- public List<? extends HCLExpression> getKeys() {
- return keys;
- }
-
- public List<? extends HCLExpression> getValues() {
- return values;
- }
-
- @Override
- public List<? extends HCLExpression> getChildren() {
- return parts;
- }
-
+ }
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLConditionalOperation.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLConditionalOperation.java
index 1980d5b51e..1072ff65ec 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLConditionalOperation.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLConditionalOperation.java
@@ -25,17 +25,7 @@ import java.util.List;
*
* @author lkishalmi
*/
-public final class HCLConditionalOperation extends HCLExpression {
-
- final HCLExpression condition;
- final HCLExpression trueValue;
- final HCLExpression falseValue;
-
- public HCLConditionalOperation(HCLExpression condition, HCLExpression
trueValue, HCLExpression falseValue) {
- this.condition = condition;
- this.trueValue = trueValue;
- this.falseValue = falseValue;
- }
+public record HCLConditionalOperation(HCLExpression condition, HCLExpression
trueValue, HCLExpression falseValue) implements HCLExpression {
@Override
public String asString() {
@@ -43,7 +33,7 @@ public final class HCLConditionalOperation extends
HCLExpression {
}
@Override
- public List<? extends HCLExpression> getChildren() {
+ public List<? extends HCLExpression> elements() {
return Arrays.asList(condition, trueValue, falseValue);
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLContainer.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLContainer.java
index 87e6559aa7..9b0ca868f5 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLContainer.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLContainer.java
@@ -18,59 +18,42 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
/**
*
* @author Laszlo Kishalmi
*/
-public abstract class HCLContainer extends HCLAddressableElement {
- final List<HCLElement> elements = new LinkedList<>();
+public sealed abstract class HCLContainer implements HCLElement permits
HCLBlock, HCLDocument {
- final List<HCLBlock> blocks = new LinkedList<>();
- final List<HCLAttribute> attributes = new LinkedList<>();
+ protected final List<HCLElement> elements;
+ private final List<HCLBlock> blocks;
+ private final List<HCLAttribute> attributes;
- public HCLContainer(HCLContainer parent) {
- super(parent);
+ protected HCLContainer(List<HCLElement> elements) {
+ this.elements = List.copyOf(elements);
+ this.blocks =
elements.stream().filter(HCLBlock.class::isInstance).map(HCLBlock.class::cast).toList();
+ this.attributes =
elements.stream().filter(HCLAttribute.class::isInstance).map(HCLAttribute.class::cast).toList();
}
- public void add(HCLBlock block) {
- elements.add(block);
- blocks.add(block);
+ public boolean hasBlock() {
+ return !blocks.isEmpty();
}
- public void add(HCLAttribute attr) {
- elements.add(attr);
- attributes.add(attr);
- }
-
- @Override
- public HCLContainer getContainer() {
- return (HCLContainer) parent;
- }
-
- public Collection<? extends HCLBlock> getBlocks() {
- return Collections.unmodifiableCollection(blocks);
+ public boolean hasAttribute() {
+ return !attributes.isEmpty();
}
- public Collection<? extends HCLAttribute> getAttributes() {
- return Collections.unmodifiableCollection(attributes);
+ public List<HCLBlock> blocks() {
+ return blocks;
}
- public boolean hasAttributes() {
- return !attributes.isEmpty();
+ public List<HCLAttribute> attributes() {
+ return attributes;
}
-
+
@Override
- public final void accept(Visitor v) {
- if (!v.visit(this)) {
- for (HCLElement element : elements) {
- element.accept(v);
- }
- }
+ public List<? extends HCLElement> elements() {
+ return elements;
}
-
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLDocument.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLDocument.java
index dfe65d93b1..41f41eff84 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLDocument.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLDocument.java
@@ -18,19 +18,32 @@
*/
package org.netbeans.modules.languages.hcl.ast;
+import java.util.List;
+import java.util.Objects;
+
/**
*
* @author Laszlo Kishalmi
*/
public final class HCLDocument extends HCLContainer {
- public HCLDocument() {
- super(null);
+ public HCLDocument(List<HCLElement> elements) {
+ super(elements);
+ }
+
+ @Override
+ public String toString() {
+ return "HCLDocument[elements=" + elements + "]";
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof HCLDocument that ? Objects.equals(this.elements,
that.elements) : false;
}
@Override
- public String id() {
- return "<hcl>";
+ public int hashCode() {
+ return Objects.hashCode(elements);
}
-
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLElement.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLElement.java
index 3c4b54f5fd..017efae28b 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLElement.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLElement.java
@@ -18,81 +18,12 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import org.antlr.v4.runtime.Token;
+import java.util.List;
/**
*
* @author Laszlo Kishalmi
*/
-public abstract class HCLElement {
-
- public abstract void accept(Visitor v);
-
- public interface Visitor {
- /**
- * Visit the given element. Shall return {@code true} if the visit
- * shall be finished at this level in the element tree.
- *
- * @param e the element to visit.
- * @return {@code false} if the visit shall continue on the subtree of
- * the given element.
- */
- boolean visit(HCLElement e);
- }
-
- /**
- * Convenience Visitor implementation, where the HCLElements are split to
- * Block, Attribute, and Expression types.
- */
- public abstract static class BAEVisitor implements Visitor {
- @Override
- public boolean visit(HCLElement e) {
- if (e instanceof HCLBlock) {
- return visitBlock((HCLBlock)e);
- } else if (e instanceof HCLAttribute) {
- return visitAttribute((HCLAttribute) e);
- } else if (e instanceof HCLExpression) {
- return visitExpression((HCLExpression) e);
- }
- return false;
- }
-
- protected abstract boolean visitBlock(HCLBlock block);
-
- protected abstract boolean visitAttribute(HCLAttribute attr);
-
- protected abstract boolean visitExpression(HCLExpression expr);
- }
-
- public static class BAEVisitorAdapter extends BAEVisitor {
-
- @Override
- protected boolean visitBlock(HCLBlock block) {
- return false;
- }
-
- @Override
- protected boolean visitAttribute(HCLAttribute attr) {
- return false;
- }
-
- @Override
- protected boolean visitExpression(HCLExpression expr) {
- return false;
- }
-
- }
-
- public static final class CreateContext {
- public final HCLElement element;
- public final Token start;
- public final Token stop;
-
- public CreateContext(HCLElement element, Token start, Token stop) {
- this.element = element;
- this.start = start;
- this.stop = stop;
- }
-
- }
+public sealed interface HCLElement permits HCLExpression, HCLIdentifier,
HCLContainer, HCLAttribute {
+ List<? extends HCLElement> elements();
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLElementFactory.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLElementFactory.java
new file mode 100644
index 0000000000..3b84857a1f
--- /dev/null
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLElementFactory.java
@@ -0,0 +1,75 @@
+/*
+ * 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.ast;
+
+import java.util.function.Consumer;
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.tree.TerminalNode;
+import org.netbeans.modules.languages.hcl.grammar.HCLLexer;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public sealed abstract class HCLElementFactory permits HCLBlockFactory,
HCLExpressionFactory {
+ public record CreateContext(HCLElement element, Token start, Token stop,
int group) {}
+
+ private final Consumer<CreateContext> createAction;
+
+ public HCLElementFactory(Consumer<CreateContext> createAction) {
+ this.createAction = createAction;
+ }
+
+ protected final HCLIdentifier id(TerminalNode tn) {
+ return tn != null ? id(tn.getSymbol()) : null;
+ }
+
+ protected final HCLIdentifier id(Token t) {
+ return (t != null) && (t.getType() == HCLLexer.IDENTIFIER) ?
created(new HCLIdentifier.SimpleId(t.getText()), t) : null;
+ }
+
+ protected final <E extends HCLElement> E created(E element, Token token) {
+ return created(element, token, token);
+ }
+
+ protected final <E extends HCLElement> E created(E element,
ParserRuleContext ctx) {
+ return created(element, ctx.start, ctx.stop);
+ }
+
+ protected final <E extends HCLElement> E created(E element,
ParserRuleContext ctx, int group) {
+ return created(element, ctx.start, ctx.stop, group);
+ }
+
+ protected final <E extends HCLElement> E created(E element, Token start,
Token stop) {
+ elementCreated(element, start, stop, -1);
+ return element;
+ }
+
+ protected final <E extends HCLElement> E created(E element, Token start,
Token stop, int group) {
+ elementCreated(element, start, stop, group);
+ return element;
+ }
+
+ protected final void elementCreated(HCLElement element, Token start, Token
stop, int group) {
+ if (createAction != null) {
+ createAction.accept(new CreateContext(element, start, stop,
group));
+ }
+ }
+}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpression.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpression.java
index 15ed91a722..344f029dba 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpression.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpression.java
@@ -18,6 +18,7 @@
*/
package org.netbeans.modules.languages.hcl.ast;
+import java.util.Collections;
import java.util.List;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
@@ -28,30 +29,28 @@ import org.netbeans.modules.languages.hcl.grammar.HCLParser;
*
* @author lkishalmi
*/
-public abstract class HCLExpression extends HCLElement {
+public sealed interface HCLExpression extends HCLElement permits
+ HCLArithmeticOperation,
+ HCLCollection,
+ HCLCollection.ObjectElement,
+ HCLConditionalOperation,
+ HCLForExpression,
+ HCLFunction,
+ HCLLiteral,
+ HCLResolveOperation,
+ HCLTemplate,
+ HCLVariable {
public static HCLExpression parse(String expr) {
HCLLexer lexer = new HCLLexer(CharStreams.fromString(expr));
HCLParser parser = new HCLParser(new CommonTokenStream(lexer));
return new HCLExpressionFactory().process(parser.expression());
}
-
- public String toString() {
- return getClass().getSimpleName() + ": " + asString();
+
+ default List<? extends HCLExpression> elements() {
+ return Collections.emptyList();
}
-
- public abstract List<? extends HCLExpression> getChildren();
-
+
public abstract String asString();
-
- @Override
- public final void accept(Visitor v) {
- if (!v.visit(this)) {
- for (HCLExpression c : getChildren()) {
- if (c != null) {
- c.accept(v);
- }
- }
- }
- }
+
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpressionFactory.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpressionFactory.java
index 3ca0ef8665..455ae4806b 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpressionFactory.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLExpressionFactory.java
@@ -26,9 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import org.antlr.v4.runtime.NoViableAltException;
import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
-import org.antlr.v4.runtime.tree.TerminalNode;
import org.netbeans.modules.languages.hcl.grammar.HCLLexer;
import static org.netbeans.modules.languages.hcl.grammar.HCLLexer.*;
import org.netbeans.modules.languages.hcl.grammar.HCLParser;
@@ -37,12 +35,10 @@ import org.netbeans.modules.languages.hcl.grammar.HCLParser;
*
* @author lkishalmi
*/
-public class HCLExpressionFactory {
+public final class HCLExpressionFactory extends HCLElementFactory {
- private final Consumer<HCLElement.CreateContext> createAction;
-
- public HCLExpressionFactory(Consumer<HCLElement.CreateContext>
createAction) {
- this.createAction = createAction;
+ public HCLExpressionFactory(Consumer<CreateContext> createAction) {
+ super(createAction);
}
public HCLExpressionFactory() {
@@ -65,12 +61,11 @@ public class HCLExpressionFactory {
return created(new HCLArithmeticOperation.Binary(op,
expr(ctx.left), expr(ctx.right)), ctx);
}
if (ctx.right != null) {
- switch (ctx.op.getType()) {
- case NOT:
- return created(new
HCLArithmeticOperation.Unary(HCLArithmeticOperation.Operator.NOT,
expr(ctx.right)), ctx);
- case MINUS:
- return created(new
HCLArithmeticOperation.Unary(HCLArithmeticOperation.Operator.MINUS,
expr(ctx.right)), ctx);
- }
+ return switch (ctx.op.getType()) {
+ case NOT -> created(new
HCLArithmeticOperation.Unary(HCLArithmeticOperation.Operator.NOT,
expr(ctx.right)), ctx);
+ case MINUS -> created(new
HCLArithmeticOperation.Unary(HCLArithmeticOperation.Operator.MINUS,
expr(ctx.right)), ctx);
+ default -> throw new
UnsupportedOperationException("Unsupported expression: " + ctx.getText());
+ };
}
if (ctx.exprCond != null && ctx.exprTrue != null && ctx.exprFalse
!= null) {
return created(new HCLConditionalOperation(expr(ctx.exprCond),
expr(ctx.exprTrue), expr(ctx.exprFalse)), ctx);
@@ -109,8 +104,7 @@ public class HCLExpressionFactory {
ret = expr(ctx.exprTerm(), splat);
}
if (ctx.exception != null) {
- if (ctx.exception instanceof NoViableAltException) {
- NoViableAltException nva = (NoViableAltException)
ctx.exception;
+ if (ctx.exception instanceof NoViableAltException nva) {
if (nva.getStartToken().getType() == HCLLexer.DOT) {
//Most probably a single DOT would mean a started
attribute resolve expression
//Let's create an empty one on the fly
@@ -168,7 +162,8 @@ public class HCLExpressionFactory {
if ((prev != null) && (ec.key != null)) {
group += prev.stop.getLine() + 1 < ec.key.start.getLine()
? 1 : 0;
}
- elements.add(new HCLCollection.ObjectElement(expr(ec.key),
expr(ec.value), group));
+ HCLCollection.ObjectElement oe = new
HCLCollection.ObjectElement(expr(ec.key), expr(ec.value));
+ elements.add(created(oe, ec, group));
prev = ec;
}
return new HCLCollection.Object(elements);
@@ -193,36 +188,22 @@ public class HCLExpressionFactory {
}
private static HCLArithmeticOperation.Operator binOp(int tokenType) {
- switch (tokenType) {
- case STAR:
- return HCLArithmeticOperation.Operator.MUL;
- case SLASH:
- return HCLArithmeticOperation.Operator.DIV;
- case PERCENT:
- return HCLArithmeticOperation.Operator.MOD;
- case PLUS:
- return HCLArithmeticOperation.Operator.ADD;
- case MINUS:
- return HCLArithmeticOperation.Operator.SUB;
- case OR:
- return HCLArithmeticOperation.Operator.OR;
- case AND:
- return HCLArithmeticOperation.Operator.AND;
- case LT:
- return HCLArithmeticOperation.Operator.LT;
- case LTE:
- return HCLArithmeticOperation.Operator.LTE;
- case GT:
- return HCLArithmeticOperation.Operator.GT;
- case GTE:
- return HCLArithmeticOperation.Operator.GTE;
- case EQUALS:
- return HCLArithmeticOperation.Operator.EQUALS;
- case NOT_EQUALS:
- return HCLArithmeticOperation.Operator.NOT_EQUALS;
- default:
- return null;
- }
+ return switch (tokenType) {
+ case STAR -> HCLArithmeticOperation.Operator.MUL;
+ case SLASH -> HCLArithmeticOperation.Operator.DIV;
+ case PERCENT -> HCLArithmeticOperation.Operator.MOD;
+ case PLUS -> HCLArithmeticOperation.Operator.ADD;
+ case MINUS -> HCLArithmeticOperation.Operator.SUB;
+ case OR -> HCLArithmeticOperation.Operator.OR;
+ case AND -> HCLArithmeticOperation.Operator.AND;
+ case LT -> HCLArithmeticOperation.Operator.LT;
+ case LTE -> HCLArithmeticOperation.Operator.LTE;
+ case GT -> HCLArithmeticOperation.Operator.GT;
+ case GTE -> HCLArithmeticOperation.Operator.GTE;
+ case EQUALS -> HCLArithmeticOperation.Operator.EQUALS;
+ case NOT_EQUALS -> HCLArithmeticOperation.Operator.NOT_EQUALS;
+ default -> null;
+ };
}
protected HCLExpression expr(HCLParser.TemplateExprContext ctx) {
@@ -267,13 +248,13 @@ public class HCLExpressionFactory {
if (ctx.heredocTemplate() != null && ctx.heredocTemplate().children !=
null) {
for (ParseTree pt : ctx.heredocTemplate().children) {
if (pt instanceof HCLParser.HeredocContentContext) {
- parts.add(new HCLTemplate.StringPart(pt.getText()));
+ parts.add(new HCLTemplate.Part.StringPart(pt.getText()));
}
if (pt instanceof HCLParser.InterpolationContext) {
- parts.add(new HCLTemplate.InterpolationPart(pt.getText()));
+ parts.add(new
HCLTemplate.Part.InterpolationPart(pt.getText()));
}
if (pt instanceof HCLParser.TemplateContext) {
- parts.add(new HCLTemplate.TemplatePart(pt.getText()));
+ parts.add(new HCLTemplate.Part.TemplatePart(pt.getText()));
}
}
}
@@ -287,13 +268,13 @@ public class HCLExpressionFactory {
LinkedList<HCLTemplate.Part> parts = new LinkedList<>();
for (ParseTree pt : ctx.children) {
if (pt instanceof HCLParser.StringContentContext) {
- parts.add(new HCLTemplate.StringPart(pt.getText()));
+ parts.add(new HCLTemplate.Part.StringPart(pt.getText()));
}
if (pt instanceof HCLParser.InterpolationContext) {
- parts.add(new HCLTemplate.InterpolationPart(pt.getText()));
+ parts.add(new
HCLTemplate.Part.InterpolationPart(pt.getText()));
}
if (pt instanceof HCLParser.TemplateContext) {
- parts.add(new HCLTemplate.TemplatePart(pt.getText()));
+ parts.add(new HCLTemplate.Part.TemplatePart(pt.getText()));
}
}
return new HCLTemplate.StringTemplate(parts);
@@ -308,7 +289,7 @@ public class HCLExpressionFactory {
HCLParser.ForIntroContext intro = isTuple ?
ctx.forTupleExpr().forIntro() : ctx.forObjectExpr().forIntro();
HCLIdentifier keyVar = null;
- HCLIdentifier valueVar = null;
+ HCLIdentifier valueVar;
if (intro.second != null) {
keyVar = id(intro.first);
valueVar = id(intro.second);
@@ -342,12 +323,11 @@ public class HCLExpressionFactory {
if (splat.fullSplat() != null) {
base = expr(base, splat);
for (ParseTree pt : splat.fullSplat().children) {
- if (pt instanceof HCLParser.GetAttrContext) {
- HCLParser.GetAttrContext ac = (HCLParser.GetAttrContext)
pt;
- base = expr(base, ac);
+ if (pt instanceof HCLParser.GetAttrContext gac) {
+ base = expr(base, gac);
}
- if (pt instanceof HCLParser.IndexContext) {
- base = expr(base, (HCLParser.IndexContext) pt);
+ if (pt instanceof HCLParser.IndexContext ic) {
+ base = expr(base, ic);
}
}
}
@@ -377,31 +357,4 @@ public class HCLExpressionFactory {
return created(new HCLResolveOperation.Index(base, index,
idx.LEGACY_INDEX() != null), idx);
}
-
- private HCLIdentifier id(TerminalNode tn) {
- return tn != null ? id(tn.getSymbol()) : null;
- }
-
- protected HCLIdentifier id(Token t) {
- return (t != null) && (t.getType() == HCLLexer.IDENTIFIER) ?
created(new HCLIdentifier.SimpleId(t.getText()), t) : null;
- }
-
- private <E extends HCLElement> E created(E element, Token token) {
- return created(element, token, token);
- }
-
- private <E extends HCLElement> E created(E element, ParserRuleContext ctx)
{
- return created(element, ctx.start, ctx.stop);
- }
-
- private <E extends HCLElement> E created(E element, Token start, Token
stop) {
- elementCreated(element, start, stop);
- return element;
- }
-
- private void elementCreated(HCLElement element, Token start, Token stop) {
- if (createAction != null) {
- createAction.accept(new HCLElement.CreateContext(element, start,
stop));
- }
- }
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLForExpression.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLForExpression.java
index 6b499026c7..4326685488 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLForExpression.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLForExpression.java
@@ -18,36 +18,21 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Arrays;
import java.util.List;
/**
*
* @author lkishalmi
*/
-public abstract class HCLForExpression extends HCLExpression {
+public sealed interface HCLForExpression extends HCLExpression {
- public final HCLIdentifier keyVar;
- public final HCLIdentifier valueVar;
+ HCLIdentifier keyVar();
+ HCLIdentifier valueVar();
- public final HCLExpression iterable;
- public final HCLExpression condition;
+ HCLExpression iterable();
+ HCLExpression condition();
- public HCLForExpression(HCLIdentifier keyVar, HCLIdentifier valueVar,
HCLExpression iterable, HCLExpression condition) {
- this.keyVar = keyVar;
- this.valueVar = valueVar;
- this.iterable = iterable;
- this.condition = condition;
- }
-
- public final static class Tuple extends HCLForExpression {
-
- public final HCLExpression result;
-
- public Tuple(HCLIdentifier keyVar, HCLIdentifier valueVar,
HCLExpression iterable, HCLExpression condition, HCLExpression result) {
- super(keyVar, valueVar, iterable, condition);
- this.result = result;
- }
+ public record Tuple(HCLIdentifier keyVar, HCLIdentifier valueVar,
HCLExpression iterable, HCLExpression condition, HCLExpression result)
implements HCLForExpression {
@Override
public String asString() {
@@ -66,24 +51,12 @@ public abstract class HCLForExpression extends
HCLExpression {
}
@Override
- public List<? extends HCLExpression> getChildren() {
- return Arrays.asList(iterable, result, condition);
+ public List<? extends HCLExpression> elements() {
+ return List.of(iterable, result, condition);
}
}
- public final static class Object extends HCLForExpression {
- public final HCLExpression resultKey;
- public final HCLExpression resultValue;
-
- public final boolean grouping;
-
- public Object(HCLIdentifier keyVar, HCLIdentifier valueVar,
HCLExpression iterable, HCLExpression condition, HCLExpression resultKey,
HCLExpression resultValue, boolean grouping) {
- super(keyVar, valueVar, iterable, condition);
- this.resultKey = resultKey;
- this.resultValue = resultValue;
- this.grouping = grouping;
- }
-
+ public record Object(HCLIdentifier keyVar, HCLIdentifier valueVar,
HCLExpression iterable, HCLExpression condition, HCLExpression resultKey,
HCLExpression resultValue, boolean grouping) implements HCLForExpression {
@Override
public String asString() {
StringBuilder sb = new StringBuilder();
@@ -104,8 +77,8 @@ public abstract class HCLForExpression extends HCLExpression
{
}
@Override
- public List<? extends HCLExpression> getChildren() {
- return Arrays.asList(iterable, resultKey, resultValue, condition);
+ public List<? extends HCLExpression> elements() {
+ return List.of(iterable, resultKey, resultValue, condition);
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLFunction.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLFunction.java
index 2900359f9e..f2556a5384 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLFunction.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLFunction.java
@@ -25,24 +25,10 @@ import java.util.StringJoiner;
*
* @author lkishalmi
*/
-public class HCLFunction extends HCLExpression {
+public record HCLFunction(HCLIdentifier name, List<HCLExpression> args,
boolean expand) implements HCLExpression {
- final HCLIdentifier name;
- final List<HCLExpression> args;
- final boolean expand;
-
- public HCLFunction(HCLIdentifier name, List<HCLExpression> args, boolean
expand) {
- this.name = name;
- this.args = args;
- this.expand = expand;
- }
-
- public HCLIdentifier getName() {
- return name;
- }
-
- public List<HCLExpression> getArgs() {
- return args;
+ public HCLFunction {
+ args = List.copyOf(args);
}
@Override
@@ -53,9 +39,7 @@ public class HCLFunction extends HCLExpression {
}
@Override
- public List<? extends HCLExpression> getChildren() {
- return args;
- }
-
-
+ public List<? extends HCLExpression> elements() {
+ return args();
+ }
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLIdentifier.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLIdentifier.java
index 32270c80c4..1dd48e8ad5 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLIdentifier.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLIdentifier.java
@@ -18,49 +18,22 @@
*/
package org.netbeans.modules.languages.hcl.ast;
+import java.util.List;
+
/**
*
* @author Laszlo Kishalmi
*/
-public abstract class HCLIdentifier extends HCLElement {
+public sealed interface HCLIdentifier extends HCLElement {
- public final String id;
+ String id();
- public HCLIdentifier(String id) {
- this.id = id;
- }
-
- public String id() {
- return id;
- }
-
@Override
- public final void accept(Visitor v) {
- v.visit(this);
- }
-
- public final static class SimpleId extends HCLIdentifier {
-
- public SimpleId(String id) {
- super(id);
- }
-
- @Override
- public String toString() {
- return id;
- }
+ default List<? extends HCLElement> elements() {
+ return List.of();
}
+
+ public record SimpleId(String id) implements HCLIdentifier {}
- public final static class StringId extends HCLIdentifier {
-
- public StringId(String id) {
- super(id);
- }
-
- @Override
- public String toString() {
- return "\"" + id + "\"";
- }
-
- }
+ public record StringId(String id) implements HCLIdentifier {}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLLiteral.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLLiteral.java
index 7ecd99d2dc..6ebd069f99 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLLiteral.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLLiteral.java
@@ -18,45 +18,25 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Collections;
-import java.util.List;
-
/**
*
* @author lkishalmi
*/
-public abstract class HCLLiteral extends HCLExpression {
+public sealed interface HCLLiteral extends HCLExpression {
public static final Bool TRUE = new Bool(true);
public static final Bool FALSE = new Bool(false);
public static final Null NULL = new Null();
- @Override
- public final List<? extends HCLExpression> getChildren() {
- return Collections.emptyList();
- }
- public static final class Bool extends HCLLiteral {
-
- final boolean value;
-
- private Bool(boolean value) {
- this.value = value;
- }
-
+ public record Bool(boolean value) implements HCLLiteral {
@Override
public String asString() {
return value ? "true" : "false";
}
}
- public static final class StringLit extends HCLLiteral {
-
- final String value;
-
- public StringLit(String value) {
- this.value = value;
- }
+ public record StringLit(String value) implements HCLLiteral {
@Override
public String asString() {
@@ -64,25 +44,14 @@ public abstract class HCLLiteral extends HCLExpression {
}
}
- public static final class Null extends HCLLiteral {
-
-
- private Null() {
- }
-
+ public record Null() implements HCLLiteral {
@Override
public String asString() {
return "null"; //NOI18N
}
}
- public static final class NumericLit extends HCLLiteral {
-
- final String value;
-
- public NumericLit(String value) {
- this.value = value;
- }
+ public record NumericLit(String value) implements HCLLiteral {
@Override
public String asString() {
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLResolveOperation.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLResolveOperation.java
index 6586b61fec..4e721f89b3 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLResolveOperation.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLResolveOperation.java
@@ -18,92 +18,50 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
/**
*
* @author lkishalmi
*/
-public abstract class HCLResolveOperation extends HCLExpression {
+public sealed interface HCLResolveOperation extends HCLExpression {
- public final HCLExpression base;
- public HCLResolveOperation(HCLExpression base) {
- this.base = base;
+ HCLExpression base();
+ default List<? extends HCLExpression> elements() {
+ return List.of(base());
}
- @Override
- public List<? extends HCLExpression> getChildren() {
- return Collections.singletonList(base);
- }
-
- public final static class Attribute extends HCLResolveOperation {
- public final HCLIdentifier attr;
-
- public Attribute(HCLExpression base, HCLIdentifier attr) {
- super(base);
- this.attr = attr;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + ": ." + attr;
- }
-
-
+ public record Attribute(HCLExpression base, HCLIdentifier attr) implements
HCLResolveOperation {
@Override
public String asString() {
return base.asString() + "." + attr;
}
-
- }
-
- public final static class Index extends HCLResolveOperation {
- public final HCLExpression index;
- public final boolean legacy;
- public Index(HCLExpression base, HCLExpression index, boolean legacy) {
- super(base);
- this.index = index;
- this.legacy = legacy;
- }
+ }
+ public record Index(HCLExpression base, HCLExpression index, boolean
legacy) implements HCLResolveOperation {
@Override
public String asString() {
return base.asString() + (legacy ? "." + index : "[" + index +
"]");
}
-
@Override
- public List<? extends HCLExpression> getChildren() {
- return Arrays.asList(base, index);
+ public List<? extends HCLExpression> elements() {
+ return List.of(base, index);
}
}
- public final static class AttrSplat extends HCLResolveOperation {
-
- public AttrSplat(HCLExpression base) {
- super(base);
- }
-
+ public record AttrSplat(HCLExpression base) implements HCLResolveOperation
{
@Override
public String asString() {
return base.asString() + ".*";
}
-
}
- public final static class FullSplat extends HCLResolveOperation {
-
- public FullSplat(HCLExpression base) {
- super(base);
- }
-
+ public record FullSplat(HCLExpression base) implements HCLResolveOperation
{
@Override
public String asString() {
return base.asString() + "[*]";
}
-
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLTemplate.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLTemplate.java
index 785b97a95a..4592bbeb44 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLTemplate.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLTemplate.java
@@ -18,85 +18,40 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Collections;
import java.util.List;
/**
*
* @author lkishalmi
*/
-public abstract class HCLTemplate extends HCLExpression {
+public sealed interface HCLTemplate extends HCLExpression {
- public final List<Part> parts;
+ List<? extends Part> parts();
- public HCLTemplate(List<Part> parts) {
- this.parts = Collections.unmodifiableList(parts);
- }
-
- @Override
- public List<? extends HCLExpression> getChildren() {
- return Collections.emptyList();
- }
-
- public abstract static class Part {
- public final String value;
-
- public Part(String value) {
- this.value = value;
- }
- }
-
- public final static class StringPart extends Part {
-
+ public sealed interface Part {
public static final StringPart NL = new StringPart("\n");
- public StringPart(String value) {
- super(value);
- }
-
- @Override
- public String toString() {
- return value;
- }
- }
-
- public final static class InterpolationPart extends Part {
-
- public InterpolationPart(String value) {
- super(value);
+ String value();
+ default String asString() {
+ if (this instanceof StringPart) return value();
+ if (this instanceof InterpolationPart) return "${" + value() + "}";
+ if (this instanceof TemplatePart) return "%{" + value() + "}";
+ return null;
}
- @Override
- public String toString() {
- return "${" + value + "}";
- }
- }
-
- /**
- * This is just a temporal implementation as the template expression
- * should really form a tree.
- */
- public final static class TemplatePart extends Part {
-
- public TemplatePart(String value) {
- super(value);
- }
-
- @Override
- public String toString() {
- return "%{" + value + "}";
- }
-
+ public record StringPart(String value) implements Part {}
+ /**
+ * This is just a temporal implementation as the template expression
+ * should really form a tree.
+ */
+ public record InterpolationPart(String value) implements Part {}
+ public record TemplatePart(String value) implements Part {}
}
- public final static class HereDoc extends HCLTemplate {
- public final String marker;
- public final int indent;
+ public record HereDoc(String marker, int indent, List<Part> parts)
implements HCLTemplate {
- public HereDoc(String marker, int indent, List<Part> parts) {
- super(parts);
- this.marker = marker;
- this.indent = indent;
+ public HereDoc {
+ parts = List.copyOf(parts);
}
public boolean isIndented() {
@@ -115,10 +70,10 @@ public abstract class HCLTemplate extends HCLExpression {
}
}
- public final static class StringTemplate extends HCLTemplate {
+ public record StringTemplate(List<Part> parts) implements HCLTemplate {
- public StringTemplate(List<Part> parts) {
- super(parts);
+ public StringTemplate {
+ parts = List.copyOf(parts);
}
@Override
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLTreeWalker.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLTreeWalker.java
new file mode 100644
index 0000000000..b6378cd41d
--- /dev/null
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLTreeWalker.java
@@ -0,0 +1,58 @@
+/*
+ * 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.ast;
+
+import java.util.LinkedList;
+import java.util.function.Predicate;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public final class HCLTreeWalker {
+ public record Step(HCLElement parent, HCLElement node, int depth) {}
+
+ private HCLTreeWalker() {}
+
+ public static void depthFirst(HCLElement root, Predicate<Step> t) {
+ LinkedList<Step> process = new LinkedList<>();
+ process.push(new Step(null, root, 0));
+ while (!process.isEmpty()) {
+ Step current = process.pop();
+ if (t.test(current)) {
+ for (HCLElement e : current.node.elements()) {
+ process.push(new Step(current.node, e, current.depth + 1));
+ }
+ }
+ }
+ }
+
+ public static void breadthFirst(HCLElement root, Predicate<Step> t) {
+ LinkedList<Step> process = new LinkedList<>();
+ process.add(new Step(null, root, 0));
+ while (!process.isEmpty()) {
+ var current = process.pop();
+ if (t.test(current)) {
+ for (HCLElement e : current.node.elements()) {
+ process.add(new Step(current.node, e, current.depth + 1));
+ }
+ }
+ }
+ }
+}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLVariable.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLVariable.java
index 306b825fc7..84f2779ec6 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLVariable.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/ast/HCLVariable.java
@@ -18,28 +18,14 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import java.util.Collections;
-import java.util.List;
-
/**
*
* @author lkishalmi
*/
-public final class HCLVariable extends HCLExpression {
-
- public final HCLIdentifier name;
-
- public HCLVariable(HCLIdentifier name) {
- this.name = name;
- }
+public record HCLVariable(HCLIdentifier name) implements HCLExpression {
@Override
public String asString() {
- return name.id;
- }
-
- @Override
- public List<? extends HCLExpression> getChildren() {
- return Collections.emptyList();
+ return name.id();
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformParserResult.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformParserResult.java
index 929d467d62..075981e069 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformParserResult.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformParserResult.java
@@ -30,8 +30,7 @@ import org.netbeans.modules.languages.hcl.ast.HCLContainer;
import org.netbeans.modules.languages.hcl.ast.HCLDocument;
import org.netbeans.modules.languages.hcl.ast.HCLIdentifier;
import org.netbeans.modules.languages.hcl.SourceRef;
-import org.netbeans.modules.languages.hcl.ast.HCLElement;
-import org.netbeans.modules.languages.hcl.ast.HCLElement.Visitor;
+import org.netbeans.modules.languages.hcl.ast.HCLTreeWalker;
import org.netbeans.modules.parsing.api.Snapshot;
import org.openide.util.NbBundle.Messages;
@@ -41,18 +40,21 @@ import org.openide.util.NbBundle.Messages;
*/
public class TerraformParserResult extends HCLParserResult {
- private Map<String, HCLBlock> definedBlocks = new HashMap<>();
+ private final Map<String, HCLBlock> definedBlocks = new HashMap<>();
public enum BlockType {
CHECK("check", 2),
DATA("data", 3),
+ IMPORT("import", 1),
LOCALS("locals", 1),
MODULE("module", 2),
MOVED("moved", 1),
OUTPUT("output", 2),
PROVIDER("provider", 2),
+ REMOVED("removed", 1),
RESOURCE("resource", 3),
+ RUN("run", 2),
TERRAFORM("terraform", 1),
VARIABLE("variable", 2);
@@ -97,59 +99,54 @@ public class TerraformParserResult extends HCLParserResult {
})
protected void processDocument(HCLDocument doc, SourceRef references) {
- doc.accept(this::duplicateAttributeVisitor);
- doc.accept(this::checkBlockDeclarationVisitor);
+ HCLTreeWalker.breadthFirst(doc, this::duplicateAttributeVisitor);
+ HCLTreeWalker.breadthFirst(doc, this::checkBlockDeclarationVisitor);
}
+ private boolean checkBlockDeclarationVisitor(HCLTreeWalker.Step step) {
+ if (step.node() instanceof HCLBlock block) {
+ List<HCLIdentifier> decl = block.declaration();
+ HCLIdentifier type = decl.get(0);
- private boolean checkBlockDeclarationVisitor(HCLElement e) {
- if (e instanceof HCLBlock) {
- HCLBlock block = (HCLBlock) e;
- if (block.getParent() instanceof HCLDocument) {
- List<HCLIdentifier> decl = block.getDeclaration();
- HCLIdentifier type = decl.get(0);
-
- BlockType bt = BlockType.get(type.id());
- if (bt != null) {
- if (decl.size() != bt.definitionLength) {
- addError(type,
Bundle.INVALID_BLOCK_DECLARATION(bt.type, bt.definitionLength - 1));
- } else {
- if (definedBlocks.put(block.id(), block) != null) {
- switch (bt) {
- case CHECK:
- case DATA:
- case MODULE:
- case OUTPUT:
- case RESOURCE:
- case VARIABLE:
- addError(decl.get(bt.definitionLength -
1), Bundle.DUPLICATE_BLOCK(block.id()));
- }
+ BlockType bt = BlockType.get(type.id());
+ if (bt != null) {
+ if (decl.size() != bt.definitionLength) {
+ addError(type, Bundle.INVALID_BLOCK_DECLARATION(bt.type,
bt.definitionLength - 1));
+ } else {
+ if (definedBlocks.put(block.id(), block) != null) {
+ switch (bt) {
+ case CHECK:
+ case DATA:
+ case MODULE:
+ case OUTPUT:
+ case RESOURCE:
+ case RUN:
+ case VARIABLE:
+ addError(decl.get(bt.definitionLength - 1),
Bundle.DUPLICATE_BLOCK(block.id()));
}
}
- } else {
- addError(type, Bundle.UNKNOWN_BLOCK(type.id()));
}
+ } else {
+ addError(type, Bundle.UNKNOWN_BLOCK(type.id()));
}
- return true;
}
- return !(e instanceof HCLDocument);
+ // Here we just check the first level of blocks, won't go deeper int
the tree
+ return false;
}
- private boolean duplicateAttributeVisitor(HCLElement e) {
- if (e instanceof HCLDocument) {
- HCLDocument doc = (HCLDocument) e;
- for (HCLAttribute attr : doc.getAttributes()) {
+ private boolean duplicateAttributeVisitor(HCLTreeWalker.Step step) {
+ if (step.node() instanceof HCLDocument doc) {
+ for (HCLAttribute attr : doc.attributes()) {
addError(attr,
Bundle.UNEXPECTED_DOCUMENT_ATTRIBUTE(attr.id()));
}
- return false;
+ return true;
}
- if (e instanceof HCLContainer) {
- HCLContainer c = (HCLContainer) e;
- if (c.hasAttributes()) {
+ if (step.node() instanceof HCLContainer c) {
+ if (c.hasAttribute()) {
Set<String> defined = new HashSet<>();
- for (HCLAttribute attr : c.getAttributes()) {
+ for (HCLAttribute attr : c.attributes()) {
if (!defined.add(attr.id())) {
- addError(attr.getName(),
Bundle.DUPLICATE_ATTRIBUTE(attr.id()));
+ addError(attr.name(),
Bundle.DUPLICATE_ATTRIBUTE(attr.id()));
}
}
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformSemanticAnalyzer.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformSemanticAnalyzer.java
index beb209b693..fa16880a04 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformSemanticAnalyzer.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/terraform/TerraformSemanticAnalyzer.java
@@ -24,12 +24,11 @@ import org.netbeans.modules.csl.api.ColoringAttributes;
import org.netbeans.modules.languages.hcl.HCLSemanticAnalyzer;
import org.netbeans.modules.languages.hcl.HCLParserResult;
import org.netbeans.modules.languages.hcl.ast.HCLBlock;
-import org.netbeans.modules.languages.hcl.ast.HCLDocument;
-import org.netbeans.modules.languages.hcl.ast.HCLExpression;
import org.netbeans.modules.languages.hcl.ast.HCLIdentifier;
import org.netbeans.modules.languages.hcl.ast.HCLResolveOperation;
import org.netbeans.modules.languages.hcl.ast.HCLVariable;
import org.netbeans.modules.languages.hcl.SourceRef;
+import org.netbeans.modules.languages.hcl.ast.HCLTreeWalker;
import
org.netbeans.modules.languages.hcl.terraform.TerraformParserResult.BlockType;
import static
org.netbeans.modules.languages.hcl.terraform.TerraformParserResult.BlockType.CHECK;
import static
org.netbeans.modules.languages.hcl.terraform.TerraformParserResult.BlockType.DATA;
@@ -61,7 +60,6 @@ public final class TerraformSemanticAnalyzer extends
HCLSemanticAnalyzer {
"string"
);
-
@Override
protected Highlighter createHighlighter(HCLParserResult result) {
return new TerraformHighlighter(result.getReferences());
@@ -75,23 +73,18 @@ public final class TerraformSemanticAnalyzer extends
HCLSemanticAnalyzer {
}
@Override
- protected boolean visitBlock(HCLBlock block) {
- if (block.getParent() instanceof HCLDocument) {
- List<HCLIdentifier> dcl = block.getDeclaration();
+ protected void highlight(HCLTreeWalker.Step step) {
+ super.highlight(step);
+
+ // TODO: Can use record patterns from Java 21
+ if (step.depth() == 1 && step.node() instanceof HCLBlock block) {
+ List<HCLIdentifier> dcl = block.declaration();
if (!dcl.isEmpty()) {
rootBlockType =
TerraformParserResult.BlockType.get(dcl.get(0).id());
}
- }
- return super.visitBlock(block);
- }
-
-
- @Override
- protected boolean visitExpression(HCLExpression expr) {
- if (expr instanceof HCLResolveOperation.Attribute) {
- HCLResolveOperation.Attribute attr =
(HCLResolveOperation.Attribute) expr;
- if ((rootBlockType != null) && (attr.base instanceof
HCLVariable)) {
- String name = ((HCLVariable)attr.base).name.id;
+ } else if (step.node() instanceof HCLResolveOperation.Attribute
attr) {
+ if ((rootBlockType != null) && (attr.base() instanceof
HCLVariable var)) {
+ String name = var.name().id();
switch (rootBlockType) {
case CHECK:
case DATA:
@@ -101,24 +94,18 @@ public final class TerraformSemanticAnalyzer extends
HCLSemanticAnalyzer {
case PROVIDER:
case RESOURCE:
if (RESOLVE_BASES.contains(name)) {
- mark(attr.base, ColoringAttributes.FIELD_SET);
+ mark(attr.base(),
ColoringAttributes.FIELD_SET);
}
break;
}
- return false;
}
- }
-
- if (rootBlockType == BlockType.VARIABLE && (expr instanceof
HCLVariable)) {
- String name = ((HCLVariable) expr).name.id;
+ } else if (rootBlockType == BlockType.VARIABLE && (step.node()
instanceof HCLVariable var)) {
+ String name = var.name().id();
if (LITERAL_TYPES.contains(name)) {
- mark(expr, ColoringAttributes.FIELD_SET);
+ mark(var, ColoringAttributes.FIELD_SET);
}
- return false;
}
- return super.visitExpression(expr);
}
}
-
}
diff --git
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/tfvars/TFVarsParserResult.java
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/tfvars/TFVarsParserResult.java
index 63e5f41d9b..e4768b9466 100644
---
a/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/tfvars/TFVarsParserResult.java
+++
b/ide/languages.hcl/src/org/netbeans/modules/languages/hcl/tfvars/TFVarsParserResult.java
@@ -45,13 +45,13 @@ public class TFVarsParserResult extends HCLParserResult {
"DUPLICATE_VARIABLE=Variable {0} is already defined."
})
protected void processDocument(HCLDocument doc, SourceRef references) {
- for (HCLBlock block : doc.getBlocks()) {
+ for (HCLBlock block : doc.blocks()) {
addError(block, Bundle.INVALID_BLOCK());
}
Set<String> usedAttributes = new HashSet<>();
- for (HCLAttribute attr : doc.getAttributes()) {
+ for (HCLAttribute attr : doc.attributes()) {
if (!usedAttributes.add(attr.id())) {
- addError(attr.getName(), Bundle.DUPLICATE_VARIABLE(attr.id()));
+ addError(attr.name(), Bundle.DUPLICATE_VARIABLE(attr.id()));
}
}
}
diff --git
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/HCLIndenterTest.java
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/HCLIndenterTest.java
index e3e055f544..26667fe46c 100644
---
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/HCLIndenterTest.java
+++
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/HCLIndenterTest.java
@@ -67,32 +67,98 @@ public class HCLIndenterTest extends NbTestCase {
@Test
public void testIndentedNL1() throws Exception {
- performNewLineIndentationTest(" a = 1\n|", " a = 1\n\n ");
+ performNewLineIndentationTest(
+ """
+ a = 1
+ |\
+ """,
+ """
+ a = 1
+
+ \s\
+ """);
}
@Test
public void testIndentedNL2() throws Exception {
- performNewLineIndentationTest(" a = 1\n \n|", " a = 1\n \n\n ");
+ performNewLineIndentationTest(
+ """
+ a = 1
+ \s
+ |\
+ """,
+ """
+ a = 1
+ \s
+
+ \s\s\
+ """
+ );
}
@Test
public void testIndentedBlockNL1() throws Exception {
- performNewLineIndentationTest("locals {|}", "locals {\n}");
+ performNewLineIndentationTest(
+ """
+ locals {|}\
+ """,
+ """
+ locals {
+ }\
+ """
+ );
}
@Test
public void testIndentedBlockNL2() throws Exception {
- performNewLineIndentationTest("locals {\n a = [|]}", "locals {\n a =
[\n]}");
+ performNewLineIndentationTest(
+ """
+ locals {
+ a = [|]}\
+ """,
+ """
+ locals {
+ a = [
+ ]}\
+ """
+ );
}
@Test
public void testIndentedBlockNL3() throws Exception {
- performNewLineIndentationTest("locals {\n a = [|\n ]\n}", "locals
{\n a = [\n \n ]\n}");
+ performNewLineIndentationTest(
+ """
+ locals {
+ a = [|
+ ]
+ }\
+ """,
+ """
+ locals {
+ a = [
+ \s
+ ]
+ }\
+ """
+ );
}
@Test
public void testIndentedBlockNL4() throws Exception {
- performNewLineIndentationTest("locals {\n\n|\n}", "locals {\n\n\n
\n}");
+ performNewLineIndentationTest(
+ """
+ locals {
+
+ |
+ }\
+ """,
+ """
+ locals {
+
+
+ \s
+ }\
+ """);
}
@@ -118,19 +184,78 @@ public class HCLIndenterTest extends NbTestCase {
@Test
public void testEmptyLine() throws Exception {
- performLineIndentationTest("locals {\n |\n}\n", "locals {\n\n}\n");
+ performLineIndentationTest(
+ """
+ locals {
+ |
+ }
+ """,
+ """
+ locals {
+
+ }
+ """
+ );
}
public void testReindent1() throws Exception {
- performSpanIndentationTest("| locals {\n a = 1\n \nb = 2\n}|\n",
"locals {\n a = 1\n\n b = 2\n}\n");
+ performSpanIndentationTest(
+ """
+ | locals {
+ a = 1
+ \s
+ b = 2
+ }|
+ """,
+ """
+ locals {
+ a = 1
+
+ b = 2
+ }
+ """);
}
public void testReindent2() throws Exception {
- performSpanIndentationTest("|a = {\nb = [[\n\"one\"\n],
[\n\"two\"\n]]\n}|\n", "a = {\n b = [[\n \"one\"\n ], [\n
\"two\"\n ]]\n}\n");
+ performSpanIndentationTest(
+ """
+ |a = {
+ b = [[
+ "one"
+ ], [
+ "two"
+ ]]
+ }|
+ """,
+ """
+ a = {
+ b = [[
+ "one"
+ ], [
+ "two"
+ ]]
+ }
+ """
+ );
}
public void testReindentHeredoc() throws Exception {
- performSpanIndentationTest("|a = <<-EOT\n This\n multi\n
line\nEOT|\n", "a = <<-EOT\n This\n multi\n line\nEOT\n");
+ performSpanIndentationTest(
+ """
+ |a = <<-EOT
+ This
+ multi
+ line
+ EOT|
+ """,
+ """
+ a = <<-EOT
+ This
+ multi
+ line
+ EOT
+ """
+ );
}
private void performNewLineIndentationTest(String code, String golden)
throws Exception {
@@ -138,7 +263,7 @@ public class HCLIndenterTest extends NbTestCase {
assertNotSame(-1, pos);
- code = code.replaceAll(Pattern.quote("|"), "");
+ code = code.replace("|", "");
doc.insertString(0, code, null);
Indent indent = Indent.get(doc);
@@ -153,7 +278,7 @@ public class HCLIndenterTest extends NbTestCase {
assertNotSame(-1, pos);
- code = code.replaceAll(Pattern.quote("|"), "");
+ code = code.replace("|", "");
doc.insertString(0, code, null);
Indent indent = Indent.get(doc);
diff --git
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ReferenceTest.java
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ReferenceTest.java
index a5c6d9a752..5d9c319583 100644
---
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ReferenceTest.java
+++
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ReferenceTest.java
@@ -54,7 +54,12 @@ public class ReferenceTest {
@Test
public void testReferences3() throws Exception {
- var at = elementAt("a^{\nb=true\n}");
+ var at = elementAt( """
+ a^{
+ b = true
+ }
+ """
+ );
assertEquals(2, at.size());
var it = at.iterator();
assertTrue(it.next() instanceof HCLBlock);
diff --git
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLLiteralsTest.java
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLLiteralsTest.java
index 2b168cda5a..d25afd1a87 100644
---
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLLiteralsTest.java
+++
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLLiteralsTest.java
@@ -44,7 +44,7 @@ public class HCLLiteralsTest {
HCLExpression exp = parse("3.14");
assertTrue(exp instanceof HCLLiteral.NumericLit);
HCLLiteral.NumericLit num = (HCLLiteral.NumericLit) exp;
- assertEquals("3.14", num.value);
+ assertEquals("3.14", num.value());
}
@Test
@@ -52,7 +52,7 @@ public class HCLLiteralsTest {
HCLExpression exp = parse("\"Hello\"");
assertTrue(exp instanceof HCLLiteral.StringLit);
HCLLiteral.StringLit str = (HCLLiteral.StringLit) exp;
- assertEquals("Hello", str.value);
+ assertEquals("Hello", str.value());
}
@Test
@@ -60,7 +60,7 @@ public class HCLLiteralsTest {
HCLExpression exp = parse("\"\"");
assertTrue(exp instanceof HCLLiteral.StringLit);
HCLLiteral.StringLit str = (HCLLiteral.StringLit) exp;
- assertEquals("", str.value);
+ assertEquals("", str.value());
}
@Test
@@ -68,7 +68,7 @@ public class HCLLiteralsTest {
HCLExpression exp = parse("<<EOT\nEOT");
assertTrue(exp instanceof HCLTemplate.HereDoc);
HCLTemplate.HereDoc heredoc = (HCLTemplate.HereDoc) exp;
- assertTrue(heredoc.parts.isEmpty());
+ assertTrue(heredoc.parts().isEmpty());
}
}
diff --git
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLOperationsTest.java
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLOperationsTest.java
index e4cb2c8bea..95d794667f 100644
---
a/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLOperationsTest.java
+++
b/ide/languages.hcl/test/unit/src/org/netbeans/modules/languages/hcl/ast/HCLOperationsTest.java
@@ -18,12 +18,6 @@
*/
package org.netbeans.modules.languages.hcl.ast;
-import org.netbeans.modules.languages.hcl.ast.HCLResolveOperation;
-import org.netbeans.modules.languages.hcl.ast.HCLArithmeticOperation;
-import org.netbeans.modules.languages.hcl.ast.HCLLiteral;
-import org.netbeans.modules.languages.hcl.ast.HCLVariable;
-import org.netbeans.modules.languages.hcl.ast.HCLExpression;
-import org.netbeans.modules.languages.hcl.ast.HCLConditionalOperation;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -40,9 +34,9 @@ public class HCLOperationsTest {
HCLExpression exp = parse("var.key");
assertTrue(exp instanceof HCLResolveOperation.Attribute);
HCLResolveOperation.Attribute resolve =
(HCLResolveOperation.Attribute) exp;
- assertEquals("key", resolve.attr.id);
- assertTrue(resolve.base instanceof HCLVariable);
- assertEquals("var", ((HCLVariable)resolve.base).name.id);
+ assertEquals("key", resolve.attr().id());
+ assertTrue(resolve.base() instanceof HCLVariable);
+ assertEquals("var", ((HCLVariable)resolve.base()).name().id());
}
@Test
@@ -50,9 +44,9 @@ public class HCLOperationsTest {
HCLExpression exp = parse("a[0]");
assertTrue(exp instanceof HCLResolveOperation.Index);
HCLResolveOperation.Index resolve = (HCLResolveOperation.Index) exp;
- assertEquals("0", ((HCLLiteral.NumericLit)resolve.index).value);
- assertTrue(resolve.base instanceof HCLVariable);
- assertEquals("a", ((HCLVariable)resolve.base).name.id);
+ assertEquals("0", ((HCLLiteral.NumericLit)resolve.index()).value());
+ assertTrue(resolve.base() instanceof HCLVariable);
+ assertEquals("a", ((HCLVariable)resolve.base()).name().id());
}
@Test
@@ -61,11 +55,11 @@ public class HCLOperationsTest {
assertTrue(exp instanceof HCLResolveOperation.Attribute);
HCLResolveOperation.Attribute resolve =
(HCLResolveOperation.Attribute) exp;
- assertTrue(resolve.base instanceof HCLResolveOperation.Index);
- HCLResolveOperation.Index resolve2 = (HCLResolveOperation.Index)
resolve.base;
- assertEquals("1", ((HCLLiteral.NumericLit)resolve2.index).value);
- assertTrue(resolve2.base instanceof HCLVariable);
- assertEquals("a", ((HCLVariable)resolve2.base).name.id);
+ assertTrue(resolve.base() instanceof HCLResolveOperation.Index);
+ HCLResolveOperation.Index resolve2 = (HCLResolveOperation.Index)
resolve.base();
+ assertEquals("1", ((HCLLiteral.NumericLit)resolve2.index()).value());
+ assertTrue(resolve2.base() instanceof HCLVariable);
+ assertEquals("a", ((HCLVariable)resolve2.base()).name().id());
}
@Test
@@ -73,9 +67,9 @@ public class HCLOperationsTest {
HCLExpression exp = parse("a == b ? 1 : var");
assertTrue(exp instanceof HCLConditionalOperation);
HCLConditionalOperation cond = (HCLConditionalOperation) exp;
- assertTrue(cond.condition instanceof HCLArithmeticOperation.Binary);
- assertTrue(cond.trueValue instanceof HCLLiteral.NumericLit);
- assertTrue(cond.falseValue instanceof HCLVariable);
+ assertTrue(cond.condition() instanceof HCLArithmeticOperation.Binary);
+ assertTrue(cond.trueValue() instanceof HCLLiteral.NumericLit);
+ assertTrue(cond.falseValue() instanceof HCLVariable);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists