Skip to content

Commit

Permalink
SONARIAC-1631 Bicep parser should parse array types (#1550)
Browse files Browse the repository at this point in the history
  • Loading branch information
GabinL21 authored Sep 30, 2024
1 parent 4fbb643 commit e634f9b
Show file tree
Hide file tree
Showing 14 changed files with 445 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.sonar.iac.arm.tree.api.Variable;
import org.sonar.iac.arm.tree.api.VariableDeclaration;
import org.sonar.iac.arm.tree.api.bicep.AmbientTypeReference;
import org.sonar.iac.arm.tree.api.bicep.ArrayTypeSuffix;
import org.sonar.iac.arm.tree.api.bicep.CompileTimeImportDeclaration;
import org.sonar.iac.arm.tree.api.bicep.Decorator;
import org.sonar.iac.arm.tree.api.bicep.ForExpression;
Expand All @@ -61,6 +62,7 @@
import org.sonar.iac.arm.tree.api.bicep.TupleType;
import org.sonar.iac.arm.tree.api.bicep.TypeDeclaration;
import org.sonar.iac.arm.tree.api.bicep.TypeExpressionAble;
import org.sonar.iac.arm.tree.api.bicep.TypeReferenceSuffix;
import org.sonar.iac.arm.tree.api.bicep.TypedLambdaExpression;
import org.sonar.iac.arm.tree.api.bicep.UnaryOperator;
import org.sonar.iac.arm.tree.api.bicep.expression.UnaryExpression;
Expand Down Expand Up @@ -427,13 +429,35 @@ public SingularTypeExpression SINGULAR_TYPE_EXPRESSION() {
b.token(Punctuator.QUERY)))));
}

public TypeExpressionAble TYPE_REFERENCE() {
return b.<TypeExpressionAble>nonterminal(BicepLexicalGrammar.TYPE_REFERENCE).is(
f.typeReference(
b.firstOf(
AMBIENT_TYPE_REFERENCE(),
IDENTIFIER()),
b.zeroOrMore(TYPE_REFERENCE_SUFFIX())));
}

public TypeReferenceSuffix TYPE_REFERENCE_SUFFIX() {
return b.<TypeReferenceSuffix>nonterminal(BicepLexicalGrammar.TYPE_REFERENCE_SUFFIX).is(
b.firstOf(
ARRAY_TYPE_SUFFIX()));
}

public ArrayTypeSuffix ARRAY_TYPE_SUFFIX() {
return b.<ArrayTypeSuffix>nonterminal(BicepLexicalGrammar.ARRAY_TYPE_SUFFIX).is(
f.arrayTypeSuffix(
b.token(Punctuator.LBRACKET),
b.optional(NUMERIC_LITERAL()),
b.token(Punctuator.RBRACKET)));
}

