Skip to content

Commit

Permalink
SONARIAC-1632 Should not fail on array expressions with trailing comm…
Browse files Browse the repository at this point in the history
…as (#1547)
  • Loading branch information
petertrr committed Sep 19, 2024
1 parent ea2bebd commit b970a2d
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,10 @@ public CompileTimeImportTarget IMPORTED_SYMBOLS_LIST() {
b.token(Punctuator.LCURLYBRACE),
b.zeroOrMore(
f.tuple(
b.optional(b.token(Punctuator.COMMA)),
f.importedSymbolListItem(
IDENTIFIER(),
b.optional(IMPORT_AS_CLAUSE())))),
b.optional(IMPORT_AS_CLAUSE())),
b.optional(b.token(Punctuator.COMMA)))),
b.token(Punctuator.RCURLYBRACE)));
}

Expand Down Expand Up @@ -303,8 +303,8 @@ public ObjectExpression OBJECT_EXPRESSION() {
b.token(Punctuator.LCURLYBRACE),
b.zeroOrMore(
f.tuple(
b.optional(b.token(Punctuator.COMMA)),
OBJECT_PROPERTY())),
OBJECT_PROPERTY(),
b.optional(b.token(Punctuator.COMMA)))),
b.token(Punctuator.RCURLYBRACE)));
}

Expand Down Expand Up @@ -477,8 +477,8 @@ public Expression ARRAY_EXPRESSION() {
b.token(Punctuator.LBRACKET),
b.zeroOrMore(
f.tuple(
b.optional(b.token(Punctuator.COMMA)),
EXPRESSION())),
EXPRESSION(),
b.optional(b.token(Punctuator.COMMA)))),
b.token(Punctuator.RBRACKET)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import com.sonar.sslr.api.typed.Optional;
import java.util.List;
import java.util.stream.Collectors;
import org.sonar.iac.arm.tree.api.ArmTree;
import org.sonar.iac.arm.tree.api.ArrayExpression;
import org.sonar.iac.arm.tree.api.BooleanLiteral;
Expand Down Expand Up @@ -377,11 +376,11 @@ public Property objectProperty(TextTree key, SyntaxToken colon, Expression value
return new PropertyImpl(key, colon, value);
}

public ObjectExpression objectExpression(SyntaxToken leftCurlyBrace, Optional<List<Tuple<Optional<SyntaxToken>, ObjectProperty>>> properties, SyntaxToken rightCurlyBrace) {
public ObjectExpression objectExpression(SyntaxToken leftCurlyBrace, Optional<List<Tuple<ObjectProperty, Optional<SyntaxToken>>>> properties, SyntaxToken rightCurlyBrace) {
return new ObjectExpressionImpl(leftCurlyBrace, toSeparatedList(properties), rightCurlyBrace);
}

public ArrayExpression arrayExpression(SyntaxToken lBracket, Optional<List<Tuple<Optional<SyntaxToken>, Expression>>> elements, SyntaxToken rBracket) {
public ArrayExpression arrayExpression(SyntaxToken lBracket, Optional<List<Tuple<Expression, Optional<SyntaxToken>>>> elements, SyntaxToken rBracket) {
return new ArrayExpressionImpl(lBracket, toSeparatedList(elements), rBracket);
}

Expand Down Expand Up @@ -424,7 +423,7 @@ public CompileTimeImportDeclaration compileTimeImportDeclaration(

public CompileTimeImportTarget importedSymbolsList(
SyntaxToken openCurly,
Optional<List<Tuple<Optional<SyntaxToken>, ImportedSymbolsListItem>>> importedSymbols,
Optional<List<Tuple<ImportedSymbolsListItem, Optional<SyntaxToken>>>> importedSymbols,
SyntaxToken closingCurly) {
return new ImportedSymbolsList(openCurly, toSeparatedList(importedSymbols), closingCurly);
}
Expand Down Expand Up @@ -568,16 +567,12 @@ public TernaryExpression ternaryExpression(Expression condition, SyntaxToken que
return new TernaryExpressionImpl(condition, query, ifTrueExpression, colon, elseExpression);
}

private static <T extends ArmTree> SeparatedList<T, SyntaxToken> toSeparatedList(Optional<List<Tuple<Optional<SyntaxToken>, T>>> elements) {
SeparatedList<T, SyntaxToken> result = emptySeparatedList();
if (elements.isPresent()) {
// replace Optional<SyntaxToken> by SyntaxToken or null
List<Tuple<SyntaxToken, T>> elementsWithNullSeparators = elements.get().stream()
.map(tuple -> new Tuple<>(tuple.first().orNull(), tuple.second()))
.collect(Collectors.toList());
var firstElement = elementsWithNullSeparators.remove(0).second();
result = separatedList(firstElement, elementsWithNullSeparators);
private static <T extends ArmTree> SeparatedList<T, SyntaxToken> toSeparatedList(Optional<List<Tuple<T, Optional<SyntaxToken>>>> elementsWithSeparators) {
if (elementsWithSeparators.isPresent()) {
var elements = elementsWithSeparators.get().stream().map(Tuple::first).toList();
var separators = elementsWithSeparators.get().stream().map(tuple -> tuple.second().orNull()).toList();
return new SeparatedListImpl<>(elements, separators);
}
return result;
return emptySeparatedList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void shouldParseMultilineArrays() {
'a'
]""")
.matches("['a', 'b']")
.matches("['a', 'b',]")
.matches("""
[
'a', 'b'
Expand Down Expand Up @@ -74,6 +75,7 @@ void shouldParseMultilineArrays() {
[
'a']""")

.notMatches("[,'a', 'b']")
.notMatches("""
[
}""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void shouldParseValidStatement() {
.matches("import { foo } from 'imports.bicep'")
.matches("import {foo,bar} from 'imports.bicep'")
.matches("import {foo, bar} from 'imports.bicep'")
.matches("import {foo, bar,} from 'imports.bicep'")
.matches("""
import {
foo as fizz
Expand All @@ -43,6 +44,7 @@ void shouldParseValidStatement() {

.notMatches("import *")
.notMatches("import {foo, *} from 'imports.bicep'")
.notMatches("import {,foo} from 'imports.bicep'")
.notMatches("import foo from 'imports.bicep'");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.sonar.iac.arm.tree.impl.bicep;

import org.junit.jupiter.api.Test;
import org.sonar.iac.arm.ArmAssertions;
import org.sonar.iac.arm.parser.bicep.BicepLexicalGrammar;
import org.sonar.iac.arm.tree.api.ArmTree;
import org.sonar.iac.arm.tree.api.HasIdentifier;
Expand All @@ -36,6 +37,32 @@

class ObjectExpressionImplTest extends BicepTreeModelTest {

@Test
void shouldParseValidObjectExpressions() {
ArmAssertions.assertThat(BicepLexicalGrammar.OBJECT_EXPRESSION)
.matches("{}")
.matches("{ key1: value1 }")
.matches("{ key1: value1, key2: value2 }")
.matches("{ key1: value1, key2: value2, }")
.matches("""
{
key1: value1
key2: value2
}""")
.matches("""
{
key1: value1, key2: value2
key3: value3
}""")
.matches("""
{
key1: value1,
key2: value2
}""")

.notMatches("{ , key1: value1 }");
}

@Test
void shouldParseMinimumObjectExpression() {
String code = "{}\n";
Expand Down

0 comments on commit b970a2d

Please sign in to comment.