diff --git a/sonar-plugin/api/src/main/java/org/sonar/plugins/javascript/api/estree/ESTree.java b/sonar-plugin/api/src/main/java/org/sonar/plugins/javascript/api/estree/ESTree.java index 2834ac1e13e..ae8bc05fa1a 100644 --- a/sonar-plugin/api/src/main/java/org/sonar/plugins/javascript/api/estree/ESTree.java +++ b/sonar-plugin/api/src/main/java/org/sonar/plugins/javascript/api/estree/ESTree.java @@ -57,7 +57,7 @@ public sealed interface Declaration extends Statement { public sealed interface Expression extends ExpressionOrSpreadElement, ExpressionOrSuper, ExpressionOrPrivateIdentifier, ExpressionOrPattern, ExpressionOrVariableDeclaration, ExpressionOrClassDeclarationOrFunctionDeclaration, BlockStatementOrExpression { } - public sealed interface Literal extends Expression { + public sealed interface Literal extends Expression, IdentifierOrLiteral { String raw(); } public sealed interface ModuleDeclaration extends DirectiveOrModuleDeclarationOrStatement { @@ -84,6 +84,7 @@ public sealed interface PropertyOrSpreadElement extends Node {} public sealed interface PropertyOrRestElement extends Node {} public sealed interface DirectiveOrModuleDeclarationOrStatement extends Node {} public sealed interface ExpressionOrPattern extends Node {} + public sealed interface IdentifierOrLiteral extends Node {} public record ArrayExpression(Location loc, List elements) implements Expression {} public record ArrayPattern(Location loc, List elements) implements Pattern {} @@ -107,7 +108,7 @@ public record DebuggerStatement(Location loc) implements Statement {} public record Directive(Location loc, Literal expression, String directive) implements DirectiveOrModuleDeclarationOrStatement {} public record DoWhileStatement(Location loc, Statement body, Expression test) implements Statement {} public record EmptyStatement(Location loc) implements Statement {} - public record ExportAllDeclaration(Location loc, Optional exported, Literal source) implements ModuleDeclaration {} + public record ExportAllDeclaration(Location loc, Optional exported, Literal source) implements ModuleDeclaration {} // In "d.ts" file, the declaration field has type: MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | Expression. // The "MaybeNamed" are there to show that the id is optional in this specific case. // We decided to not create this extra class, and instead use the existing FunctionDeclaration and ClassDeclaration classes. @@ -122,7 +123,7 @@ public record ForStatement(Location loc, Optional id, BlockStatement body, List params, boolean generator, boolean async) implements Declaration, ExpressionOrClassDeclarationOrFunctionDeclaration {} public record FunctionExpression(Location loc, Optional id, BlockStatement body, List params, boolean generator, boolean async) implements Expression {} - public record Identifier(Location loc, String name) implements Expression, Pattern {} + public record Identifier(Location loc, String name) implements Expression, Pattern, IdentifierOrLiteral {} public record IfStatement(Location loc, Expression test, Statement consequent, Optional alternate) implements Statement {} public record ImportDeclaration(Location loc, List specifiers, Literal source) implements ModuleDeclaration {} public record ImportDefaultSpecifier(Location loc, Identifier local) implements ImportDefaultSpecifierOrImportNamespaceSpecifierOrImportSpecifier {} diff --git a/sonar-plugin/api/src/test/java/org/sonar/plugins/javascript/api/estree/ESTreeTest.java b/sonar-plugin/api/src/test/java/org/sonar/plugins/javascript/api/estree/ESTreeTest.java index fe89eacf35f..f429a756de5 100644 --- a/sonar-plugin/api/src/test/java/org/sonar/plugins/javascript/api/estree/ESTreeTest.java +++ b/sonar-plugin/api/src/test/java/org/sonar/plugins/javascript/api/estree/ESTreeTest.java @@ -11,11 +11,11 @@ class ESTreeTest { void test() { Class[] classes = ESTree.class.getDeclaredClasses(); - assertThat(classes).hasSize(105); + assertThat(classes).hasSize(106); //filter all classes that are interface var ifaceCount = Arrays.stream(classes).filter(Class::isInterface).count(); - assertThat(ifaceCount).isEqualTo(24); + assertThat(ifaceCount).isEqualTo(25); var recordCount = Arrays.stream(classes).filter(Class::isRecord).count(); assertThat(recordCount).isEqualTo(76); @@ -25,7 +25,7 @@ void test() { void test_node_subclasses() { Class sealedClass = ESTree.Node.class; Class[] permittedSubclasses = sealedClass.getPermittedSubclasses(); - assertThat(permittedSubclasses).hasSize(22); + assertThat(permittedSubclasses).hasSize(23); } @Test diff --git a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/ESTreeFactory.java b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/ESTreeFactory.java index 1974f23bb97..7616bbac66d 100644 --- a/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/ESTreeFactory.java +++ b/sonar-plugin/bridge/src/main/java/org/sonar/plugins/javascript/bridge/ESTreeFactory.java @@ -207,7 +207,9 @@ private static ESTree.Program fromProgramType(Node node) { private static ESTree.ExportAllDeclaration fromExportAllDeclarationType(Node node) { ExportAllDeclaration exportAllDeclaration = node.getExportAllDeclaration(); return new ESTree.ExportAllDeclaration(fromLocation(node.getLoc()), - exportAllDeclaration.hasExported() ? Optional.of(from(exportAllDeclaration.getExported(), ESTree.Identifier.class)) : Optional.empty(), + exportAllDeclaration.hasExported() ? + Optional.of(from(exportAllDeclaration.getExported(), ESTree.IdentifierOrLiteral.class)) : + Optional.empty(), from(exportAllDeclaration.getSource(), ESTree.Literal.class)); } diff --git a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/ESTreeFactoryTest.java b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/ESTreeFactoryTest.java index 68385ca5793..b3db8406427 100644 --- a/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/ESTreeFactoryTest.java +++ b/sonar-plugin/bridge/src/test/java/org/sonar/plugins/javascript/bridge/ESTreeFactoryTest.java @@ -34,6 +34,7 @@ import org.sonar.plugins.javascript.bridge.protobuf.ChainExpression; import org.sonar.plugins.javascript.bridge.protobuf.ClassDeclaration; import org.sonar.plugins.javascript.bridge.protobuf.EmptyStatement; +import org.sonar.plugins.javascript.bridge.protobuf.ExportAllDeclaration; import org.sonar.plugins.javascript.bridge.protobuf.ExportDefaultDeclaration; import org.sonar.plugins.javascript.bridge.protobuf.ExportSpecifier; import org.sonar.plugins.javascript.bridge.protobuf.ExpressionStatement; @@ -580,6 +581,41 @@ void should_create_static_block_type() { }); } + @Test + void should_create_export_all_declaration_type_using_a_literal() { + ExportAllDeclaration exportAllDeclaration = ExportAllDeclaration.newBuilder() + .setExported( + Node.newBuilder() + .setType(NodeType.LiteralType) + .setLiteral( + Literal.newBuilder() + .setValueString("4k") + ) + .build() + ) + .setSource( + Node.newBuilder() + .setType(NodeType.LiteralType) + .setLiteral( + Literal.newBuilder() + .setValueString("yolo") + ) + ) + .build(); + + Node protobufNode = Node.newBuilder() + .setType(NodeType.ExportAllDeclarationType) + .setExportAllDeclaration(exportAllDeclaration) + .build(); + + ESTree.Node estree = ESTreeFactory.from(protobufNode, ESTree.Node.class); + assertThat(estree).isInstanceOfSatisfying(ESTree.ExportAllDeclaration.class, declaration -> { + assertThat(declaration.exported().isPresent()).isTrue(); + var exported = declaration.exported().get(); + assertThat(exported).isInstanceOf(ESTree.Literal.class); + }); + } + @Test void throw_exception_from_unrecognized_type() { Node protobufNode = Node.newBuilder()