From 665d6749d6b91605fa74062c689005b07f8af3f6 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 1 Oct 2024 22:23:19 +0530 Subject: [PATCH 1/9] Add rule for non isolated public construct --- .../io/ballerina/scan/internal/CoreRule.java | 5 +- .../scan/internal/StaticCodeAnalyzer.java | 87 ++++++++++++++- .../io/ballerina/scan/utils/Constants.java | 10 ++ .../scan/utils/ScanCodeAnalyzerUtils.java | 36 +++++++ .../scan/internal/StaticCodeAnalyzerTest.java | 50 +++++++-- .../rule_non_isolated_public_functions.bal | 101 ++++++++++++++++++ 6 files changed, 275 insertions(+), 14 deletions(-) create mode 100644 scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java create mode 100644 scan-command/src/test/resources/test-resources/core-rules/rule_non_isolated_public_functions.bal diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java index 211049e3..4a4eb6e8 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java @@ -20,6 +20,7 @@ import io.ballerina.scan.Rule; import io.ballerina.scan.RuleKind; +import io.ballerina.scan.utils.Constants; import java.util.ArrayList; import java.util.List; @@ -30,7 +31,9 @@ * @since 0.1.0 * */ enum CoreRule { - AVOID_CHECKPANIC(RuleFactory.createRule(1, "Avoid checkpanic", RuleKind.CODE_SMELL)); + AVOID_CHECKPANIC(RuleFactory.createRule(1, Constants.RuleDescription.AVOID_CHECKPANIC, RuleKind.CODE_SMELL)), + PUBLIC_NON_ISOLATED_CONSTRUCT(RuleFactory.createRule( + 2, Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL)); private final Rule rule; diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java index d7cf2c0e..a38d2629 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java @@ -18,14 +18,31 @@ package io.ballerina.scan.internal; +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.api.symbols.ClassSymbol; +import io.ballerina.compiler.api.symbols.Qualifier; +import io.ballerina.compiler.api.symbols.SymbolKind; import io.ballerina.compiler.syntax.tree.CheckExpressionNode; +import io.ballerina.compiler.syntax.tree.ClassDefinitionNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; import io.ballerina.compiler.syntax.tree.ModulePartNode; +import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.NodeVisitor; -import io.ballerina.compiler.syntax.tree.SyntaxKind; import io.ballerina.compiler.syntax.tree.SyntaxTree; +import io.ballerina.compiler.syntax.tree.Token; import io.ballerina.projects.Document; import io.ballerina.scan.ScannerContext; +import java.util.List; + +import static io.ballerina.compiler.syntax.tree.SyntaxKind.CHECKPANIC_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.PUBLIC_KEYWORD; +import static io.ballerina.scan.utils.Constants.INIT_METHOD; +import static io.ballerina.scan.utils.Constants.MAIN_METHOD; +import static io.ballerina.scan.utils.ScanCodeAnalyzerUtils.getQualifier; +import static io.ballerina.scan.utils.ScanCodeAnalyzerUtils.reportIssue; + /** * {@code StaticCodeAnalyzer} contains the logic to perform core static code analysis on Ballerina documents. * @@ -35,8 +52,10 @@ class StaticCodeAnalyzer extends NodeVisitor { private final Document document; private final SyntaxTree syntaxTree; private final ScannerContext scannerContext; + private final SemanticModel semanticModel; StaticCodeAnalyzer(Document document, ScannerContextImpl scannerContext) { + semanticModel = document.module().getCompilation().getSemanticModel(); this.document = document; this.syntaxTree = document.syntaxTree(); this.scannerContext = scannerContext; @@ -46,6 +65,11 @@ void analyze() { this.visit((ModulePartNode) syntaxTree.rootNode()); } + @Override + public void visit(ModulePartNode modulePartNode) { + modulePartNode.members().forEach(member -> member.accept(this)); + } + /** * Visits check expressions in a Ballerina document and perform static code analysis. * @@ -53,9 +77,64 @@ void analyze() { */ @Override public void visit(CheckExpressionNode checkExpressionNode) { - if (checkExpressionNode.checkKeyword().kind().equals(SyntaxKind.CHECKPANIC_KEYWORD)) { - scannerContext.getReporter().reportIssue(document, checkExpressionNode.location(), - CoreRule.AVOID_CHECKPANIC.rule()); + if (checkExpressionNode.checkKeyword().kind().equals(CHECKPANIC_KEYWORD)) { + reportIssue(scannerContext, document, checkExpressionNode, CoreRule.AVOID_CHECKPANIC.rule()); + } + } + + @Override + public void visit(ClassDefinitionNode classDefinitionNode) { + semanticModel.symbol(classDefinitionNode).ifPresent(symbol -> { + if (symbol instanceof ClassSymbol classSymbol) { + List qualifiers = classSymbol.qualifiers(); + if (getQualifier(qualifiers, PUBLIC_KEYWORD.stringValue()) && + !getQualifier(qualifiers, ISOLATED_KEYWORD.stringValue())) { + reportIssue(scannerContext, document, classDefinitionNode, + CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule()); + } + } + }); + classDefinitionNode.members().forEach(member -> { + semanticModel.symbol(member).ifPresent(symbol -> { + if (symbol.kind() == SymbolKind.METHOD) { + checkNonIsolatedPublicMethods((FunctionDefinitionNode) member, classDefinitionNode); + } + member.accept(this); + }); + }); + } + + @Override + public void visit(FunctionDefinitionNode functionDefinitionNode) { + if (!functionDefinitionNode.functionName().text().equals(MAIN_METHOD) && + !functionDefinitionNode.functionName().text().equals(INIT_METHOD)) { + semanticModel.symbol(functionDefinitionNode).ifPresent(symbol -> { + if (symbol.kind() != SymbolKind.METHOD) { + checkNonIsolatedPublicFunctions(functionDefinitionNode); + } + }); + } + functionDefinitionNode.functionBody().children().forEach(child -> child.accept(this)); + } + + private void checkNonIsolatedPublicMethods(FunctionDefinitionNode member, + ClassDefinitionNode classDefinitionNode) { + semanticModel.symbol(classDefinitionNode).ifPresent(symbol -> { + if (symbol instanceof ClassSymbol classSymbol) { + if (getQualifier(classSymbol.qualifiers(), PUBLIC_KEYWORD.stringValue()) && + getQualifier(member.qualifierList(), PUBLIC_KEYWORD) && + !getQualifier(member.qualifierList(), ISOLATED_KEYWORD)) { + reportIssue(scannerContext, document, member, CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule()); + } + } + }); + } + + private void checkNonIsolatedPublicFunctions(FunctionDefinitionNode functionDefinitionNode) { + NodeList qualifiers = functionDefinitionNode.qualifierList(); + if (getQualifier(qualifiers, PUBLIC_KEYWORD) && !getQualifier(qualifiers, ISOLATED_KEYWORD)) { + reportIssue(scannerContext, document, functionDefinitionNode, + CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule()); } } } diff --git a/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java b/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java index 372de85d..c48f97c7 100644 --- a/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java +++ b/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java @@ -61,6 +61,16 @@ public class Constants { static final String RULE_KIND_COLUMN = "Rule Kind"; static final String RULE_DESCRIPTION_COLUMN = "Rule Description"; static final String[] RULE_PRIORITY_LIST = {"ballerina", "ballerina/", "ballerinax/", "wso2/"}; + public static final String MAIN_METHOD = "main"; + public static final String INIT_METHOD = "init"; + + public static class RuleDescription { + public static final String AVOID_CHECKPANIC = "Avoid checkpanic"; + public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; + + private RuleDescription() { + } + } private Constants() { } diff --git a/scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java b/scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java new file mode 100644 index 00000000..dcff050f --- /dev/null +++ b/scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java @@ -0,0 +1,36 @@ +package io.ballerina.scan.utils; + +import io.ballerina.compiler.api.symbols.Qualifier; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import io.ballerina.compiler.syntax.tree.Token; +import io.ballerina.projects.Document; +import io.ballerina.scan.Rule; +import io.ballerina.scan.ScannerContext; + +import java.util.List; + +public class ScanCodeAnalyzerUtils { + public static boolean getQualifier(List qualifierList, String qualifierValue) { + for (Qualifier qualifier : qualifierList) { + if (qualifier.getValue() == qualifierValue) { + return true; + } + } + return false; + } + + public static boolean getQualifier(NodeList qualifierList, SyntaxKind qualifier) { + for (Token token : qualifierList) { + if (qualifier == token.kind()) { + return true; + } + } + return false; + } + + public static void reportIssue(ScannerContext scannerContext, Document document, Node node, Rule rule) { + scannerContext.getReporter().reportIssue(document, node.location(), rule); + } +} diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java index 242b11e2..0b1c3ad0 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java @@ -27,6 +27,7 @@ import io.ballerina.scan.Rule; import io.ballerina.scan.RuleKind; import io.ballerina.scan.Source; +import io.ballerina.scan.utils.Constants; import io.ballerina.tools.text.LineRange; import org.testng.Assert; import org.testng.annotations.Test; @@ -57,18 +58,49 @@ void testCheckpanicAnalyzer() { staticCodeAnalyzer.analyze(); List issues = scannerContext.getReporter().getIssues(); Assert.assertEquals(issues.size(), 1); - Issue issue = issues.get(0); + assertIssue(issues.get(0), documentName, 20, 17, 20, 39, "ballerina:1", 1, + Constants.RuleDescription.AVOID_CHECKPANIC, RuleKind.CODE_SMELL); + } + + @Test(description = "test non isolated public functions analyzer") + void testNonIsolatedEntrypointAnalyzer() { + String documentName = "rule_non_isolated_public_functions.bal"; + Document document = loadDocument(documentName); + ScannerContextImpl scannerContext = new ScannerContextImpl(List.of(CoreRule + .PUBLIC_NON_ISOLATED_CONSTRUCT.rule())); + StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext); + staticCodeAnalyzer.analyze(); + List issues = scannerContext.getReporter().getIssues(); + Assert.assertEquals(issues.size(), 7); + assertIssue(issues.get(0), documentName, 16, 0, 18, 1, "ballerina:2", 2, + Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(1), documentName, 58, 0, 78, 1, "ballerina:2", 2, + Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(2), documentName, 63, 4, 65, 5, "ballerina:2", 2, + Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(3), documentName, 67, 4, 69, 5, "ballerina:2", 2, + Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(4), documentName, 75, 4, 77, 5, "ballerina:2", 2, + Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(5), documentName, 89, 4, 91, 5, "ballerina:2", 2, + Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(6), documentName, 97, 4, 99, 5, "ballerina:2", 2, + Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + } + + void assertIssue(Issue issue, String documentName, int startLine, int startOffset, int endLine, int endOffset, + String ruleId, int numericId, String description, RuleKind ruleKind) { Assert.assertEquals(issue.source(), Source.BUILT_IN); LineRange location = issue.location().lineRange(); Assert.assertEquals(location.fileName(), documentName); - Assert.assertEquals(location.startLine().line(), 20); - Assert.assertEquals(location.startLine().offset(), 17); - Assert.assertEquals(location.endLine().line(), 20); - Assert.assertEquals(location.endLine().offset(), 39); + Assert.assertEquals(location.startLine().line(), startLine); + Assert.assertEquals(location.startLine().offset(), startOffset); + Assert.assertEquals(location.endLine().line(), endLine); + Assert.assertEquals(location.endLine().offset(), endOffset); Rule rule = issue.rule(); - Assert.assertEquals(rule.id(), "ballerina:1"); - Assert.assertEquals(rule.numericId(), 1); - Assert.assertEquals(rule.description(), "Avoid checkpanic"); - Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); + Assert.assertEquals(rule.id(), ruleId); + Assert.assertEquals(rule.numericId(), numericId); + Assert.assertEquals(rule.description(), description); + Assert.assertEquals(rule.kind(), ruleKind); } } diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule_non_isolated_public_functions.bal b/scan-command/src/test/resources/test-resources/core-rules/rule_non_isolated_public_functions.bal new file mode 100644 index 00000000..e3fd58cf --- /dev/null +++ b/scan-command/src/test/resources/test-resources/core-rules/rule_non_isolated_public_functions.bal @@ -0,0 +1,101 @@ +// Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). +// +// WSO2 Inc. 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. + +public function a() { // warning + +} + +public isolated function a2() { + +} + +public function main() { + +} + +function b() { + +} + +function init() { + +} + +class A { + function init() { + + } + + public isolated function c2() { + + } + + public function c() { + + } + + function d() { + + } + + public isolated function main() { + + } +} + +public class A2 { // warning + public isolated function c2() { + + } + + public function init() { // warning + + } + + public function c() { // warning + + } + + function d() { + + } + + public function main() { // warning + + } +} + +public isolated class A2 { + public isolated function c2() { + + } + + public isolated function init() { + + } + + public function c() { // warning + + } + + function d() { + + } + + public function main() { // warning + + } +} From a2e5611035ff695b809060a564435d11b9896940 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 9 Oct 2024 17:46:41 +0530 Subject: [PATCH 2/9] Update scan command tests for public constructs --- .../io/ballerina/scan/internal/CoreRule.java | 6 +- .../scan/internal/ProjectAnalyzer.java | 3 +- .../scan/internal/StaticCodeAnalyzer.java | 78 ++++++++++++------- .../io/ballerina/scan/utils/Constants.java | 8 -- .../ballerina/scan/utils/RuleDescription.java | 9 +++ .../scan/utils/ScanCodeAnalyzerUtils.java | 36 --------- .../scan/internal/CheckPanicAnalyzerTest.java | 28 +++++++ .../ballerina/scan/internal/CoreRuleTest.java | 14 +++- ...onIsolatedPublicConstructAnalyzerTest.java | 41 ++++++++++ .../scan/internal/StaticCodeAnalyzerTest.java | 44 +---------- .../unix/list-rules-output.txt | 5 +- .../unix/print-rules-to-console.txt | 5 +- .../windows/list-rules-output.txt | 3 +- .../windows/print-rules-to-console.txt | 3 +- scan-command/src/test/resources/testng.xml | 3 +- 15 files changed, 160 insertions(+), 126 deletions(-) create mode 100644 scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java delete mode 100644 scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java create mode 100644 scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java create mode 100644 scan-command/src/test/java/io/ballerina/scan/internal/NonIsolatedPublicConstructAnalyzerTest.java diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java index 4a4eb6e8..61f4bd71 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java @@ -20,7 +20,7 @@ import io.ballerina.scan.Rule; import io.ballerina.scan.RuleKind; -import io.ballerina.scan.utils.Constants; +import io.ballerina.scan.utils.RuleDescription; import java.util.ArrayList; import java.util.List; @@ -31,9 +31,9 @@ * @since 0.1.0 * */ enum CoreRule { - AVOID_CHECKPANIC(RuleFactory.createRule(1, Constants.RuleDescription.AVOID_CHECKPANIC, RuleKind.CODE_SMELL)), + AVOID_CHECKPANIC(RuleFactory.createRule(1, RuleDescription.AVOID_CHECKPANIC, RuleKind.CODE_SMELL)), PUBLIC_NON_ISOLATED_CONSTRUCT(RuleFactory.createRule( - 2, Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL)); + 3, RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL)); private final Rule rule; diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/ProjectAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/ProjectAnalyzer.java index 2b60df49..4204511f 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/ProjectAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/ProjectAnalyzer.java @@ -113,7 +113,8 @@ List analyze(List inbuiltRules) { private Consumer analyzeDocument(Module module, ScannerContextImpl scannerContext) { return documentId -> { Document document = module.document(documentId); - StaticCodeAnalyzer analyzer = new StaticCodeAnalyzer(document, scannerContext); + StaticCodeAnalyzer analyzer = new StaticCodeAnalyzer(document, scannerContext, module.getCompilation() + .getSemanticModel()); analyzer.analyze(); }; } diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java index a38d2629..b671c469 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java @@ -26,11 +26,14 @@ import io.ballerina.compiler.syntax.tree.ClassDefinitionNode; import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; import io.ballerina.compiler.syntax.tree.ModulePartNode; +import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.NodeVisitor; +import io.ballerina.compiler.syntax.tree.SyntaxKind; import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.compiler.syntax.tree.Token; import io.ballerina.projects.Document; +import io.ballerina.scan.Rule; import io.ballerina.scan.ScannerContext; import java.util.List; @@ -40,8 +43,6 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.PUBLIC_KEYWORD; import static io.ballerina.scan.utils.Constants.INIT_METHOD; import static io.ballerina.scan.utils.Constants.MAIN_METHOD; -import static io.ballerina.scan.utils.ScanCodeAnalyzerUtils.getQualifier; -import static io.ballerina.scan.utils.ScanCodeAnalyzerUtils.reportIssue; /** * {@code StaticCodeAnalyzer} contains the logic to perform core static code analysis on Ballerina documents. @@ -54,22 +55,17 @@ class StaticCodeAnalyzer extends NodeVisitor { private final ScannerContext scannerContext; private final SemanticModel semanticModel; - StaticCodeAnalyzer(Document document, ScannerContextImpl scannerContext) { - semanticModel = document.module().getCompilation().getSemanticModel(); + StaticCodeAnalyzer(Document document, ScannerContextImpl scannerContext, SemanticModel semanticModel) { this.document = document; this.syntaxTree = document.syntaxTree(); this.scannerContext = scannerContext; + this.semanticModel = semanticModel; } void analyze() { this.visit((ModulePartNode) syntaxTree.rootNode()); } - @Override - public void visit(ModulePartNode modulePartNode) { - modulePartNode.members().forEach(member -> member.accept(this)); - } - /** * Visits check expressions in a Ballerina document and perform static code analysis. * @@ -84,6 +80,20 @@ public void visit(CheckExpressionNode checkExpressionNode) { @Override public void visit(ClassDefinitionNode classDefinitionNode) { + checkNonIsolatedPublicClassDefinitions(classDefinitionNode); + checkNonIsolatedPublicClassMembers(classDefinitionNode); + } + + @Override + public void visit(FunctionDefinitionNode functionDefinitionNode) { + if (!functionDefinitionNode.functionName().text().equals(MAIN_METHOD) && + !functionDefinitionNode.functionName().text().equals(INIT_METHOD)) { + checkNonIsolatedPublicFunctions(functionDefinitionNode); + } + functionDefinitionNode.functionBody().children().forEach(child -> child.accept(this)); + } + + private void checkNonIsolatedPublicClassDefinitions(ClassDefinitionNode classDefinitionNode) { semanticModel.symbol(classDefinitionNode).ifPresent(symbol -> { if (symbol instanceof ClassSymbol classSymbol) { List qualifiers = classSymbol.qualifiers(); @@ -94,6 +104,9 @@ public void visit(ClassDefinitionNode classDefinitionNode) { } } }); + } + + private void checkNonIsolatedPublicClassMembers(ClassDefinitionNode classDefinitionNode) { classDefinitionNode.members().forEach(member -> { semanticModel.symbol(member).ifPresent(symbol -> { if (symbol.kind() == SymbolKind.METHOD) { @@ -104,19 +117,6 @@ public void visit(ClassDefinitionNode classDefinitionNode) { }); } - @Override - public void visit(FunctionDefinitionNode functionDefinitionNode) { - if (!functionDefinitionNode.functionName().text().equals(MAIN_METHOD) && - !functionDefinitionNode.functionName().text().equals(INIT_METHOD)) { - semanticModel.symbol(functionDefinitionNode).ifPresent(symbol -> { - if (symbol.kind() != SymbolKind.METHOD) { - checkNonIsolatedPublicFunctions(functionDefinitionNode); - } - }); - } - functionDefinitionNode.functionBody().children().forEach(child -> child.accept(this)); - } - private void checkNonIsolatedPublicMethods(FunctionDefinitionNode member, ClassDefinitionNode classDefinitionNode) { semanticModel.symbol(classDefinitionNode).ifPresent(symbol -> { @@ -131,10 +131,36 @@ private void checkNonIsolatedPublicMethods(FunctionDefinitionNode member, } private void checkNonIsolatedPublicFunctions(FunctionDefinitionNode functionDefinitionNode) { - NodeList qualifiers = functionDefinitionNode.qualifierList(); - if (getQualifier(qualifiers, PUBLIC_KEYWORD) && !getQualifier(qualifiers, ISOLATED_KEYWORD)) { - reportIssue(scannerContext, document, functionDefinitionNode, - CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule()); + semanticModel.symbol(functionDefinitionNode).ifPresent(symbol -> { + if (symbol.kind() != SymbolKind.METHOD) { + NodeList qualifiers = functionDefinitionNode.qualifierList(); + if (getQualifier(qualifiers, PUBLIC_KEYWORD) && !getQualifier(qualifiers, ISOLATED_KEYWORD)) { + reportIssue(scannerContext, document, functionDefinitionNode, + CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule()); + } + } + }); + } + + private boolean getQualifier(List qualifierList, String qualifierValue) { + for (Qualifier qualifier : qualifierList) { + if (qualifier.getValue().equals(qualifierValue)) { + return true; + } } + return false; + } + + private boolean getQualifier(NodeList qualifierList, SyntaxKind qualifier) { + for (Token token : qualifierList) { + if (qualifier == token.kind()) { + return true; + } + } + return false; + } + + private void reportIssue(ScannerContext scannerContext, Document document, Node node, Rule rule) { + scannerContext.getReporter().reportIssue(document, node.location(), rule); } } diff --git a/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java b/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java index c48f97c7..21f6ebe7 100644 --- a/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java +++ b/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java @@ -64,14 +64,6 @@ public class Constants { public static final String MAIN_METHOD = "main"; public static final String INIT_METHOD = "init"; - public static class RuleDescription { - public static final String AVOID_CHECKPANIC = "Avoid checkpanic"; - public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; - - private RuleDescription() { - } - } - private Constants() { } } diff --git a/scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java b/scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java new file mode 100644 index 00000000..8f3ad0c2 --- /dev/null +++ b/scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java @@ -0,0 +1,9 @@ +package io.ballerina.scan.utils; + +public class RuleDescription { + public static final String AVOID_CHECKPANIC = "Avoid checkpanic"; + public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; + + private RuleDescription() { + } +} diff --git a/scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java b/scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java deleted file mode 100644 index dcff050f..00000000 --- a/scan-command/src/main/java/io/ballerina/scan/utils/ScanCodeAnalyzerUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.ballerina.scan.utils; - -import io.ballerina.compiler.api.symbols.Qualifier; -import io.ballerina.compiler.syntax.tree.Node; -import io.ballerina.compiler.syntax.tree.NodeList; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import io.ballerina.compiler.syntax.tree.Token; -import io.ballerina.projects.Document; -import io.ballerina.scan.Rule; -import io.ballerina.scan.ScannerContext; - -import java.util.List; - -public class ScanCodeAnalyzerUtils { - public static boolean getQualifier(List qualifierList, String qualifierValue) { - for (Qualifier qualifier : qualifierList) { - if (qualifier.getValue() == qualifierValue) { - return true; - } - } - return false; - } - - public static boolean getQualifier(NodeList qualifierList, SyntaxKind qualifier) { - for (Token token : qualifierList) { - if (qualifier == token.kind()) { - return true; - } - } - return false; - } - - public static void reportIssue(ScannerContext scannerContext, Document document, Node node, Rule rule) { - scannerContext.getReporter().reportIssue(document, node.location(), rule); - } -} diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java new file mode 100644 index 00000000..71841485 --- /dev/null +++ b/scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java @@ -0,0 +1,28 @@ +package io.ballerina.scan.internal; + +import io.ballerina.projects.Document; +import io.ballerina.scan.Issue; +import io.ballerina.scan.RuleKind; +import io.ballerina.scan.utils.RuleDescription; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.List; + +public class CheckPanicAnalyzerTest extends StaticCodeAnalyzerTest { + + @Test(description = "test checkpanic analyzer") + void testCheckpanicAnalyzer() { + String documentName = "rule_checkpanic.bal"; + Document document = loadDocument(documentName); + ScannerContextImpl scannerContext = new ScannerContextImpl(List.of(CoreRule.AVOID_CHECKPANIC.rule())); + StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, + scannerContext, document.module().getCompilation().getSemanticModel()); + staticCodeAnalyzer.analyze(); + List issues = scannerContext.getReporter().getIssues(); + Assert.assertEquals(issues.size(), 1); + + assertIssue(issues.get(0), documentName, 20, 17, 20, 39, "ballerina:1", 1, + RuleDescription.AVOID_CHECKPANIC, RuleKind.CODE_SMELL); + } +} diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java index 212b3596..86f766e4 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java @@ -20,6 +20,7 @@ import io.ballerina.scan.Rule; import io.ballerina.scan.RuleKind; +import io.ballerina.scan.utils.RuleDescription; import org.testng.Assert; import org.testng.annotations.Test; @@ -31,7 +32,7 @@ public class CoreRuleTest { @Test(description = "test all rules") void testAllRules() { - Assert.assertEquals(CoreRule.rules().size(), 1); + Assert.assertEquals(CoreRule.rules().size(), 2); } @Test(description = "test checkpanic rule") @@ -39,7 +40,16 @@ void testCheckpanicRule() { Rule rule = CoreRule.AVOID_CHECKPANIC.rule(); Assert.assertEquals(rule.id(), "ballerina:1"); Assert.assertEquals(rule.numericId(), 1); - Assert.assertEquals(rule.description(), "Avoid checkpanic"); + Assert.assertEquals(rule.description(), RuleDescription.AVOID_CHECKPANIC); + Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); + } + + @Test(description = "test checkpanic rule") + void testNonIsolatedPublicConstructsRule() { + Rule rule = CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule(); + Assert.assertEquals(rule.id(), "ballerina:3"); + Assert.assertEquals(rule.numericId(), 3); + Assert.assertEquals(rule.description(), RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT); Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/NonIsolatedPublicConstructAnalyzerTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/NonIsolatedPublicConstructAnalyzerTest.java new file mode 100644 index 00000000..97555758 --- /dev/null +++ b/scan-command/src/test/java/io/ballerina/scan/internal/NonIsolatedPublicConstructAnalyzerTest.java @@ -0,0 +1,41 @@ +package io.ballerina.scan.internal; + +import io.ballerina.projects.Document; +import io.ballerina.scan.Issue; +import io.ballerina.scan.RuleKind; +import io.ballerina.scan.utils.RuleDescription; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.List; + +public class NonIsolatedPublicConstructAnalyzerTest extends StaticCodeAnalyzerTest { + + @Test(description = "test non isolated public functions analyzer") + void testNonIsolatedConstructsAnalyzer() { + String documentName = "rule_non_isolated_public_functions.bal"; + Document document = loadDocument(documentName); + ScannerContextImpl scannerContext = new ScannerContextImpl(List + .of(CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule())); + StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext, + document.module().getCompilation().getSemanticModel()); + staticCodeAnalyzer.analyze(); + + List issues = scannerContext.getReporter().getIssues(); + Assert.assertEquals(issues.size(), 7); + assertIssue(issues.get(0), documentName, 16, 0, 18, 1, "ballerina:3", 3, + RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(1), documentName, 58, 0, 78, 1, "ballerina:3", 3, + RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(2), documentName, 63, 4, 65, 5, "ballerina:3", 3, + RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(3), documentName, 67, 4, 69, 5, "ballerina:3", 3, + RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(4), documentName, 75, 4, 77, 5, "ballerina:3", 3, + RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(5), documentName, 89, 4, 91, 5, "ballerina:3", 3, + RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(6), documentName, 97, 4, 99, 5, "ballerina:3", 3, + RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + } +} diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java index 0b1c3ad0..828c3756 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/StaticCodeAnalyzerTest.java @@ -27,13 +27,10 @@ import io.ballerina.scan.Rule; import io.ballerina.scan.RuleKind; import io.ballerina.scan.Source; -import io.ballerina.scan.utils.Constants; import io.ballerina.tools.text.LineRange; import org.testng.Assert; -import org.testng.annotations.Test; import java.nio.file.Path; -import java.util.List; /** * Core analyzer tests. @@ -43,51 +40,12 @@ public class StaticCodeAnalyzerTest extends BaseTest { private final Path coreRuleBalFiles = testResources.resolve("test-resources").resolve("core-rules"); - private Document loadDocument(String documentName) { + Document loadDocument(String documentName) { Project project = SingleFileProject.load(coreRuleBalFiles.resolve(documentName)); Module defaultModule = project.currentPackage().getDefaultModule(); return defaultModule.document(defaultModule.documentIds().iterator().next()); } - @Test(description = "test checkpanic analyzer") - void testCheckpanicAnalyzer() { - String documentName = "rule_checkpanic.bal"; - Document document = loadDocument(documentName); - ScannerContextImpl scannerContext = new ScannerContextImpl(List.of(CoreRule.AVOID_CHECKPANIC.rule())); - StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext); - staticCodeAnalyzer.analyze(); - List issues = scannerContext.getReporter().getIssues(); - Assert.assertEquals(issues.size(), 1); - assertIssue(issues.get(0), documentName, 20, 17, 20, 39, "ballerina:1", 1, - Constants.RuleDescription.AVOID_CHECKPANIC, RuleKind.CODE_SMELL); - } - - @Test(description = "test non isolated public functions analyzer") - void testNonIsolatedEntrypointAnalyzer() { - String documentName = "rule_non_isolated_public_functions.bal"; - Document document = loadDocument(documentName); - ScannerContextImpl scannerContext = new ScannerContextImpl(List.of(CoreRule - .PUBLIC_NON_ISOLATED_CONSTRUCT.rule())); - StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext); - staticCodeAnalyzer.analyze(); - List issues = scannerContext.getReporter().getIssues(); - Assert.assertEquals(issues.size(), 7); - assertIssue(issues.get(0), documentName, 16, 0, 18, 1, "ballerina:2", 2, - Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(1), documentName, 58, 0, 78, 1, "ballerina:2", 2, - Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(2), documentName, 63, 4, 65, 5, "ballerina:2", 2, - Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(3), documentName, 67, 4, 69, 5, "ballerina:2", 2, - Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(4), documentName, 75, 4, 77, 5, "ballerina:2", 2, - Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(5), documentName, 89, 4, 91, 5, "ballerina:2", 2, - Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(6), documentName, 97, 4, 99, 5, "ballerina:2", 2, - Constants.RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - } - void assertIssue(Issue issue, String documentName, int startLine, int startOffset, int endLine, int endOffset, String ruleId, int numericId, String description, RuleKind ruleKind) { Assert.assertEquals(issue.source(), Source.BUILT_IN); diff --git a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt index 991c7a85..743fa833 100644 --- a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt @@ -1,7 +1,8 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-project-with-config-file/Scan.toml - RuleID | Rule Kind | Rule Description - ------------------------------------------------------------------------------------ + RuleID | Rule Kind | Rule Description + ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic + ballerina:3 | CODE_SMELL | Non isolated public class or function/method ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt b/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt index 51bcff07..cc1c9eba 100644 --- a/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt +++ b/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt @@ -1,7 +1,8 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-project-with-config-file/Scan.toml - RuleID | Rule Kind | Rule Description - ------------------------------------------------------------------------------------ + RuleID | Rule Kind | Rule Description + ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic + ballerina:3 | CODE_SMELL | Non isolated public class or function/method ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt index e31d510b..f428f78b 100644 --- a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt @@ -1,7 +1,8 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml RuleID | Rule Kind | Rule Description - ------------------------------------------------------------------------------------ + ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic + ballerina:3 | CODE_SMELL | Non isolated public class or function/method ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt index 9b4032f5..b14bb7e9 100644 --- a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt +++ b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt @@ -1,7 +1,8 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml RuleID | Rule Kind | Rule Description - ------------------------------------------------------------------------------------ + ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic + ballerina:3 | CODE_SMELL | Non isolated public class or function/method ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/testng.xml b/scan-command/src/test/resources/testng.xml index 2ec71776..02469d92 100644 --- a/scan-command/src/test/resources/testng.xml +++ b/scan-command/src/test/resources/testng.xml @@ -29,7 +29,8 @@ under the License. - + + From 8f89ef7dcec8019ec611ea81489e89ed81f6a9e2 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Fri, 1 Nov 2024 09:20:01 +0530 Subject: [PATCH 3/9] Add static rule warning for public isolated constructs --- .../io/ballerina/scan/internal/CoreRule.java | 4 +- .../scan/internal/StaticCodeAnalyzer.java | 1 - .../ballerina/scan/utils/RuleDescription.java | 9 ---- .../scan/internal/CheckPanicAnalyzerTest.java | 28 ------------ .../ballerina/scan/internal/CoreRuleTest.java | 5 +-- .../ballerina/scan/internal/Rule002Test.java | 18 ++++---- .../ballerina/scan/internal/Rule003Test.java | 45 ++++++++++++++----- .../unix/list-rules-output.txt | 2 +- .../windows/list-rules-output.txt | 2 +- ...le002_unused_anonymous_func_parameters.bal | 12 ++--- .../rule002_unused_func_parameters.bal | 2 +- ...03_rule_non_isolated_public_functions.bal} | 0 scan-command/src/test/resources/testng.xml | 2 +- 13 files changed, 57 insertions(+), 73 deletions(-) delete mode 100644 scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java delete mode 100644 scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java rename scan-command/src/test/resources/test-resources/core-rules/{rule_non_isolated_public_functions.bal => rule003_rule_non_isolated_public_functions.bal} (100%) diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java index d90337f2..ac6a3374 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java @@ -20,7 +20,6 @@ import io.ballerina.scan.Rule; import io.ballerina.scan.RuleKind; -import io.ballerina.scan.utils.RuleDescription; import java.util.ArrayList; import java.util.List; @@ -33,7 +32,8 @@ enum CoreRule { AVOID_CHECKPANIC(RuleFactory.createRule(1, "Avoid checkpanic", RuleKind.CODE_SMELL)), UNUSED_FUNCTION_PARAMETER(RuleFactory.createRule(2, "Unused function parameter", RuleKind.CODE_SMELL)), - PUBLIC_NON_ISOLATED_CONSTRUCT(RuleFactory.createRule(3, RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL)); + PUBLIC_NON_ISOLATED_CONSTRUCT(RuleFactory.createRule(3, + "Non isolated public class or function/method", RuleKind.CODE_SMELL)); private final Rule rule; diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java index 198bbf45..5e5a26c8 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java @@ -91,7 +91,6 @@ public void visit(FunctionDefinitionNode functionDefinitionNode) { !functionDefinitionNode.functionName().text().equals(INIT_METHOD)) { checkNonIsolatedPublicFunctions(functionDefinitionNode); } - functionDefinitionNode.functionBody().children().forEach(child -> child.accept(this)); this.visitSyntaxNode(functionDefinitionNode); } diff --git a/scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java b/scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java deleted file mode 100644 index 8f3ad0c2..00000000 --- a/scan-command/src/main/java/io/ballerina/scan/utils/RuleDescription.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.ballerina.scan.utils; - -public class RuleDescription { - public static final String AVOID_CHECKPANIC = "Avoid checkpanic"; - public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; - - private RuleDescription() { - } -} diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java deleted file mode 100644 index 71841485..00000000 --- a/scan-command/src/test/java/io/ballerina/scan/internal/CheckPanicAnalyzerTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.ballerina.scan.internal; - -import io.ballerina.projects.Document; -import io.ballerina.scan.Issue; -import io.ballerina.scan.RuleKind; -import io.ballerina.scan.utils.RuleDescription; -import org.testng.Assert; -import org.testng.annotations.Test; - -import java.util.List; - -public class CheckPanicAnalyzerTest extends StaticCodeAnalyzerTest { - - @Test(description = "test checkpanic analyzer") - void testCheckpanicAnalyzer() { - String documentName = "rule_checkpanic.bal"; - Document document = loadDocument(documentName); - ScannerContextImpl scannerContext = new ScannerContextImpl(List.of(CoreRule.AVOID_CHECKPANIC.rule())); - StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, - scannerContext, document.module().getCompilation().getSemanticModel()); - staticCodeAnalyzer.analyze(); - List issues = scannerContext.getReporter().getIssues(); - Assert.assertEquals(issues.size(), 1); - - assertIssue(issues.get(0), documentName, 20, 17, 20, 39, "ballerina:1", 1, - RuleDescription.AVOID_CHECKPANIC, RuleKind.CODE_SMELL); - } -} diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java index d3dc31d8..25537b7a 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java @@ -20,7 +20,6 @@ import io.ballerina.scan.Rule; import io.ballerina.scan.RuleKind; -import io.ballerina.scan.utils.RuleDescription; import org.testng.Assert; import org.testng.annotations.Test; @@ -32,6 +31,7 @@ public class CoreRuleTest { public static final String AVOID_CHECKPANIC = "Avoid checkpanic"; public static final String UNUSED_FUNCTION_PARAMETER = "Unused function parameter"; + public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; @Test(description = "test all rules") void testAllRules() { @@ -61,8 +61,7 @@ void testNonIsolatedPublicConstructsRule() { Rule rule = CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule(); Assert.assertEquals(rule.id(), "ballerina:3"); Assert.assertEquals(rule.numericId(), 3); - Assert.assertEquals(rule.description(), RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT); - Assert.assertEquals(rule.description(), RuleDescription.AVOID_CHECKPANIC); + Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_CONSTRUCT); Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/Rule002Test.java b/scan-command/src/test/java/io/ballerina/scan/internal/Rule002Test.java index caa365e7..47faa51d 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/Rule002Test.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/Rule002Test.java @@ -69,9 +69,9 @@ void testUnusedFunctionParameter() { UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(11), documentName, 72, 19, 72, 24, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(12), documentName, 76, 18, 76, 23, "ballerina:2", 2, + assertIssue(issues.get(12), documentName, 76, 11, 76, 16, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(13), documentName, 76, 32, 76, 37, "ballerina:2", 2, + assertIssue(issues.get(13), documentName, 76, 25, 76, 30, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(14), documentName, 77, 22, 77, 28, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); @@ -93,23 +93,23 @@ void testUnusedAnonymousFunctionParameter() { List issues = scannerContext.getReporter().getIssues(); Assert.assertEquals(issues.size(), 16); - assertIssue(issues.get(0), documentName, 16, 34, 16, 39, "ballerina:2", 2, + assertIssue(issues.get(0), documentName, 16, 27, 16, 32, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(1), documentName, 16, 41, 16, 46, "ballerina:2", 2, + assertIssue(issues.get(1), documentName, 16, 34, 16, 39, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(2), documentName, 17, 17, 17, 24, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(3), documentName, 25, 26, 25, 31, "ballerina:2", 2, + assertIssue(issues.get(3), documentName, 25, 19, 25, 24, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(4), documentName, 27, 50, 27, 57, "ballerina:2", 2, + assertIssue(issues.get(4), documentName, 27, 43, 27, 50, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(5), documentName, 29, 48, 29, 49, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(6), documentName, 31, 61, 31, 66, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(7), documentName, 33, 26, 33, 31, "ballerina:2", 2, + assertIssue(issues.get(7), documentName, 33, 19, 33, 24, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(8), documentName, 33, 57, 33, 64, "ballerina:2", 2, + assertIssue(issues.get(8), documentName, 33, 50, 33, 57, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(9), documentName, 39, 26, 39, 31, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); @@ -117,7 +117,7 @@ void testUnusedAnonymousFunctionParameter() { UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(11), documentName, 47, 17, 47, 22, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); - assertIssue(issues.get(12), documentName, 53, 28, 53, 33, "ballerina:2", 2, + assertIssue(issues.get(12), documentName, 53, 21, 53, 26, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); assertIssue(issues.get(13), documentName, 56, 19, 56, 26, "ballerina:2", 2, UNUSED_FUNCTION_PARAMETER, RuleKind.CODE_SMELL); diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java index 97555758..c65acef1 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java @@ -1,19 +1,42 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. 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 io.ballerina.scan.internal; import io.ballerina.projects.Document; import io.ballerina.scan.Issue; import io.ballerina.scan.RuleKind; -import io.ballerina.scan.utils.RuleDescription; import org.testng.Assert; import org.testng.annotations.Test; import java.util.List; -public class NonIsolatedPublicConstructAnalyzerTest extends StaticCodeAnalyzerTest { +/** + * Non isolated public constructs usage tests. + * + * @since 0.1.0 + */ +public class Rule003Test extends StaticCodeAnalyzerTest { + public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; @Test(description = "test non isolated public functions analyzer") - void testNonIsolatedConstructsAnalyzer() { - String documentName = "rule_non_isolated_public_functions.bal"; + void testNonIsolatedPublicConstructsUsage() { + String documentName = "rule003_rule_non_isolated_public_functions.bal"; Document document = loadDocument(documentName); ScannerContextImpl scannerContext = new ScannerContextImpl(List .of(CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule())); @@ -24,18 +47,18 @@ void testNonIsolatedConstructsAnalyzer() { List issues = scannerContext.getReporter().getIssues(); Assert.assertEquals(issues.size(), 7); assertIssue(issues.get(0), documentName, 16, 0, 18, 1, "ballerina:3", 3, - RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(1), documentName, 58, 0, 78, 1, "ballerina:3", 3, - RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(2), documentName, 63, 4, 65, 5, "ballerina:3", 3, - RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(3), documentName, 67, 4, 69, 5, "ballerina:3", 3, - RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(4), documentName, 75, 4, 77, 5, "ballerina:3", 3, - RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(5), documentName, 89, 4, 91, 5, "ballerina:3", 3, - RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(6), documentName, 97, 4, 99, 5, "ballerina:3", 3, - RuleDescription.PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt index cfea060c..31df6485 100644 --- a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt @@ -1,5 +1,5 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-project-with-config-file/Scan.toml - RuleID | Rule Kind | Rule Description + RuleID | Rule Kind | Rule Description ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter diff --git a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt index cddace90..6af17a69 100644 --- a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt @@ -1,5 +1,5 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml - RuleID | Rule Kind | Rule Description + RuleID | Rule Kind | Rule Description ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_anonymous_func_parameters.bal b/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_anonymous_func_parameters.bal index 9043b248..c5502906 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_anonymous_func_parameters.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_anonymous_func_parameters.bal @@ -14,7 +14,7 @@ // specific language governing permissions and limitations // under the License. -public function testExprFunctions(int a, int b, int c) { // warning * 2 +function testExprFunctions(int a, int b, int c) { // warning * 2 [1,2].forEach(element => ()); // warning [1,2].forEach(element => doNothing(element + c)); } @@ -23,15 +23,15 @@ function (int, int) returns int anonFunc1 = (x, y) => x + y; function (int, int) returns int anonFunc2 = function (int x, int y) returns int => x + y; -public function anonFunc3(int a) => [1,2].forEach(element => doNothing(element)); // warning +function anonFunc3(int a) => [1,2].forEach(element => doNothing(element)); // warning -public function anonFunc4(int a) => [1,2].forEach(element => doNothing(a)); // warning +function anonFunc4(int a) => [1,2].forEach(element => doNothing(a)); // warning function (int, int) returns int anonFunc5 = (x, y) => x; // warning function (int, int) returns int anonFunc6 = function (int x, int y) returns int => x; // warning -public function anonFunc7(int a, int b) => [1,2].forEach(element => doNothing(b)); // warning * 2 +function anonFunc7(int a, int b) => [1,2].forEach(element => doNothing(b)); // warning * 2 type F function (int, int) returns int; @@ -42,7 +42,7 @@ type R record { }; }; -public function testInlineFunctionDecl() { +function testInlineFunctionDecl() { F[] _ = [ (a, b) => a, // warning function(int a, int b) returns int { // warning @@ -51,7 +51,7 @@ public function testInlineFunctionDecl() { ]; } -public function main(int a, int b, int c) { // warning +function main(int a, int b, int c) { // warning _ = doNothing(a); _ = doNothing(c); [1,2].forEach((element) => ()); // warning diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_func_parameters.bal b/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_func_parameters.bal index 3894afc5..e89ff062 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_func_parameters.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule002_unused_func_parameters.bal @@ -74,7 +74,7 @@ function doNothing(int a) { // warning return; } -public function t(int a, int b, int c) { // warning * 2 +function t(int a, int b, int c) { // warning * 2 var fn = function(int a2, int b2) returns int => b; // warning * 2 int _ = fn(1,2); } diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule_non_isolated_public_functions.bal b/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions.bal similarity index 100% rename from scan-command/src/test/resources/test-resources/core-rules/rule_non_isolated_public_functions.bal rename to scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions.bal diff --git a/scan-command/src/test/resources/testng.xml b/scan-command/src/test/resources/testng.xml index d51d902d..465860f6 100644 --- a/scan-command/src/test/resources/testng.xml +++ b/scan-command/src/test/resources/testng.xml @@ -31,7 +31,7 @@ under the License. - + From 22fd8a21f68bad5ea3e3c4ed4d426402d11cf24f Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Fri, 1 Nov 2024 09:40:35 +0530 Subject: [PATCH 4/9] Fix windows build issue with non isolated public construct static rule --- .../resources/command-outputs/windows/list-rules-output.txt | 2 +- .../command-outputs/windows/print-rules-to-console.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt index 6af17a69..acef73f7 100644 --- a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt @@ -1,5 +1,5 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml - RuleID | Rule Kind | Rule Description + RuleID | Rule Kind | Rule Description ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter diff --git a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt index 59709fe2..56304ad1 100644 --- a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt +++ b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt @@ -1,5 +1,5 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml - RuleID | Rule Kind | Rule Description + RuleID | Rule Kind | Rule Description ---------------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter From 374149009dcb05d4a6af9b2e72d0d2371d6e7792 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Mon, 3 Feb 2025 00:14:14 +0530 Subject: [PATCH 5/9] Refactor utill methods --- .../io/ballerina/scan/internal/CoreRule.java | 6 +- .../scan/internal/StaticCodeAnalyzer.java | 97 +++++++++++++------ .../io/ballerina/scan/utils/Constants.java | 4 +- .../ballerina/scan/internal/CoreRuleTest.java | 21 +++- .../ballerina/scan/internal/Rule003Test.java | 55 +++++++---- ..._isolated_public_functions_or_methods.bal} | 2 +- ...non_isolated_public_classes_or_objects.bal | 47 +++++++++ 7 files changed, 171 insertions(+), 61 deletions(-) rename scan-command/src/test/resources/test-resources/core-rules/{rule003_rule_non_isolated_public_functions.bal => rule003_rule_non_isolated_public_functions_or_methods.bal} (98%) create mode 100644 scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java index ac6a3374..556d4e33 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java @@ -32,8 +32,10 @@ enum CoreRule { AVOID_CHECKPANIC(RuleFactory.createRule(1, "Avoid checkpanic", RuleKind.CODE_SMELL)), UNUSED_FUNCTION_PARAMETER(RuleFactory.createRule(2, "Unused function parameter", RuleKind.CODE_SMELL)), - PUBLIC_NON_ISOLATED_CONSTRUCT(RuleFactory.createRule(3, - "Non isolated public class or function/method", RuleKind.CODE_SMELL)); + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT(RuleFactory.createRule(3, + "Non isolated public function or method", RuleKind.CODE_SMELL)), + PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT(RuleFactory.createRule(4, + "Non isolated public class or object", RuleKind.CODE_SMELL)); private final Rule rule; diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java index 5e5a26c8..d1991192 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java @@ -19,10 +19,12 @@ package io.ballerina.scan.internal; import io.ballerina.compiler.api.SemanticModel; -import io.ballerina.compiler.api.symbols.ClassSymbol; +import io.ballerina.compiler.api.symbols.ObjectTypeSymbol; import io.ballerina.compiler.api.symbols.Qualifier; import io.ballerina.compiler.api.symbols.Symbol; import io.ballerina.compiler.api.symbols.SymbolKind; +import io.ballerina.compiler.api.symbols.TypeDefinitionSymbol; +import io.ballerina.compiler.api.symbols.TypeSymbol; import io.ballerina.compiler.syntax.tree.CheckExpressionNode; import io.ballerina.compiler.syntax.tree.ClassDefinitionNode; import io.ballerina.compiler.syntax.tree.ExplicitAnonymousFunctionExpressionNode; @@ -35,10 +37,12 @@ import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.NodeVisitor; +import io.ballerina.compiler.syntax.tree.ObjectTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.compiler.syntax.tree.Token; +import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; import io.ballerina.projects.Document; import io.ballerina.scan.ScannerContext; @@ -47,8 +51,8 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.PUBLIC_KEYWORD; -import static io.ballerina.scan.utils.Constants.INIT_METHOD; -import static io.ballerina.scan.utils.Constants.MAIN_METHOD; +import static io.ballerina.scan.utils.Constants.INIT_FUNCTION; +import static io.ballerina.scan.utils.Constants.MAIN_FUNCTION; /** * {@code StaticCodeAnalyzer} contains the logic to perform core static code analysis on Ballerina documents. @@ -87,8 +91,9 @@ public void visit(CheckExpressionNode checkExpressionNode) { @Override public void visit(FunctionDefinitionNode functionDefinitionNode) { checkUnusedFunctionParameters(functionDefinitionNode.functionSignature()); - if (!functionDefinitionNode.functionName().text().equals(MAIN_METHOD) && - !functionDefinitionNode.functionName().text().equals(INIT_METHOD)) { + String functionName = functionDefinitionNode.functionName().text(); + if (!functionName.equals(MAIN_FUNCTION) && + !functionName.equals(INIT_FUNCTION)) { checkNonIsolatedPublicFunctions(functionDefinitionNode); } this.visitSyntaxNode(functionDefinitionNode); @@ -118,67 +123,95 @@ public void visit(ImplicitAnonymousFunctionExpressionNode implicitAnonymousFunct @Override public void visit(ClassDefinitionNode classDefinitionNode) { - checkNonIsolatedPublicClassDefinitions(classDefinitionNode); + checkNonIsolatedPublicClassDefinition(classDefinitionNode); checkNonIsolatedPublicClassMembers(classDefinitionNode); } - private void checkNonIsolatedPublicClassDefinitions(ClassDefinitionNode classDefinitionNode) { + @Override + public void visit(TypeDefinitionNode typeDefinitionNode) { + semanticModel.symbol(typeDefinitionNode).ifPresent(symbol -> { + if (symbol instanceof TypeDefinitionSymbol typeDefinitionSymbol) { + TypeSymbol typeSymbol = typeDefinitionSymbol.typeDescriptor(); + if (typeSymbol instanceof ObjectTypeSymbol objectTypeSymbol) { + List qualifiers = objectTypeSymbol.qualifiers(); + List typeDefQualifiers = typeDefinitionSymbol.qualifiers(); + if (hasQualifier(typeDefQualifiers, PUBLIC_KEYWORD) && + !hasQualifier(qualifiers, ISOLATED_KEYWORD)) { + reportIssue(typeDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT); + } + } + } + }); + } + + private void checkNonIsolatedPublicClassDefinition(ClassDefinitionNode classDefinitionNode) { semanticModel.symbol(classDefinitionNode).ifPresent(symbol -> { - if (symbol instanceof ClassSymbol classSymbol) { - List qualifiers = classSymbol.qualifiers(); - if (getQualifier(qualifiers, PUBLIC_KEYWORD.stringValue()) && - !getQualifier(qualifiers, ISOLATED_KEYWORD.stringValue())) { - reportIssue(classDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT); + if (symbol instanceof ObjectTypeSymbol objectTypeSymbol) { + List qualifiers = objectTypeSymbol.qualifiers(); + if (hasQualifier(qualifiers, PUBLIC_KEYWORD) && + !hasQualifier(qualifiers, ISOLATED_KEYWORD)) { + reportIssue(classDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT); } } }); } private void checkNonIsolatedPublicClassMembers(ClassDefinitionNode classDefinitionNode) { - classDefinitionNode.members().forEach(member -> { - semanticModel.symbol(member).ifPresent(symbol -> { - if (symbol.kind() == SymbolKind.METHOD) { - checkNonIsolatedPublicMethods((FunctionDefinitionNode) member, classDefinitionNode); + semanticModel.symbol(classDefinitionNode).ifPresent(classSymbol -> { + if (classSymbol instanceof ObjectTypeSymbol objectTypeSymbol) { + boolean isPublicObjectTypeSymbol = hasQualifier(objectTypeSymbol.qualifiers(), PUBLIC_KEYWORD); + classDefinitionNode.members().forEach(member -> { + semanticModel.symbol(member).ifPresent(memberSymbol -> { + if (isPublicObjectTypeSymbol && memberSymbol.kind() == SymbolKind.METHOD) { + checkNonIsolatedPublicMethods((FunctionDefinitionNode) member); + } + member.accept(this); + }); + }); + } + }); + } + + private void checkNonIsolatedPublicObjectMembers(ObjectTypeDescriptorNode objectTypeDescriptorNode) { + objectTypeDescriptorNode.members().forEach(member -> { + semanticModel.symbol(member).ifPresent(memberSymbol -> { + if (memberSymbol.kind() == SymbolKind.METHOD) { + checkNonIsolatedPublicMethods((FunctionDefinitionNode) member); } member.accept(this); }); }); } - private void checkNonIsolatedPublicMethods(FunctionDefinitionNode member, - ClassDefinitionNode classDefinitionNode) { - semanticModel.symbol(classDefinitionNode).ifPresent(symbol -> { - if (symbol instanceof ClassSymbol classSymbol) { - if (getQualifier(classSymbol.qualifiers(), PUBLIC_KEYWORD.stringValue()) && - getQualifier(member.qualifierList(), PUBLIC_KEYWORD) && - !getQualifier(member.qualifierList(), ISOLATED_KEYWORD)) { - reportIssue(member, CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT); - } - } - }); + private void checkNonIsolatedPublicMethods(FunctionDefinitionNode member) { + if (hasQualifier(member.qualifierList(), PUBLIC_KEYWORD) && + !hasQualifier(member.qualifierList(), ISOLATED_KEYWORD)) { + reportIssue(member, CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); + } } private void checkNonIsolatedPublicFunctions(FunctionDefinitionNode functionDefinitionNode) { semanticModel.symbol(functionDefinitionNode).ifPresent(symbol -> { if (symbol.kind() != SymbolKind.METHOD) { NodeList qualifiers = functionDefinitionNode.qualifierList(); - if (getQualifier(qualifiers, PUBLIC_KEYWORD) && !getQualifier(qualifiers, ISOLATED_KEYWORD)) { - reportIssue(functionDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT); + if (hasQualifier(qualifiers, PUBLIC_KEYWORD) && !hasQualifier(qualifiers, ISOLATED_KEYWORD)) { + reportIssue(functionDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); } } }); } - private boolean getQualifier(List qualifierList, String qualifierValue) { + private boolean hasQualifier(List qualifierList, SyntaxKind qualifierValue) { + String qualifierValueStr = qualifierValue.stringValue(); for (Qualifier qualifier : qualifierList) { - if (qualifier.getValue().equals(qualifierValue)) { + if (qualifier.getValue().equals(qualifierValueStr)) { return true; } } return false; } - private boolean getQualifier(NodeList qualifierList, SyntaxKind qualifier) { + private boolean hasQualifier(NodeList qualifierList, SyntaxKind qualifier) { for (Token token : qualifierList) { if (qualifier == token.kind()) { return true; diff --git a/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java b/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java index 21f6ebe7..d23a82d5 100644 --- a/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java +++ b/scan-command/src/main/java/io/ballerina/scan/utils/Constants.java @@ -61,8 +61,8 @@ public class Constants { static final String RULE_KIND_COLUMN = "Rule Kind"; static final String RULE_DESCRIPTION_COLUMN = "Rule Description"; static final String[] RULE_PRIORITY_LIST = {"ballerina", "ballerina/", "ballerinax/", "wso2/"}; - public static final String MAIN_METHOD = "main"; - public static final String INIT_METHOD = "init"; + public static final String MAIN_FUNCTION = "main"; + public static final String INIT_FUNCTION = "init"; private Constants() { } diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java index 25537b7a..f9cd4d6c 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java @@ -31,7 +31,9 @@ public class CoreRuleTest { public static final String AVOID_CHECKPANIC = "Avoid checkpanic"; public static final String UNUSED_FUNCTION_PARAMETER = "Unused function parameter"; - public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; + public static final String PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT = + "Non isolated public function or method"; + public static final String PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT = "Non isolated public class or object"; @Test(description = "test all rules") void testAllRules() { @@ -56,12 +58,21 @@ void testUnusedFunctionParameterRule() { Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); } - @Test(description = "test checkpanic rule") - void testNonIsolatedPublicConstructsRule() { - Rule rule = CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule(); + @Test(description = "test non isolated public functions or methods") + void testNonIsolatedPublicFunctionOrMethodConstructsRule() { + Rule rule = CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule(); Assert.assertEquals(rule.id(), "ballerina:3"); Assert.assertEquals(rule.numericId(), 3); - Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_CONSTRUCT); + Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); + Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); + } + + @Test(description = "test non isolated public class or object constructs") + void testNonIsolatedPublicClassOrObjectConstructsRule() { + Rule rule = CoreRule.PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT.rule(); + Assert.assertEquals(rule.id(), "ballerina:4"); + Assert.assertEquals(rule.numericId(), 4); + Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT); Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java index c65acef1..a3dbd3ad 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java @@ -32,33 +32,50 @@ * @since 0.1.0 */ public class Rule003Test extends StaticCodeAnalyzerTest { - public static final String PUBLIC_NON_ISOLATED_CONSTRUCT = "Non isolated public class or function/method"; + public static final String PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT = + "Non isolated public function or method"; + public static final String PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT = + "Non isolated public class or object"; @Test(description = "test non isolated public functions analyzer") - void testNonIsolatedPublicConstructsUsage() { - String documentName = "rule003_rule_non_isolated_public_functions.bal"; + void testNonIsolatedPublicFunctionOrMethodConstructsUsage() { + String documentName = "rule003_rule_non_isolated_public_functions_or_methods.bal"; Document document = loadDocument(documentName); - ScannerContextImpl scannerContext = new ScannerContextImpl(List - .of(CoreRule.PUBLIC_NON_ISOLATED_CONSTRUCT.rule())); + ScannerContextImpl scannerContext = new ScannerContextImpl(List.of( + CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule())); StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext, document.module().getCompilation().getSemanticModel()); staticCodeAnalyzer.analyze(); List issues = scannerContext.getReporter().getIssues(); - Assert.assertEquals(issues.size(), 7); + Assert.assertEquals(issues.size(), 6); assertIssue(issues.get(0), documentName, 16, 0, 18, 1, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(1), documentName, 58, 0, 78, 1, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(2), documentName, 63, 4, 65, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(3), documentName, 67, 4, 69, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(4), documentName, 75, 4, 77, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(5), documentName, 89, 4, 91, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(6), documentName, 97, 4, 99, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(1), documentName, 63, 4, 65, 5, "ballerina:3", 3, + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(2), documentName, 67, 4, 69, 5, "ballerina:3", 3, + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(3), documentName, 75, 4, 77, 5, "ballerina:3", 3, + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(4), documentName, 89, 4, 91, 5, "ballerina:3", 3, + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(5), documentName, 97, 4, 99, 5, "ballerina:3", 3, + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + } + + @Test(description = "test non isolated public class or object analyzer") + void testNonIsolatedPublicClassOrObjectConstructsUsage() { + String documentName = "rule004_rule_non_isolated_public_classes_or_objects.bal"; + Document document = loadDocument(documentName); + ScannerContextImpl scannerContext = new ScannerContextImpl(List.of( + CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule())); + StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext, + document.module().getCompilation().getSemanticModel()); + staticCodeAnalyzer.analyze(); + + List issues = scannerContext.getReporter().getIssues(); + Assert.assertEquals(issues.size(), 2); + assertIssue(issues.get(0), documentName, 20, 0, 22, 1, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions.bal b/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal similarity index 98% rename from scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions.bal rename to scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal index e3fd58cf..20a1c653 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal @@ -56,7 +56,7 @@ class A { } } -public class A2 { // warning +public isolated class A2 { public isolated function c2() { } diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal b/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal new file mode 100644 index 00000000..657253d2 --- /dev/null +++ b/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal @@ -0,0 +1,47 @@ +// Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). +// +// WSO2 Inc. 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. + +class A { + +} + +public class B { // warning + +} + +isolated class C { + +} + +public isolated class D { + +} + +type E object { + public function hash() returns int; +}; + +public type F object { // warning + public function hash() returns int; +}; + +isolated type G object { + public isolated function hash() returns int; +}; + +public isolated type Hashable object { + public function hash() returns int; +}; From f6b5ee27722e95fc2066c37f744094af9963c4f6 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 19 Feb 2025 01:07:00 +0530 Subject: [PATCH 6/9] Add tests for service classes and object types --- .../scan/internal/StaticCodeAnalyzer.java | 13 +--- .../ballerina/scan/internal/CoreRuleTest.java | 2 +- .../ballerina/scan/internal/Rule003Test.java | 24 +++---- .../ballerina/scan/internal/Rule004Test.java | 59 ++++++++++++++++ .../unix/list-rules-output.txt | 7 +- .../unix/print-rules-to-console.txt | 9 +-- ...n_isolated_public_functions_or_methods.bal | 68 ++++++++++++++++++- ...non_isolated_public_classes_or_objects.bal | 32 ++++++++- scan-command/src/test/resources/testng.xml | 1 + 9 files changed, 177 insertions(+), 38 deletions(-) create mode 100644 scan-command/src/test/java/io/ballerina/scan/internal/Rule004Test.java diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java index d1991192..47b27107 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java @@ -37,7 +37,6 @@ import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.NodeVisitor; -import io.ballerina.compiler.syntax.tree.ObjectTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; import io.ballerina.compiler.syntax.tree.SyntaxTree; @@ -142,6 +141,7 @@ public void visit(TypeDefinitionNode typeDefinitionNode) { } } }); + this.visitSyntaxNode(typeDefinitionNode); } private void checkNonIsolatedPublicClassDefinition(ClassDefinitionNode classDefinitionNode) { @@ -172,17 +172,6 @@ private void checkNonIsolatedPublicClassMembers(ClassDefinitionNode classDefinit }); } - private void checkNonIsolatedPublicObjectMembers(ObjectTypeDescriptorNode objectTypeDescriptorNode) { - objectTypeDescriptorNode.members().forEach(member -> { - semanticModel.symbol(member).ifPresent(memberSymbol -> { - if (memberSymbol.kind() == SymbolKind.METHOD) { - checkNonIsolatedPublicMethods((FunctionDefinitionNode) member); - } - member.accept(this); - }); - }); - } - private void checkNonIsolatedPublicMethods(FunctionDefinitionNode member) { if (hasQualifier(member.qualifierList(), PUBLIC_KEYWORD) && !hasQualifier(member.qualifierList(), ISOLATED_KEYWORD)) { diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java index f9cd4d6c..88039849 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java @@ -37,7 +37,7 @@ public class CoreRuleTest { @Test(description = "test all rules") void testAllRules() { - Assert.assertEquals(CoreRule.rules().size(), 3); + Assert.assertEquals(CoreRule.rules().size(), 4); } @Test(description = "test checkpanic rule") diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java index a3dbd3ad..d2df2167 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java @@ -48,7 +48,7 @@ void testNonIsolatedPublicFunctionOrMethodConstructsUsage() { staticCodeAnalyzer.analyze(); List issues = scannerContext.getReporter().getIssues(); - Assert.assertEquals(issues.size(), 6); + Assert.assertEquals(issues.size(), 10); assertIssue(issues.get(0), documentName, 16, 0, 18, 1, "ballerina:3", 3, PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(1), documentName, 63, 4, 65, 5, "ballerina:3", 3, @@ -61,21 +61,13 @@ void testNonIsolatedPublicFunctionOrMethodConstructsUsage() { PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); assertIssue(issues.get(5), documentName, 97, 4, 99, 5, "ballerina:3", 3, PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - } - - @Test(description = "test non isolated public class or object analyzer") - void testNonIsolatedPublicClassOrObjectConstructsUsage() { - String documentName = "rule004_rule_non_isolated_public_classes_or_objects.bal"; - Document document = loadDocument(documentName); - ScannerContextImpl scannerContext = new ScannerContextImpl(List.of( - CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule())); - StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext, - document.module().getCompilation().getSemanticModel()); - staticCodeAnalyzer.analyze(); - - List issues = scannerContext.getReporter().getIssues(); - Assert.assertEquals(issues.size(), 2); - assertIssue(issues.get(0), documentName, 20, 0, 22, 1, "ballerina:4", 4, + assertIssue(issues.get(6), documentName, 102, 0, 122, 1, "ballerina:4", 4, PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(7), documentName, 111, 4, 113, 5, "ballerina:3", 3, + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(8), documentName, 146, 0, 166, 1, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(9), documentName, 155, 4, 157, 5, "ballerina:3", 3, + PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/Rule004Test.java b/scan-command/src/test/java/io/ballerina/scan/internal/Rule004Test.java new file mode 100644 index 00000000..02ad2bdd --- /dev/null +++ b/scan-command/src/test/java/io/ballerina/scan/internal/Rule004Test.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. 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 io.ballerina.scan.internal; + +import io.ballerina.projects.Document; +import io.ballerina.scan.Issue; +import io.ballerina.scan.RuleKind; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.List; + +/** + * Non isolated public constructs usage tests. + * + * @since 0.1.0 + */ +public class Rule004Test extends StaticCodeAnalyzerTest { + public static final String PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT = + "Non isolated public class or object"; + + @Test(description = "test non isolated public class or object analyzer") + void testNonIsolatedPublicClassOrObjectConstructsUsage() { + String documentName = "rule004_rule_non_isolated_public_classes_or_objects.bal"; + Document document = loadDocument(documentName); + ScannerContextImpl scannerContext = new ScannerContextImpl(List.of( + CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule())); + StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext, + document.module().getCompilation().getSemanticModel()); + staticCodeAnalyzer.analyze(); + + List issues = scannerContext.getReporter().getIssues(); + Assert.assertEquals(issues.size(), 4); + assertIssue(issues.get(0), documentName, 20, 0, 22, 1, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(1), documentName, 37, 0, 40, 2, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(2), documentName, 57, 0, 60, 2, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(3), documentName, 74, 0, 76, 1, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + } +} diff --git a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt index 31df6485..e2f35b40 100644 --- a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt @@ -1,9 +1,10 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-project-with-config-file/Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ---------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public class or function/method + ballerina:3 | CODE_SMELL | Non isolated public function or method + ballerina:4 | CODE_SMELL | Non isolated public class or object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt b/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt index 1efce09e..e2f35b40 100644 --- a/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt +++ b/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt @@ -1,9 +1,10 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-project-with-config-file/Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ---------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public class or function/method + ballerina:3 | CODE_SMELL | Non isolated public function or method + ballerina:4 | CODE_SMELL | Non isolated public class or object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 @@ -12,4 +13,4 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-proj ballerinax/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 exampleOrg/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 exampleOrg/example_module_static_code_analyzer:2 | BUG | rule 2 - exampleOrg/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 \ No newline at end of file + exampleOrg/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal b/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal index 20a1c653..b91db86c 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal @@ -78,7 +78,7 @@ public isolated class A2 { } } -public isolated class A2 { +public isolated class A3 { public isolated function c2() { } @@ -99,3 +99,69 @@ public isolated class A2 { } } + +public class A4 { // warning + function init() { + + } + + public isolated function c2() { + + } + + public function c() { // warning + + } + + function d() { + + } + + public isolated function main() { + + } +} + +public isolated service class { + function init() { + + } + + public isolated function c2() { + + } + + public function c() { + + } + + function d() { + + } + + public isolated function main() { + + } +} + +public service class SC { // warning + function init() { + + } + + public isolated function c2() { + + } + + public function c() { // warning + + } + + function d() { + + } + + public isolated function main() { + + } +} diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal b/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal index 657253d2..4f71f6ee 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal @@ -32,16 +32,46 @@ public isolated class D { type E object { public function hash() returns int; + function hash2() returns int; }; public type F object { // warning public function hash() returns int; + function hash2() returns int; }; isolated type G object { public isolated function hash() returns int; + function hash2() returns int; }; -public isolated type Hashable object { +public type Hashable isolated object { public function hash() returns int; + function hash2() returns int; }; + +type H object { + public isolated function hash() returns int; + function hash2() returns int; +}; + +public type I object { // warning + public isolated function hash() returns int; + function hash2() returns int; +}; + +isolated service class A { + +} + +service class SA2 { + +} + +public isolated service class SA3 { + +} + +public service class SA4 { // warning + +} \ No newline at end of file diff --git a/scan-command/src/test/resources/testng.xml b/scan-command/src/test/resources/testng.xml index 465860f6..9cc39786 100644 --- a/scan-command/src/test/resources/testng.xml +++ b/scan-command/src/test/resources/testng.xml @@ -32,6 +32,7 @@ under the License. + From bf0081b8002bba644cbba670a5e37119c79485f2 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Thu, 20 Feb 2025 13:30:47 +0530 Subject: [PATCH 7/9] Update windows tests in reports --- .../command-outputs/windows/list-rules-output.txt | 7 ++++--- .../command-outputs/windows/print-rules-to-console.txt | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt index acef73f7..6e8919b0 100644 --- a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt @@ -1,9 +1,10 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ---------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public class or function/method + ballerina:3 | CODE_SMELL | Non isolated public function or method + ballerina:4 | CODE_SMELL | Non isolated public class or object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt index 56304ad1..6e8919b0 100644 --- a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt +++ b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt @@ -1,9 +1,10 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ---------------------------------------------------------------------------------------------------------- ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public class or function/method + ballerina:3 | CODE_SMELL | Non isolated public function or method + ballerina:4 | CODE_SMELL | Non isolated public class or object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 @@ -12,4 +13,4 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-proj ballerinax/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 exampleOrg/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 exampleOrg/example_module_static_code_analyzer:2 | BUG | rule 2 - exampleOrg/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 \ No newline at end of file + exampleOrg/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 From cbb64866d597f61268d13765e1acb36628edb9f9 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 25 Feb 2025 15:36:23 +0530 Subject: [PATCH 8/9] Update public isolated construct rules --- .../scan/internal/StaticCodeAnalyzer.java | 39 ++++++++++++------- ...non_isolated_public_classes_or_objects.bal | 2 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java index 47b27107..8248f02d 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java @@ -91,9 +91,8 @@ public void visit(CheckExpressionNode checkExpressionNode) { public void visit(FunctionDefinitionNode functionDefinitionNode) { checkUnusedFunctionParameters(functionDefinitionNode.functionSignature()); String functionName = functionDefinitionNode.functionName().text(); - if (!functionName.equals(MAIN_FUNCTION) && - !functionName.equals(INIT_FUNCTION)) { - checkNonIsolatedPublicFunctions(functionDefinitionNode); + if (!functionName.equals(MAIN_FUNCTION) && !functionName.equals(INIT_FUNCTION)) { + checkNonIsolatedPublicFunction(functionDefinitionNode); } this.visitSyntaxNode(functionDefinitionNode); } @@ -123,11 +122,17 @@ public void visit(ImplicitAnonymousFunctionExpressionNode implicitAnonymousFunct @Override public void visit(ClassDefinitionNode classDefinitionNode) { checkNonIsolatedPublicClassDefinition(classDefinitionNode); - checkNonIsolatedPublicClassMembers(classDefinitionNode); + checkNonIsolatedPublicClassMethod(classDefinitionNode); + this.visitSyntaxNode(classDefinitionNode); } @Override public void visit(TypeDefinitionNode typeDefinitionNode) { + checkNonIsolatedConstructsInTypeDefinition(typeDefinitionNode); + this.visitSyntaxNode(typeDefinitionNode); + } + + private void checkNonIsolatedConstructsInTypeDefinition(TypeDefinitionNode typeDefinitionNode) { semanticModel.symbol(typeDefinitionNode).ifPresent(symbol -> { if (symbol instanceof TypeDefinitionSymbol typeDefinitionSymbol) { TypeSymbol typeSymbol = typeDefinitionSymbol.typeDescriptor(); @@ -141,49 +146,45 @@ public void visit(TypeDefinitionNode typeDefinitionNode) { } } }); - this.visitSyntaxNode(typeDefinitionNode); } private void checkNonIsolatedPublicClassDefinition(ClassDefinitionNode classDefinitionNode) { semanticModel.symbol(classDefinitionNode).ifPresent(symbol -> { if (symbol instanceof ObjectTypeSymbol objectTypeSymbol) { List qualifiers = objectTypeSymbol.qualifiers(); - if (hasQualifier(qualifiers, PUBLIC_KEYWORD) && - !hasQualifier(qualifiers, ISOLATED_KEYWORD)) { + if (isPublicIsolatedConstruct(qualifiers)) { reportIssue(classDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT); } } }); } - private void checkNonIsolatedPublicClassMembers(ClassDefinitionNode classDefinitionNode) { + private void checkNonIsolatedPublicClassMethod(ClassDefinitionNode classDefinitionNode) { semanticModel.symbol(classDefinitionNode).ifPresent(classSymbol -> { if (classSymbol instanceof ObjectTypeSymbol objectTypeSymbol) { boolean isPublicObjectTypeSymbol = hasQualifier(objectTypeSymbol.qualifiers(), PUBLIC_KEYWORD); classDefinitionNode.members().forEach(member -> { semanticModel.symbol(member).ifPresent(memberSymbol -> { if (isPublicObjectTypeSymbol && memberSymbol.kind() == SymbolKind.METHOD) { - checkNonIsolatedPublicMethods((FunctionDefinitionNode) member); + checkNonIsolatedPublicMethod((FunctionDefinitionNode) member); } - member.accept(this); }); }); } }); } - private void checkNonIsolatedPublicMethods(FunctionDefinitionNode member) { - if (hasQualifier(member.qualifierList(), PUBLIC_KEYWORD) && - !hasQualifier(member.qualifierList(), ISOLATED_KEYWORD)) { + private void checkNonIsolatedPublicMethod(FunctionDefinitionNode member) { + if (isPublicIsolatedConstruct(member.qualifierList())) { reportIssue(member, CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); } } - private void checkNonIsolatedPublicFunctions(FunctionDefinitionNode functionDefinitionNode) { + private void checkNonIsolatedPublicFunction(FunctionDefinitionNode functionDefinitionNode) { semanticModel.symbol(functionDefinitionNode).ifPresent(symbol -> { if (symbol.kind() != SymbolKind.METHOD) { NodeList qualifiers = functionDefinitionNode.qualifierList(); - if (hasQualifier(qualifiers, PUBLIC_KEYWORD) && !hasQualifier(qualifiers, ISOLATED_KEYWORD)) { + if (isPublicIsolatedConstruct(qualifiers)) { reportIssue(functionDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); } } @@ -236,4 +237,12 @@ private boolean isUnusedNode(Node node) { Optional symbol = semanticModel.symbol(node); return symbol.filter(value -> semanticModel.references(value).size() == 1).isPresent(); } + + private boolean isPublicIsolatedConstruct(NodeList qualifiers) { + return hasQualifier(qualifiers, PUBLIC_KEYWORD) && !hasQualifier(qualifiers, ISOLATED_KEYWORD); + } + + private boolean isPublicIsolatedConstruct(List qualifiers) { + return hasQualifier(qualifiers, PUBLIC_KEYWORD) && !hasQualifier(qualifiers, ISOLATED_KEYWORD); + } } diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal b/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal index 4f71f6ee..7c509bd4 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal @@ -74,4 +74,4 @@ public isolated service class SA3 { public service class SA4 { // warning -} \ No newline at end of file +} From c877b5fe9fdc2df2ca70125019836ef335fe1358 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Sat, 15 Mar 2025 22:32:04 +0530 Subject: [PATCH 9/9] Divide public construct warnings into four --- .../io/ballerina/scan/internal/CoreRule.java | 12 ++-- .../scan/internal/StaticCodeAnalyzer.java | 8 +-- .../ballerina/scan/internal/CoreRuleTest.java | 47 ++++++++++---- ...ule003Test.java => Rule003And004Test.java} | 62 +++++++++++-------- ...ule004Test.java => Rule005And006Test.java} | 29 +++++---- .../unix/list-rules-output.txt | 10 +-- .../unix/print-rules-to-console.txt | 10 +-- .../windows/list-rules-output.txt | 10 +-- .../windows/print-rules-to-console.txt | 10 +-- ..._isolated_public_functions_or_methods.bal} | 26 +++++++- ...on_isolated_public_classes_or_objects.bal} | 4 +- scan-command/src/test/resources/testng.xml | 4 +- 12 files changed, 150 insertions(+), 82 deletions(-) rename scan-command/src/test/java/io/ballerina/scan/internal/{Rule003Test.java => Rule003And004Test.java} (50%) rename scan-command/src/test/java/io/ballerina/scan/internal/{Rule004Test.java => Rule005And006Test.java} (67%) rename scan-command/src/test/resources/test-resources/core-rules/{rule003_rule_non_isolated_public_functions_or_methods.bal => rule003_and_004_rules_non_isolated_public_functions_or_methods.bal} (86%) rename scan-command/src/test/resources/test-resources/core-rules/{rule004_rule_non_isolated_public_classes_or_objects.bal => rule005_and_006_rule_non_isolated_public_classes_or_objects.bal} (96%) diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java index 556d4e33..742f91c6 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/CoreRule.java @@ -32,10 +32,14 @@ enum CoreRule { AVOID_CHECKPANIC(RuleFactory.createRule(1, "Avoid checkpanic", RuleKind.CODE_SMELL)), UNUSED_FUNCTION_PARAMETER(RuleFactory.createRule(2, "Unused function parameter", RuleKind.CODE_SMELL)), - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT(RuleFactory.createRule(3, - "Non isolated public function or method", RuleKind.CODE_SMELL)), - PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT(RuleFactory.createRule(4, - "Non isolated public class or object", RuleKind.CODE_SMELL)); + PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT(RuleFactory.createRule(3, + "Non isolated public function", RuleKind.CODE_SMELL)), + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT(RuleFactory.createRule(4, + "Non isolated public method", RuleKind.CODE_SMELL)), + PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT(RuleFactory.createRule(5, + "Non isolated public class", RuleKind.CODE_SMELL)), + PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT(RuleFactory.createRule(6, + "Non isolated public object", RuleKind.CODE_SMELL)); private final Rule rule; diff --git a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java index 8248f02d..b39c7201 100644 --- a/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java +++ b/scan-command/src/main/java/io/ballerina/scan/internal/StaticCodeAnalyzer.java @@ -141,7 +141,7 @@ private void checkNonIsolatedConstructsInTypeDefinition(TypeDefinitionNode typeD List typeDefQualifiers = typeDefinitionSymbol.qualifiers(); if (hasQualifier(typeDefQualifiers, PUBLIC_KEYWORD) && !hasQualifier(qualifiers, ISOLATED_KEYWORD)) { - reportIssue(typeDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT); + reportIssue(typeDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT); } } } @@ -153,7 +153,7 @@ private void checkNonIsolatedPublicClassDefinition(ClassDefinitionNode classDefi if (symbol instanceof ObjectTypeSymbol objectTypeSymbol) { List qualifiers = objectTypeSymbol.qualifiers(); if (isPublicIsolatedConstruct(qualifiers)) { - reportIssue(classDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT); + reportIssue(classDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT); } } }); @@ -176,7 +176,7 @@ private void checkNonIsolatedPublicClassMethod(ClassDefinitionNode classDefiniti private void checkNonIsolatedPublicMethod(FunctionDefinitionNode member) { if (isPublicIsolatedConstruct(member.qualifierList())) { - reportIssue(member, CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); + reportIssue(member, CoreRule.PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT); } } @@ -185,7 +185,7 @@ private void checkNonIsolatedPublicFunction(FunctionDefinitionNode functionDefin if (symbol.kind() != SymbolKind.METHOD) { NodeList qualifiers = functionDefinitionNode.qualifierList(); if (isPublicIsolatedConstruct(qualifiers)) { - reportIssue(functionDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); + reportIssue(functionDefinitionNode, CoreRule.PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT); } } }); diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java index 88039849..ec24936a 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/CoreRuleTest.java @@ -31,13 +31,18 @@ public class CoreRuleTest { public static final String AVOID_CHECKPANIC = "Avoid checkpanic"; public static final String UNUSED_FUNCTION_PARAMETER = "Unused function parameter"; - public static final String PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT = - "Non isolated public function or method"; - public static final String PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT = "Non isolated public class or object"; + public static final String PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT = + "Non isolated public function"; + public static final String PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT = + "Non isolated public method"; + public static final String PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT = + "Non isolated public class"; + public static final String PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT = + "Non isolated public object"; @Test(description = "test all rules") void testAllRules() { - Assert.assertEquals(CoreRule.rules().size(), 4); + Assert.assertEquals(CoreRule.rules().size(), 6); } @Test(description = "test checkpanic rule") @@ -58,21 +63,39 @@ void testUnusedFunctionParameterRule() { Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); } - @Test(description = "test non isolated public functions or methods") - void testNonIsolatedPublicFunctionOrMethodConstructsRule() { - Rule rule = CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule(); + @Test(description = "test non isolated public functions") + void testNonIsolatedPublicFunctionConstructsRule() { + Rule rule = CoreRule.PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT.rule(); Assert.assertEquals(rule.id(), "ballerina:3"); Assert.assertEquals(rule.numericId(), 3); - Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT); + Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT); Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); } - @Test(description = "test non isolated public class or object constructs") - void testNonIsolatedPublicClassOrObjectConstructsRule() { - Rule rule = CoreRule.PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT.rule(); + @Test(description = "test non isolated public methods") + void testNonIsolatedPublicMethodConstructsRule() { + Rule rule = CoreRule.PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT.rule(); Assert.assertEquals(rule.id(), "ballerina:4"); Assert.assertEquals(rule.numericId(), 4); - Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT); + Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT); + Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); + } + + @Test(description = "test non isolated public classes") + void testNonIsolatedPublicClassConstructsRule() { + Rule rule = CoreRule.PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT.rule(); + Assert.assertEquals(rule.id(), "ballerina:5"); + Assert.assertEquals(rule.numericId(), 5); + Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT); + Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); + } + + @Test(description = "test non isolated public objects") + void testNonIsolatedPublicObjectConstructsRule() { + Rule rule = CoreRule.PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT.rule(); + Assert.assertEquals(rule.id(), "ballerina:6"); + Assert.assertEquals(rule.numericId(), 6); + Assert.assertEquals(rule.description(), PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT); Assert.assertEquals(rule.kind(), RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003And004Test.java similarity index 50% rename from scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java rename to scan-command/src/test/java/io/ballerina/scan/internal/Rule003And004Test.java index d2df2167..fd0de087 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/Rule003Test.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/Rule003And004Test.java @@ -31,43 +31,51 @@ * * @since 0.1.0 */ -public class Rule003Test extends StaticCodeAnalyzerTest { - public static final String PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT = - "Non isolated public function or method"; - public static final String PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT = - "Non isolated public class or object"; +public class Rule003And004Test extends StaticCodeAnalyzerTest { + public static final String PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT = + "Non isolated public function"; + public static final String PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT = + "Non isolated public method"; + public static final String PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT = + "Non isolated public class"; @Test(description = "test non isolated public functions analyzer") void testNonIsolatedPublicFunctionOrMethodConstructsUsage() { - String documentName = "rule003_rule_non_isolated_public_functions_or_methods.bal"; + String documentName = "rule003_and_004_rules_non_isolated_public_functions_or_methods.bal"; Document document = loadDocument(documentName); ScannerContextImpl scannerContext = new ScannerContextImpl(List.of( - CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule())); + CoreRule.PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT.rule(), + CoreRule.PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT.rule(), + CoreRule.PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT.rule())); StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext, document.module().getCompilation().getSemanticModel()); staticCodeAnalyzer.analyze(); List issues = scannerContext.getReporter().getIssues(); - Assert.assertEquals(issues.size(), 10); + Assert.assertEquals(issues.size(), 12); assertIssue(issues.get(0), documentName, 16, 0, 18, 1, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(1), documentName, 63, 4, 65, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(2), documentName, 67, 4, 69, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(3), documentName, 75, 4, 77, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(4), documentName, 89, 4, 91, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(5), documentName, 97, 4, 99, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(6), documentName, 102, 0, 122, 1, "ballerina:4", 4, - PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(7), documentName, 111, 4, 113, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(8), documentName, 146, 0, 166, 1, "ballerina:4", 4, - PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(9), documentName, 155, 4, 157, 5, "ballerina:3", 3, - PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + PUBLIC_NON_ISOLATED_FUNCTION_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(1), documentName, 63, 4, 65, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(2), documentName, 67, 4, 69, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(3), documentName, 75, 4, 77, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(4), documentName, 89, 4, 91, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(5), documentName, 97, 4, 99, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(6), documentName, 102, 0, 122, 1, "ballerina:5", 5, + PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(7), documentName, 111, 4, 113, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(8), documentName, 133, 4, 135, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(9), documentName, 146, 0, 166, 1, "ballerina:5", 5, + PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(10), documentName, 155, 4, 157, 5, "ballerina:4", 4, + PUBLIC_NON_ISOLATED_METHOD_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(11), documentName, 180, 0, 184, 1, "ballerina:5", 5, + PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT, RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/java/io/ballerina/scan/internal/Rule004Test.java b/scan-command/src/test/java/io/ballerina/scan/internal/Rule005And006Test.java similarity index 67% rename from scan-command/src/test/java/io/ballerina/scan/internal/Rule004Test.java rename to scan-command/src/test/java/io/ballerina/scan/internal/Rule005And006Test.java index 02ad2bdd..545833e0 100644 --- a/scan-command/src/test/java/io/ballerina/scan/internal/Rule004Test.java +++ b/scan-command/src/test/java/io/ballerina/scan/internal/Rule005And006Test.java @@ -31,29 +31,32 @@ * * @since 0.1.0 */ -public class Rule004Test extends StaticCodeAnalyzerTest { - public static final String PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT = - "Non isolated public class or object"; +public class Rule005And006Test extends StaticCodeAnalyzerTest { + public static final String PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT = + "Non isolated public object"; + public static final String PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT = + "Non isolated public class"; @Test(description = "test non isolated public class or object analyzer") void testNonIsolatedPublicClassOrObjectConstructsUsage() { - String documentName = "rule004_rule_non_isolated_public_classes_or_objects.bal"; + String documentName = "rule005_and_006_rule_non_isolated_public_classes_or_objects.bal"; Document document = loadDocument(documentName); ScannerContextImpl scannerContext = new ScannerContextImpl(List.of( - CoreRule.PUBLIC_NON_ISOLATED_FUNCTIONS_OR_METHOD_CONSTRUCT.rule())); + CoreRule.PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT.rule(), + CoreRule.PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT.rule())); StaticCodeAnalyzer staticCodeAnalyzer = new StaticCodeAnalyzer(document, scannerContext, document.module().getCompilation().getSemanticModel()); staticCodeAnalyzer.analyze(); List issues = scannerContext.getReporter().getIssues(); Assert.assertEquals(issues.size(), 4); - assertIssue(issues.get(0), documentName, 20, 0, 22, 1, "ballerina:4", 4, - PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(1), documentName, 37, 0, 40, 2, "ballerina:4", 4, - PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(2), documentName, 57, 0, 60, 2, "ballerina:4", 4, - PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); - assertIssue(issues.get(3), documentName, 74, 0, 76, 1, "ballerina:4", 4, - PUBLIC_NON_ISOLATED_CLASS_OR_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(0), documentName, 20, 0, 22, 1, "ballerina:5", 5, + PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(1), documentName, 37, 0, 40, 2, "ballerina:6", 6, + PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(2), documentName, 57, 0, 60, 2, "ballerina:6", 6, + PUBLIC_NON_ISOLATED_OBJECT_CONSTRUCT, RuleKind.CODE_SMELL); + assertIssue(issues.get(3), documentName, 74, 0, 76, 1, "ballerina:5", 5, + PUBLIC_NON_ISOLATED_CLASS_CONSTRUCT, RuleKind.CODE_SMELL); } } diff --git a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt index e2f35b40..6dea19c6 100644 --- a/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/unix/list-rules-output.txt @@ -1,10 +1,12 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-project-with-config-file/Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ------------------------------------------------------------------------------------------------ ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public function or method - ballerina:4 | CODE_SMELL | Non isolated public class or object + ballerina:3 | CODE_SMELL | Non isolated public function + ballerina:4 | CODE_SMELL | Non isolated public method + ballerina:5 | CODE_SMELL | Non isolated public class + ballerina:6 | CODE_SMELL | Non isolated public object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt b/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt index e2f35b40..6dea19c6 100644 --- a/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt +++ b/scan-command/src/test/resources/command-outputs/unix/print-rules-to-console.txt @@ -1,10 +1,12 @@ Loading scan tool configurations from src/test/resources/test-resources/bal-project-with-config-file/Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ------------------------------------------------------------------------------------------------ ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public function or method - ballerina:4 | CODE_SMELL | Non isolated public class or object + ballerina:3 | CODE_SMELL | Non isolated public function + ballerina:4 | CODE_SMELL | Non isolated public method + ballerina:5 | CODE_SMELL | Non isolated public class + ballerina:6 | CODE_SMELL | Non isolated public object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt index 6e8919b0..7fd737b3 100644 --- a/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt +++ b/scan-command/src/test/resources/command-outputs/windows/list-rules-output.txt @@ -1,10 +1,12 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ------------------------------------------------------------------------------------------------ ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public function or method - ballerina:4 | CODE_SMELL | Non isolated public class or object + ballerina:3 | CODE_SMELL | Non isolated public function + ballerina:4 | CODE_SMELL | Non isolated public method + ballerina:5 | CODE_SMELL | Non isolated public class + ballerina:6 | CODE_SMELL | Non isolated public object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt index 6e8919b0..7fd737b3 100644 --- a/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt +++ b/scan-command/src/test/resources/command-outputs/windows/print-rules-to-console.txt @@ -1,10 +1,12 @@ Loading scan tool configurations from src\test\resources\test-resources\bal-project-with-config-file\Scan.toml - RuleID | Rule Kind | Rule Description - ---------------------------------------------------------------------------------------------------------- + RuleID | Rule Kind | Rule Description + ------------------------------------------------------------------------------------------------ ballerina:1 | CODE_SMELL | Avoid checkpanic ballerina:2 | CODE_SMELL | Unused function parameter - ballerina:3 | CODE_SMELL | Non isolated public function or method - ballerina:4 | CODE_SMELL | Non isolated public class or object + ballerina:3 | CODE_SMELL | Non isolated public function + ballerina:4 | CODE_SMELL | Non isolated public method + ballerina:5 | CODE_SMELL | Non isolated public class + ballerina:6 | CODE_SMELL | Non isolated public object ballerina/example_module_static_code_analyzer:1 | CODE_SMELL | rule 1 ballerina/example_module_static_code_analyzer:2 | BUG | rule 2 ballerina/example_module_static_code_analyzer:3 | VULNERABILITY | rule 3 diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal b/scan-command/src/test/resources/test-resources/core-rules/rule003_and_004_rules_non_isolated_public_functions_or_methods.bal similarity index 86% rename from scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal rename to scan-command/src/test/resources/test-resources/core-rules/rule003_and_004_rules_non_isolated_public_functions_or_methods.bal index b91db86c..408ba27b 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule003_rule_non_isolated_public_functions_or_methods.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule003_and_004_rules_non_isolated_public_functions_or_methods.bal @@ -122,7 +122,7 @@ public class A4 { // warning } } -public isolated service class { +public isolated service class SC4 { function init() { } @@ -131,7 +131,7 @@ public isolated service class { } - public function c() { + public function c() { // warning } @@ -165,3 +165,25 @@ public service class SC { // warning } } + +public isolated service class SC3 { + isolated function c2() { + + } +} + +isolated service class SC6 { + isolated function c2() { + + } +} + +public service class SC5 { // warning + isolated function c2() { + + } +} + +isolated function a3() { + +} diff --git a/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal b/scan-command/src/test/resources/test-resources/core-rules/rule005_and_006_rule_non_isolated_public_classes_or_objects.bal similarity index 96% rename from scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal rename to scan-command/src/test/resources/test-resources/core-rules/rule005_and_006_rule_non_isolated_public_classes_or_objects.bal index 7c509bd4..aec5978c 100644 --- a/scan-command/src/test/resources/test-resources/core-rules/rule004_rule_non_isolated_public_classes_or_objects.bal +++ b/scan-command/src/test/resources/test-resources/core-rules/rule005_and_006_rule_non_isolated_public_classes_or_objects.bal @@ -40,7 +40,7 @@ public type F object { // warning function hash2() returns int; }; -isolated type G object { +type G isolated object { public isolated function hash() returns int; function hash2() returns int; }; @@ -60,7 +60,7 @@ public type I object { // warning function hash2() returns int; }; -isolated service class A { +isolated service class J { } diff --git a/scan-command/src/test/resources/testng.xml b/scan-command/src/test/resources/testng.xml index 9cc39786..15465740 100644 --- a/scan-command/src/test/resources/testng.xml +++ b/scan-command/src/test/resources/testng.xml @@ -31,8 +31,8 @@ under the License. - - + +