From c219aca5e4072de42d12fa108dc955a387452d21 Mon Sep 17 00:00:00 2001 From: Victor Diez Date: Wed, 28 Aug 2024 13:33:35 +0200 Subject: [PATCH 1/8] JS-280 Support unknown nodes in AST protobuf file --- packages/jsts/src/parsers/ast.ts | 4 +-- packages/jsts/src/parsers/estree.proto | 6 +++++ packages/jsts/tests/parsers/ast.test.ts | 10 +++++++ .../tests/parsers/fixtures/ast/unknownNode.ts | 3 +++ .../plugins/javascript/api/estree/ESTree.java | 1 + .../javascript/bridge/ESTreeFactory.java | 5 ++++ .../bridge/src/main/protobuf/estree.proto | 6 +++++ .../javascript/bridge/ESTreeFactoryTest.java | 25 +++++++++++++++--- .../src/test/resources/files/unknown.proto | Bin 0 -> 244 bytes tools/estree/output/estree.proto | 6 +++++ 10 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 packages/jsts/tests/parsers/fixtures/ast/unknownNode.ts create mode 100644 sonar-plugin/bridge/src/test/resources/files/unknown.proto diff --git a/packages/jsts/src/parsers/ast.ts b/packages/jsts/src/parsers/ast.ts index 2a654236bf..6a95150b56 100644 --- a/packages/jsts/src/parsers/ast.ts +++ b/packages/jsts/src/parsers/ast.ts @@ -26,7 +26,7 @@ import { debug } from '@sonar/shared'; const PATH_TO_PROTOFILE = path.join(__dirname, 'estree.proto'); const PROTO_ROOT = protobuf.loadSync(PATH_TO_PROTOFILE); const NODE_TYPE = PROTO_ROOT.lookupType('Node'); -const NODE_TYPE_ENUM = PROTO_ROOT.lookupEnum('NodeType'); +export const NODE_TYPE_ENUM = PROTO_ROOT.lookupEnum('NodeType'); export function serializeInProtobuf(ast: AST.Program): Uint8Array { const protobufAST = parseInProtobuf(ast); @@ -57,7 +57,7 @@ export function visitNode(node: estree.BaseNodeWithoutComments | undefined | nul } return { - type: NODE_TYPE_ENUM.values[node.type + 'Type'], + type: NODE_TYPE_ENUM.values[node.type + 'Type'] ?? NODE_TYPE_ENUM.values['UnknownType'], loc: node.loc, [lowerCaseFirstLetter(node.type)]: getProtobufShapeForNode(node), }; diff --git a/packages/jsts/src/parsers/estree.proto b/packages/jsts/src/parsers/estree.proto index cdd4ee777f..3d035a7b4a 100644 --- a/packages/jsts/src/parsers/estree.proto +++ b/packages/jsts/src/parsers/estree.proto @@ -87,6 +87,7 @@ enum NodeType { LiteralType = 68; TemplateElementType = 69; FunctionExpressionType = 70; + UnknownType = 1000; } message Node { NodeType type = 1; @@ -163,6 +164,7 @@ message Node { Literal literal = 71; TemplateElement templateElement = 72; FunctionExpression functionExpression = 73; + UnknownNode unknownNode = 1000; } } message Program { @@ -467,3 +469,7 @@ message FunctionExpression { optional bool generator = 4; optional bool async = 5; } + +message UnknownNode { + +} diff --git a/packages/jsts/tests/parsers/ast.test.ts b/packages/jsts/tests/parsers/ast.test.ts index fbdc0cef6b..fd279bcae6 100644 --- a/packages/jsts/tests/parsers/ast.test.ts +++ b/packages/jsts/tests/parsers/ast.test.ts @@ -27,6 +27,7 @@ import { deserializeProtobuf, parseInProtobuf, serializeInProtobuf, + NODE_TYPE_ENUM, } from '../../src/parsers'; import { JsTsAnalysisInput } from '../../src/analysis'; @@ -62,6 +63,15 @@ describe('ast', () => { }, ); }); + test('should encode unknown nodes', async () => { + const filePath = path.join(__dirname, 'fixtures', 'ast', 'unknownNode.ts'); + const sc = await parseSourceCode(filePath, parsers.typescript); + const protoMessage = parseInProtobuf(sc.ast); + expect( + (protoMessage as any).program.body[0].ifStatement.test.type === + NODE_TYPE_ENUM.values['UnknownType'], + ); + }); }); /** diff --git a/packages/jsts/tests/parsers/fixtures/ast/unknownNode.ts b/packages/jsts/tests/parsers/fixtures/ast/unknownNode.ts new file mode 100644 index 0000000000..a8eaada343 --- /dev/null +++ b/packages/jsts/tests/parsers/fixtures/ast/unknownNode.ts @@ -0,0 +1,3 @@ +if ("ts" as Object) { + console.log(""); +} 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 21faf35947..d58e38255a 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 @@ -168,6 +168,7 @@ public record VariableDeclarator(Location loc, Pattern id, Optional public record WhileStatement(Location loc, Expression test, Statement body) implements Statement {} public record WithStatement(Location loc, Expression object, Statement body) implements Statement {} public record YieldExpression(Location loc, Optional argument, boolean delegate) implements Expression {} + public record UnknownNode(Location loc) implements Expression {} public interface Operator { String raw(); 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 dfa7e43e24..2f2dbc568a 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 @@ -179,6 +179,7 @@ public static T from(Node node, Class clazz) { case LiteralType -> fromLiteralType(node); case TemplateElementType -> fromTemplateElementType(node); case FunctionExpressionType -> fromFunctionExpressionType(node); + case UnknownType -> fromUnknownType(node); case UNRECOGNIZED -> throw new IllegalArgumentException("Unknown node type: " + node.getType() + " at " + node.getLoc()); }; @@ -724,4 +725,8 @@ private static ESTree.FunctionExpression fromFunctionExpressionType(Node node) { functionExpression.getAsync()); } + private static ESTree.UnknownNode fromUnknownType(Node node) { + return new ESTree.UnknownNode(fromLocation(node.getLoc())); + } + } diff --git a/sonar-plugin/bridge/src/main/protobuf/estree.proto b/sonar-plugin/bridge/src/main/protobuf/estree.proto index cdd4ee777f..3d035a7b4a 100644 --- a/sonar-plugin/bridge/src/main/protobuf/estree.proto +++ b/sonar-plugin/bridge/src/main/protobuf/estree.proto @@ -87,6 +87,7 @@ enum NodeType { LiteralType = 68; TemplateElementType = 69; FunctionExpressionType = 70; + UnknownType = 1000; } message Node { NodeType type = 1; @@ -163,6 +164,7 @@ message Node { Literal literal = 71; TemplateElement templateElement = 72; FunctionExpression functionExpression = 73; + UnknownNode unknownNode = 1000; } } message Program { @@ -467,3 +469,7 @@ message FunctionExpression { optional bool generator = 4; optional bool async = 5; } + +message UnknownNode { + +} 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 d483651218..eecef6fefb 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 @@ -19,6 +19,9 @@ */ package org.sonar.plugins.javascript.bridge; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -57,11 +60,27 @@ import org.sonar.plugins.javascript.bridge.protobuf.UpdateExpression; import org.sonar.plugins.javascript.bridge.protobuf.WithStatement; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - class ESTreeFactoryTest { + @Test + void should_not_fail_with_unknown_nodes() throws IOException { + // the clear version of serialized.proto is `packages/jsts/tests/parsers/fixtures/ast/JS-285-reproducer.ts`, + // it was generated by writing to a file the serialized data in the test `packages/jsts/tests/parsers/ast.test.ts` + File file = Path.of("src", "test", "resources", "files", "unknown.proto").toFile(); + + Node node; + try (FileInputStream fis = new FileInputStream(file)) { + node = Node.parseFrom(fis); + } + ESTree.Node root = ESTreeFactory.from(node, ESTree.Node.class); + assertThat(root).isInstanceOf(ESTree.Program.class); + ESTree.Program program = (ESTree.Program) root; + assertThat(program.body()).hasSize(1); + assertThat(program.body().get(0)).isInstanceOfSatisfying(ESTree.IfStatement.class, ifStatement -> { + assertThat(ifStatement.test()).isInstanceOf(ESTree.UnknownNode.class); + }); + } + @Test void should_create_nodes_from_serialized_data() throws IOException { // the clear version of serialized.proto is `packages/jsts/tests/parsers/fixtures/ast/base.js`, diff --git a/sonar-plugin/bridge/src/test/resources/files/unknown.proto b/sonar-plugin/bridge/src/test/resources/files/unknown.proto new file mode 100644 index 0000000000000000000000000000000000000000..7f6fff313449f0fcabec3d494befb490b6b0a6d2 GIT binary patch literal 244 zcmd;J5aJPH;b0VCkYeFr0g?|Hx!7{^Q%ZAEg|0DjSR=_Y3ow3SKE%i+$nk<5D$D}Z z#3&#nw1$yG5-KDD6auPz#5jYIYbqm$Ggz2O0Hl&hKx7k3BO_Nmha!ro@FJ!h4hA7# z4lxvA{!@%rT+$p&D1zKtoLub5`FX|pKnIG$C3(Qc^J}qkG3Vr`OE4%fNJ(t<8 literal 0 HcmV?d00001 diff --git a/tools/estree/output/estree.proto b/tools/estree/output/estree.proto index cdd4ee777f..3d035a7b4a 100644 --- a/tools/estree/output/estree.proto +++ b/tools/estree/output/estree.proto @@ -87,6 +87,7 @@ enum NodeType { LiteralType = 68; TemplateElementType = 69; FunctionExpressionType = 70; + UnknownType = 1000; } message Node { NodeType type = 1; @@ -163,6 +164,7 @@ message Node { Literal literal = 71; TemplateElement templateElement = 72; FunctionExpression functionExpression = 73; + UnknownNode unknownNode = 1000; } } message Program { @@ -467,3 +469,7 @@ message FunctionExpression { optional bool generator = 4; optional bool async = 5; } + +message UnknownNode { + +} From 2fd16144077f88a165a2a6fd38694e558c437149 Mon Sep 17 00:00:00 2001 From: Victor Diez Date: Wed, 28 Aug 2024 13:34:34 +0200 Subject: [PATCH 2/8] fix surefire error --- its/plugin/sonarlint-tests/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/its/plugin/sonarlint-tests/pom.xml b/its/plugin/sonarlint-tests/pom.xml index 726a9c1f77..c90be42e0f 100644 --- a/its/plugin/sonarlint-tests/pom.xml +++ b/its/plugin/sonarlint-tests/pom.xml @@ -10,6 +10,7 @@ javascript-it-plugin-sonarlint-tests JavaScript :: IT :: Plugin :: SonarLint Tests + pom -server From e84b7e39ea58c0ce4f13cee3c2a1fb5e596720fc Mon Sep 17 00:00:00 2001 From: Victor Diez Date: Wed, 28 Aug 2024 14:24:35 +0200 Subject: [PATCH 3/8] fix estree test --- .../plugins/javascript/api/estree/ESTreeTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 10d1ed05e9..6d1f2d359d 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 @@ -1,24 +1,24 @@ package org.sonar.plugins.javascript.api.estree; +import static org.assertj.core.api.Assertions.assertThat; + import java.util.Arrays; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - class ESTreeTest { @Test void test() { Class[] classes = ESTree.class.getDeclaredClasses(); - assertThat(classes).hasSize(106); + assertThat(classes).hasSize(107); //filter all classes that are interface var ifaceCount = Arrays.stream(classes).filter(Class::isInterface).count(); assertThat(ifaceCount).isEqualTo(25); var recordCount = Arrays.stream(classes).filter(Class::isRecord).count(); - assertThat(recordCount).isEqualTo(76); + assertThat(recordCount).isEqualTo(77); } @Test @@ -32,7 +32,7 @@ void test_node_subclasses() { void test_expression_subclasses() { Class sealedClass = ESTree.Expression.class; Class[] permittedSubclasses = sealedClass.getPermittedSubclasses(); - assertThat(permittedSubclasses).hasSize(24); + assertThat(permittedSubclasses).hasSize(25); } @Test From 687ebf0037985907ac2de84db45d271070754b55 Mon Sep 17 00:00:00 2001 From: Victor Diez Date: Wed, 28 Aug 2024 17:05:49 +0200 Subject: [PATCH 4/8] Add original TS type to protobuf file --- packages/jsts/src/parsers/ast.ts | 27 ++++++++++++++---- packages/jsts/src/parsers/estree.proto | 4 +-- packages/jsts/tests/parsers/ast.test.ts | 9 ++++-- .../plugins/javascript/api/estree/ESTree.java | 2 +- .../javascript/bridge/ESTreeFactory.java | 8 ++++-- .../bridge/src/main/protobuf/estree.proto | 4 +-- .../javascript/bridge/ESTreeFactoryTest.java | 3 ++ .../src/test/resources/files/unknown.proto | Bin 244 -> 263 bytes tools/estree/output/estree.proto | 4 +-- 9 files changed, 43 insertions(+), 18 deletions(-) diff --git a/packages/jsts/src/parsers/ast.ts b/packages/jsts/src/parsers/ast.ts index 6a95150b56..480c8ed87b 100644 --- a/packages/jsts/src/parsers/ast.ts +++ b/packages/jsts/src/parsers/ast.ts @@ -56,11 +56,21 @@ export function visitNode(node: estree.BaseNodeWithoutComments | undefined | nul return undefined; } - return { - type: NODE_TYPE_ENUM.values[node.type + 'Type'] ?? NODE_TYPE_ENUM.values['UnknownType'], - loc: node.loc, - [lowerCaseFirstLetter(node.type)]: getProtobufShapeForNode(node), - }; + const protoType = NODE_TYPE_ENUM.values[node.type + 'Type']; + + if (typeof protoType !== 'undefined') { + return { + type: protoType, + loc: node.loc, + [lowerCaseFirstLetter(node.type)]: getProtobufShapeForNode(node), + }; + } else { + return { + type: NODE_TYPE_ENUM.values['UnknownNodeType'], + loc: node.loc, + unknownNode: getProtobufShapeForNode(node), + }; + } function lowerCaseFirstLetter(str: string) { return str.charAt(0).toLowerCase() + str.slice(1); @@ -216,6 +226,7 @@ export function visitNode(node: estree.BaseNodeWithoutComments | undefined | nul return visitFunctionExpression(node as estree.FunctionExpression); default: debug(`Unknown node type: ${node.type}`); + return visitUnknownNode(node); } } @@ -763,4 +774,10 @@ export function visitNode(node: estree.BaseNodeWithoutComments | undefined | nul async: node.async, }; } + + function visitUnknownNode(node: estree.BaseNodeWithoutComments) { + return { + astNodeType: node.type, + }; + } } diff --git a/packages/jsts/src/parsers/estree.proto b/packages/jsts/src/parsers/estree.proto index 3d035a7b4a..275f507591 100644 --- a/packages/jsts/src/parsers/estree.proto +++ b/packages/jsts/src/parsers/estree.proto @@ -87,7 +87,7 @@ enum NodeType { LiteralType = 68; TemplateElementType = 69; FunctionExpressionType = 70; - UnknownType = 1000; + UnknownNodeType = 1000; } message Node { NodeType type = 1; @@ -471,5 +471,5 @@ message FunctionExpression { } message UnknownNode { - + string astNodeType = 1; } diff --git a/packages/jsts/tests/parsers/ast.test.ts b/packages/jsts/tests/parsers/ast.test.ts index fd279bcae6..29f7a6489c 100644 --- a/packages/jsts/tests/parsers/ast.test.ts +++ b/packages/jsts/tests/parsers/ast.test.ts @@ -30,6 +30,7 @@ import { NODE_TYPE_ENUM, } from '../../src/parsers'; import { JsTsAnalysisInput } from '../../src/analysis'; +import fs from 'fs'; const parseFunctions = [ { @@ -67,9 +68,11 @@ describe('ast', () => { const filePath = path.join(__dirname, 'fixtures', 'ast', 'unknownNode.ts'); const sc = await parseSourceCode(filePath, parsers.typescript); const protoMessage = parseInProtobuf(sc.ast); - expect( - (protoMessage as any).program.body[0].ifStatement.test.type === - NODE_TYPE_ENUM.values['UnknownType'], + fs.writeFileSync('JS-285-reproducer-ts-proto.json', JSON.stringify(protoMessage, null, 2)); + const serialized = serializeInProtobuf(sc.ast); + fs.writeFileSync('JS-285-reproducer-ts.proto', serialized); + expect((protoMessage as any).program.body[0].ifStatement.test.type).toEqual( + NODE_TYPE_ENUM.values['UnknownNodeType'], ); }); }); 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 d58e38255a..ec638d34ea 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 @@ -168,7 +168,7 @@ public record VariableDeclarator(Location loc, Pattern id, Optional public record WhileStatement(Location loc, Expression test, Statement body) implements Statement {} public record WithStatement(Location loc, Expression object, Statement body) implements Statement {} public record YieldExpression(Location loc, Optional argument, boolean delegate) implements Expression {} - public record UnknownNode(Location loc) implements Expression {} + public record UnknownNode(Location loc, String astNodeType) implements Expression {} public interface Operator { String raw(); 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 2f2dbc568a..2df0f0971e 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 @@ -87,6 +87,7 @@ import org.sonar.plugins.javascript.bridge.protobuf.ThrowStatement; import org.sonar.plugins.javascript.bridge.protobuf.TryStatement; import org.sonar.plugins.javascript.bridge.protobuf.UnaryExpression; +import org.sonar.plugins.javascript.bridge.protobuf.UnknownNode; import org.sonar.plugins.javascript.bridge.protobuf.UpdateExpression; import org.sonar.plugins.javascript.bridge.protobuf.VariableDeclaration; import org.sonar.plugins.javascript.bridge.protobuf.VariableDeclarator; @@ -179,7 +180,7 @@ public static T from(Node node, Class clazz) { case LiteralType -> fromLiteralType(node); case TemplateElementType -> fromTemplateElementType(node); case FunctionExpressionType -> fromFunctionExpressionType(node); - case UnknownType -> fromUnknownType(node); + case UnknownNodeType -> fromUnknownNodeType(node); case UNRECOGNIZED -> throw new IllegalArgumentException("Unknown node type: " + node.getType() + " at " + node.getLoc()); }; @@ -725,8 +726,9 @@ private static ESTree.FunctionExpression fromFunctionExpressionType(Node node) { functionExpression.getAsync()); } - private static ESTree.UnknownNode fromUnknownType(Node node) { - return new ESTree.UnknownNode(fromLocation(node.getLoc())); + private static ESTree.UnknownNode fromUnknownNodeType(Node node) { + UnknownNode unknownNode = node.getUnknownNode(); + return new ESTree.UnknownNode(fromLocation(node.getLoc()), unknownNode.getAstNodeType()); } } diff --git a/sonar-plugin/bridge/src/main/protobuf/estree.proto b/sonar-plugin/bridge/src/main/protobuf/estree.proto index 3d035a7b4a..275f507591 100644 --- a/sonar-plugin/bridge/src/main/protobuf/estree.proto +++ b/sonar-plugin/bridge/src/main/protobuf/estree.proto @@ -87,7 +87,7 @@ enum NodeType { LiteralType = 68; TemplateElementType = 69; FunctionExpressionType = 70; - UnknownType = 1000; + UnknownNodeType = 1000; } message Node { NodeType type = 1; @@ -471,5 +471,5 @@ message FunctionExpression { } message UnknownNode { - + string astNodeType = 1; } 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 eecef6fefb..a9aa762dad 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 @@ -78,6 +78,9 @@ void should_not_fail_with_unknown_nodes() throws IOException { assertThat(program.body()).hasSize(1); assertThat(program.body().get(0)).isInstanceOfSatisfying(ESTree.IfStatement.class, ifStatement -> { assertThat(ifStatement.test()).isInstanceOf(ESTree.UnknownNode.class); + ESTree.UnknownNode unknownNode = (ESTree.UnknownNode)ifStatement.test(); + assertThat(unknownNode.astNodeType()).isEqualTo("TSAsExpression"); + }); } diff --git a/sonar-plugin/bridge/src/test/resources/files/unknown.proto b/sonar-plugin/bridge/src/test/resources/files/unknown.proto index 7f6fff313449f0fcabec3d494befb490b6b0a6d2..f0eb1745c3ca976a8c2a0ee8beae7242faaf791e 100644 GIT binary patch delta 96 zcmeyu*v=He!63vV#KOTSz#zrK!2%?|Fmkcw=BJeAqzb)c7GIFuy=BJeAqzYYQ Date: Wed, 28 Aug 2024 18:54:20 +0200 Subject: [PATCH 5/8] changes after review --- packages/jsts/src/parsers/ast.ts | 2 +- packages/jsts/src/parsers/estree.proto | 2 +- packages/jsts/tests/parsers/ast.test.ts | 4 ---- .../java/org/sonar/plugins/javascript/api/estree/ESTree.java | 2 +- .../org/sonar/plugins/javascript/bridge/ESTreeFactory.java | 2 +- sonar-plugin/bridge/src/main/protobuf/estree.proto | 2 +- .../sonar/plugins/javascript/bridge/ESTreeFactoryTest.java | 4 ++-- tools/estree/output/estree.proto | 2 +- 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/jsts/src/parsers/ast.ts b/packages/jsts/src/parsers/ast.ts index 480c8ed87b..90166b296f 100644 --- a/packages/jsts/src/parsers/ast.ts +++ b/packages/jsts/src/parsers/ast.ts @@ -777,7 +777,7 @@ export function visitNode(node: estree.BaseNodeWithoutComments | undefined | nul function visitUnknownNode(node: estree.BaseNodeWithoutComments) { return { - astNodeType: node.type, + rawType: node.type, }; } } diff --git a/packages/jsts/src/parsers/estree.proto b/packages/jsts/src/parsers/estree.proto index 275f507591..6a1e198f99 100644 --- a/packages/jsts/src/parsers/estree.proto +++ b/packages/jsts/src/parsers/estree.proto @@ -471,5 +471,5 @@ message FunctionExpression { } message UnknownNode { - string astNodeType = 1; + string rawType = 1; } diff --git a/packages/jsts/tests/parsers/ast.test.ts b/packages/jsts/tests/parsers/ast.test.ts index 29f7a6489c..92eeba6347 100644 --- a/packages/jsts/tests/parsers/ast.test.ts +++ b/packages/jsts/tests/parsers/ast.test.ts @@ -30,7 +30,6 @@ import { NODE_TYPE_ENUM, } from '../../src/parsers'; import { JsTsAnalysisInput } from '../../src/analysis'; -import fs from 'fs'; const parseFunctions = [ { @@ -68,9 +67,6 @@ describe('ast', () => { const filePath = path.join(__dirname, 'fixtures', 'ast', 'unknownNode.ts'); const sc = await parseSourceCode(filePath, parsers.typescript); const protoMessage = parseInProtobuf(sc.ast); - fs.writeFileSync('JS-285-reproducer-ts-proto.json', JSON.stringify(protoMessage, null, 2)); - const serialized = serializeInProtobuf(sc.ast); - fs.writeFileSync('JS-285-reproducer-ts.proto', serialized); expect((protoMessage as any).program.body[0].ifStatement.test.type).toEqual( NODE_TYPE_ENUM.values['UnknownNodeType'], ); 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 ec638d34ea..e6e5318942 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 @@ -168,7 +168,7 @@ public record VariableDeclarator(Location loc, Pattern id, Optional public record WhileStatement(Location loc, Expression test, Statement body) implements Statement {} public record WithStatement(Location loc, Expression object, Statement body) implements Statement {} public record YieldExpression(Location loc, Optional argument, boolean delegate) implements Expression {} - public record UnknownNode(Location loc, String astNodeType) implements Expression {} + public record UnknownNode(Location loc, String rawType) implements Expression {} public interface Operator { String raw(); 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 2df0f0971e..14e9586cd6 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 @@ -728,7 +728,7 @@ private static ESTree.FunctionExpression fromFunctionExpressionType(Node node) { private static ESTree.UnknownNode fromUnknownNodeType(Node node) { UnknownNode unknownNode = node.getUnknownNode(); - return new ESTree.UnknownNode(fromLocation(node.getLoc()), unknownNode.getAstNodeType()); + return new ESTree.UnknownNode(fromLocation(node.getLoc()), unknownNode.getRawType()); } } diff --git a/sonar-plugin/bridge/src/main/protobuf/estree.proto b/sonar-plugin/bridge/src/main/protobuf/estree.proto index 275f507591..6a1e198f99 100644 --- a/sonar-plugin/bridge/src/main/protobuf/estree.proto +++ b/sonar-plugin/bridge/src/main/protobuf/estree.proto @@ -471,5 +471,5 @@ message FunctionExpression { } message UnknownNode { - string astNodeType = 1; + string rawType = 1; } 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 a9aa762dad..d66ce81f9a 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 @@ -64,7 +64,7 @@ class ESTreeFactoryTest { @Test void should_not_fail_with_unknown_nodes() throws IOException { - // the clear version of serialized.proto is `packages/jsts/tests/parsers/fixtures/ast/JS-285-reproducer.ts`, + // the clear version of serialized.proto is `packages/jsts/tests/parsers/fixtures/ast/unknownNode.ts`, // it was generated by writing to a file the serialized data in the test `packages/jsts/tests/parsers/ast.test.ts` File file = Path.of("src", "test", "resources", "files", "unknown.proto").toFile(); @@ -79,7 +79,7 @@ void should_not_fail_with_unknown_nodes() throws IOException { assertThat(program.body().get(0)).isInstanceOfSatisfying(ESTree.IfStatement.class, ifStatement -> { assertThat(ifStatement.test()).isInstanceOf(ESTree.UnknownNode.class); ESTree.UnknownNode unknownNode = (ESTree.UnknownNode)ifStatement.test(); - assertThat(unknownNode.astNodeType()).isEqualTo("TSAsExpression"); + assertThat(unknownNode.rawType()).isEqualTo("TSAsExpression"); }); } diff --git a/tools/estree/output/estree.proto b/tools/estree/output/estree.proto index 275f507591..6a1e198f99 100644 --- a/tools/estree/output/estree.proto +++ b/tools/estree/output/estree.proto @@ -471,5 +471,5 @@ message FunctionExpression { } message UnknownNode { - string astNodeType = 1; + string rawType = 1; } From 4632615e544ebd98215b151b4bd4753f216e43e3 Mon Sep 17 00:00:00 2001 From: Victor Diez Date: Wed, 28 Aug 2024 18:54:33 +0200 Subject: [PATCH 6/8] changes after review --- .../org/sonar/plugins/javascript/bridge/ESTreeFactoryTest.java | 1 - 1 file changed, 1 deletion(-) 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 d66ce81f9a..7eeaea268a 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 @@ -80,7 +80,6 @@ void should_not_fail_with_unknown_nodes() throws IOException { assertThat(ifStatement.test()).isInstanceOf(ESTree.UnknownNode.class); ESTree.UnknownNode unknownNode = (ESTree.UnknownNode)ifStatement.test(); assertThat(unknownNode.rawType()).isEqualTo("TSAsExpression"); - }); } From 181257bb14155031f23e620b11e3e44fb9ba5530 Mon Sep 17 00:00:00 2001 From: Victor Diez Date: Wed, 28 Aug 2024 19:24:43 +0200 Subject: [PATCH 7/8] fix error --- packages/jsts/src/parsers/ast.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jsts/src/parsers/ast.ts b/packages/jsts/src/parsers/ast.ts index db17485b38..3958f234c9 100644 --- a/packages/jsts/src/parsers/ast.ts +++ b/packages/jsts/src/parsers/ast.ts @@ -318,7 +318,7 @@ export function visitNode(node: TSESTree.Node | undefined | null): any { case 'TSUndefinedKeyword': case 'TSUnionType': case 'TSUnknownKeyword': - case 'TSVoidKeyword': { + case 'TSVoidKeyword': default: { debug(`Unknown node type: ${node.type}`); return visitUnknownNode(node); @@ -871,7 +871,7 @@ export function visitNode(node: TSESTree.Node | undefined | null): any { }; } - function visitUnknownNode(node: estree.BaseNodeWithoutComments) { + function visitUnknownNode(node: TSESTree.Node) { return { rawType: node.type, }; From 39440b720146e1247013119a41d3c9eea7d99222 Mon Sep 17 00:00:00 2001 From: Victor Diez Date: Wed, 28 Aug 2024 19:36:38 +0200 Subject: [PATCH 8/8] fix test --- packages/jsts/tests/parsers/ast.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jsts/tests/parsers/ast.test.ts b/packages/jsts/tests/parsers/ast.test.ts index 8adc0c2f74..8a797b603b 100644 --- a/packages/jsts/tests/parsers/ast.test.ts +++ b/packages/jsts/tests/parsers/ast.test.ts @@ -67,7 +67,7 @@ describe('ast', () => { test('should encode unknown nodes', async () => { const filePath = path.join(__dirname, 'fixtures', 'ast', 'unknownNode.ts'); const sc = await parseSourceCode(filePath, parsers.typescript); - const protoMessage = parseInProtobuf(sc.ast); + const protoMessage = parseInProtobuf(sc.ast as TSESTree.Program); expect((protoMessage as any).program.body[0].ifStatement.test.type).toEqual( NODE_TYPE_ENUM.values['UnknownNodeType'], );