public TypeExpressionAble PRIMARY_TYPE_EXPRESSION() {
return b.<TypeExpressionAble>nonterminal(BicepLexicalGrammar.PRIMARY_TYPE_EXPRESSION).is(
b.firstOf(
AMBIENT_TYPE_REFERENCE(),
// The literal value needs to be before identifier
// The literal value needs to be before identifier, which is in type reference
LITERAL_VALUE_AS_TYPE_EXPRESSION_ABLE(),
IDENTIFIER(),
TYPE_REFERENCE(),
UNARY_OPERATOR_LITERAL_VALUE(),
MULTILINE_STRING(),
STRING_LITERAL(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class BicepLexicalConstant {
public static final String NULL = "null";
public static final String SINGLE_QUOTED_STRING_CONTENT = "(?:(?!\\$\\{)(?:\\\\[\\S]|[^']))*+";
public static final String IDENTIFIER_LITERAL = "[a-zA-Z_][a-zA-Z_0-9]*+";
public static final String AMBIENT_TYPE = "(?:array|bool|int|object|string)(?=\\s|\\)|,|\\z)";
public static final String AMBIENT_TYPE = "(?:array|bool|int|object|string)(?=\\s|\\)|,|\\[|\\z)";
public static final String UNARY_OPERATOR = "!|-|\\+";
public static final String MULTILINE_STRING = "(?:(?!''')(?:[\\s\\S])?+)*+";
public static final String EXCLAMATION_SIGN_ALONE = "!(?!=)";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ public enum BicepLexicalGrammar implements GrammarRuleKey {
PARENTHESIZED_TYPE_EXPRESSION,
OBJECT_TYPE,
OBJECT_TYPE_PROPERTY,
TYPE_REFERENCE,
TYPE_REFERENCE_SUFFIX,
AMBIENT_TYPE_REFERENCE,
ARRAY_TYPE_SUFFIX,
IF_CONDITION,
EXPRESSION,
BINARY_EXPRESSION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.sonar.iac.arm.parser.bicep;

import com.sonar.sslr.api.typed.Optional;
import java.util.Collections;
import java.util.List;
import org.sonar.iac.arm.tree.api.ArmTree;
import org.sonar.iac.arm.tree.api.ArrayExpression;
Expand All @@ -40,6 +41,7 @@
import org.sonar.iac.arm.tree.api.Variable;
import org.sonar.iac.arm.tree.api.VariableDeclaration;
import org.sonar.iac.arm.tree.api.bicep.AmbientTypeReference;
import org.sonar.iac.arm.tree.api.bicep.ArrayTypeSuffix;
import org.sonar.iac.arm.tree.api.bicep.CompileTimeImportDeclaration;
import org.sonar.iac.arm.tree.api.bicep.Decorator;
import org.sonar.iac.arm.tree.api.bicep.ForExpression;
Expand All @@ -64,6 +66,7 @@
import org.sonar.iac.arm.tree.api.bicep.TupleType;
import org.sonar.iac.arm.tree.api.bicep.TypeDeclaration;
import org.sonar.iac.arm.tree.api.bicep.TypeExpressionAble;
import org.sonar.iac.arm.tree.api.bicep.TypeReferenceSuffix;
import org.sonar.iac.arm.tree.api.bicep.TypedLambdaExpression;
import org.sonar.iac.arm.tree.api.bicep.UnaryOperator;
import org.sonar.iac.arm.tree.api.bicep.expression.AdditiveExpression;
Expand All @@ -90,6 +93,7 @@
import org.sonar.iac.arm.tree.impl.VariableImpl;
import org.sonar.iac.arm.tree.impl.bicep.AmbientTypeReferenceImpl;
import org.sonar.iac.arm.tree.impl.bicep.ArrayExpressionImpl;
import org.sonar.iac.arm.tree.impl.bicep.ArrayTypeSuffixImpl;
import org.sonar.iac.arm.tree.impl.bicep.BooleanLiteralImpl;
import org.sonar.iac.arm.tree.impl.bicep.CompileTimeImportDeclarationImpl;
import org.sonar.iac.arm.tree.impl.bicep.DecoratorImpl;
Expand Down Expand Up @@ -476,6 +480,18 @@ public AmbientTypeReference ambientTypeReference(SyntaxToken token) {
return new AmbientTypeReferenceImpl(token);
}

public TypeExpressionAble typeReference(TypeExpressionAble type, Optional<List<TypeReferenceSuffix>> optionalSuffixes) {
List<TypeReferenceSuffix> suffixes = optionalSuffixes.or(Collections.emptyList());
for (TypeReferenceSuffix suffix : suffixes) {
type = suffix.applyTo(type);
}
return type;
}

public ArrayTypeSuffix arrayTypeSuffix(SyntaxToken lBracket, Optional<NumericLiteral> length, SyntaxToken rBracket) {
return new ArrayTypeSuffixImpl(lBracket, length.orNull(), rBracket);
}

public UnaryOperator unaryOperator(SyntaxToken token) {
return new UnaryOperatorImpl(token);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import javax.annotation.CheckForNull;
import org.sonar.iac.arm.tree.api.bicep.AmbientTypeReference;
import org.sonar.iac.arm.tree.api.bicep.ArrayTypeReference;
import org.sonar.iac.arm.tree.api.bicep.CompileTimeImportDeclaration;
import org.sonar.iac.arm.tree.api.bicep.Decorator;
import org.sonar.iac.arm.tree.api.bicep.ForExpression;
Expand Down Expand Up @@ -126,6 +127,7 @@ enum Kind implements GrammarRuleKey {
TERNARY_EXPRESSION(TernaryExpression.class),
PARENTHESIZED_EXPRESSION(ParenthesizedExpression.class),
AMBIENT_TYPE_REFERENCE(AmbientTypeReference.class),
ARRAY_TYPE_REFERENCE(ArrayTypeReference.class),
UNARY_OPERATOR(UnaryOperator.class),
TUPLE_TYPE(TupleType.class),
TUPLE_ITEM(TupleItem.class),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SonarQube IaC Plugin
* Copyright (C) 2021-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.iac.arm.tree.api.bicep;

import javax.annotation.CheckForNull;
import org.sonar.iac.arm.tree.api.NumericLiteral;

/**
* Marker interface for array types (e.g. {@code string[]})
*/
public interface ArrayTypeReference extends TypeExpressionAble {
TypeExpressionAble getType();

@CheckForNull
NumericLiteral getLength();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* SonarQube IaC Plugin
* Copyright (C) 2021-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.iac.arm.tree.api.bicep;

/**
* Interface for array type suffix that build into {@link ArrayTypeReference}.
*/
public interface ArrayTypeSuffix extends TypeReferenceSuffix {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* SonarQube IaC Plugin
* Copyright (C) 2021-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.iac.arm.tree.api.bicep;

/**
* Interface for type suffix that get applied to {@link TypeExpressionAble} types.
*/
public interface TypeReferenceSuffix {

/**
* Apply the suffix to another type.
*
* @param baseType the base type to which the suffix will be applied
* @return the base type with the suffix
*/
TypeExpressionAble applyTo(TypeExpressionAble baseType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@ public List<Tree> children() {
public Kind getKind() {
return Kind.AMBIENT_TYPE_REFERENCE;
}

@Override
public String toString() {
return token.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SonarQube IaC Plugin
* Copyright (C) 2021-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.iac.arm.tree.impl.bicep;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.iac.arm.tree.api.NumericLiteral;
import org.sonar.iac.arm.tree.api.bicep.ArrayTypeReference;
import org.sonar.iac.arm.tree.api.bicep.SyntaxToken;
import org.sonar.iac.arm.tree.api.bicep.TypeExpressionAble;
import org.sonar.iac.arm.tree.impl.AbstractArmTreeImpl;
import org.sonar.iac.common.api.tree.Tree;

public class ArrayTypeReferenceImpl extends AbstractArmTreeImpl implements ArrayTypeReference {
private final TypeExpressionAble type;
private final SyntaxToken lBracket;
@CheckForNull
private final NumericLiteral length;
private final SyntaxToken rBracket;

public ArrayTypeReferenceImpl(TypeExpressionAble type, SyntaxToken lBracket, @Nullable NumericLiteral length, SyntaxToken rBracket) {
this.type = type;
this.lBracket = lBracket;
this.length = length;
this.rBracket = rBracket;
}

@Override
public TypeExpressionAble getType() {
return type;
}

@CheckForNull
@Override
public NumericLiteral getLength() {
return length;
}

@Override
public List<Tree> children() {
List<Tree> children = new ArrayList<>(type.children());
children.add(lBracket);
if (length != null) {
children.add(length);
}
children.add(rBracket);
return children;
}

@Override
public Kind getKind() {
return Kind.ARRAY_TYPE_REFERENCE;
}

@Override
public String toString() {
var result = type.toString();
result += lBracket.toString();
if (length != null) {
result += length.toString();
}
result += rBracket.toString();
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* SonarQube IaC Plugin
* Copyright (C) 2021-2024 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.iac.arm.tree.impl.bicep;

import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.iac.arm.tree.api.NumericLiteral;
import org.sonar.iac.arm.tree.api.bicep.ArrayTypeSuffix;
import org.sonar.iac.arm.tree.api.bicep.SyntaxToken;
import org.sonar.iac.arm.tree.api.bicep.TypeExpressionAble;

public class ArrayTypeSuffixImpl implements ArrayTypeSuffix {
private final SyntaxToken lBracket;
@CheckForNull
private final NumericLiteral length;
private final SyntaxToken rBracket;

public ArrayTypeSuffixImpl(SyntaxToken lBracket, @Nullable NumericLiteral length, SyntaxToken rBracket) {
this.lBracket = lBracket;
this.length = length;
this.rBracket = rBracket;
}

@Override
public TypeExpressionAble applyTo(TypeExpressionAble baseType) {
return new ArrayTypeReferenceImpl(baseType, lBracket, length, rBracket);
}
}
Loading

0 comments on commit e634f9b

Please sign in to comment.