Skip to content

Commit

Permalink
Add additional implementations and descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Xenowa committed Apr 19, 2024
1 parent 0e3b455 commit e7ccd96
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.exceptions;

/**
* Thrown to indicate that a static code analysis rule is not found during reporting an analysis issue.
*
* @since 0.1.0
* */
public class RuleNotFoundException extends RuntimeException {
public RuleNotFoundException(int ruleId) {
super(String.format("Rule not found: Invalid rule numeric identifier '%d'.", ruleId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.scan.Rule;

import java.util.ArrayList;
import java.util.List;

public class InbuiltRules {
static final List<Rule> INBUILT_RULES = new ArrayList<>();

private InbuiltRules() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@
import java.util.List;
import java.util.function.Consumer;

import static io.ballerina.scan.internal.InbuiltRules.INBUILT_RULES;

/**
* This class represents the project analyzer used for analyzing projects.
*
* @since 0.1.0
* */
class ProjectAnalyzer {
List<Issue> analyze(Project project) {
ScannerContextImpl scannerContext = new ScannerContextImpl();
ScannerContextImpl scannerContext = new ScannerContextImpl(INBUILT_RULES);
project.currentPackage().moduleIds().forEach(moduleId -> {
Module module = project.currentPackage().module(moduleId);
module.documentIds().forEach(analyzeDocument(module, scannerContext));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
import io.ballerina.scan.Reporter;
import io.ballerina.scan.Rule;
import io.ballerina.scan.Source;
import io.ballerina.scan.exceptions.RuleNotFoundException;
import io.ballerina.tools.diagnostics.Location;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* This class implements the {@link Reporter} interface.
Expand All @@ -37,9 +40,30 @@
* */
class ReporterImpl implements Reporter {
private final List<Issue> issues = new ArrayList<>();
private final Map<Integer, Rule> rules = new HashMap<>();

ReporterImpl(List<Rule> rules) {
rules.forEach(rule -> {
this.rules.put(rule.numericId(), rule);
});
}

@Override
public void reportIssue(Document reportedDocument, Location location, int ruleId) {
String documentName = reportedDocument.name();
Module module = reportedDocument.module();
String moduleName = module.moduleName().toString();
Path issuesFilePath = module.project().documentPath(reportedDocument.documentId())
.orElse(Path.of(documentName));

Rule rule = rules.get(ruleId);
if (rule == null) {
throw new RuleNotFoundException(ruleId);
}

IssueImpl issue = new IssueImpl(location, rule, Source.BUILT_IN,
moduleName + System.lineSeparator() + documentName, issuesFilePath.toString());
issues.add(issue);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.scan.Rule;
import io.ballerina.scan.Severity;

import static io.ballerina.scan.internal.ScanToolConstants.BALLERINA_RULE_PREFIX;

public class RuleFactory {
public static Rule createRule(int numericId, String description, Severity severity) {
return new RuleImpl(BALLERINA_RULE_PREFIX + numericId, numericId, description, severity);
}

private RuleFactory() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
public class ScanToolConstants {
static final String SCAN_COMMAND = "scan";
public static final String RESULTS_JSON_FILE = "scan_results.json";
static final String BALLERINA_RULE_PREFIX = "B";

private ScanToolConstants() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@

package io.ballerina.scan.internal;

import io.ballerina.scan.Rule;
import io.ballerina.scan.ScannerContext;

import java.util.List;

/**
* This class implements the {@link ScannerContext} interface.
*
Expand All @@ -28,8 +31,8 @@
class ScannerContextImpl implements ScannerContext {
private final ReporterImpl reporter;

ScannerContextImpl() {
this.reporter = new ReporterImpl();
ScannerContextImpl(List<Rule> rules) {
this.reporter = new ReporterImpl(rules);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.ballerina.projects.Project;
import io.ballerina.projects.directory.SingleFileProject;
import io.ballerina.scan.Issue;
import io.ballerina.scan.Rule;
import io.ballerina.scan.Severity;
import io.ballerina.scan.Source;
import io.ballerina.tools.text.LineRange;
Expand All @@ -34,13 +35,42 @@

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class ReporterImplTest {
@Test(description = "test creating a reporter and retrieving issues reported")
void testReporter() {
@Test(description = "test creating a reporter and retrieving issues reported with a numeric rule identifier")
void testReporterWithNumericId() {
RuleImpl rule = new RuleImpl("B101", 101, "rule 101", Severity.BUG);
ReporterImpl reporter = new ReporterImpl();
List<Rule> rules = new ArrayList<>();
rules.add(rule);
ReporterImpl reporter = new ReporterImpl(rules);
Path validBalProject = Paths.get("src", "test", "resources", "test-resources",
"valid-single-file-project", "main.bal");
Project project = SingleFileProject.load(validBalProject);
Module defaultModule = project.currentPackage().getDefaultModule();
Document document = defaultModule.document(defaultModule.documentIds().iterator().next());
ModulePartNode modulePartNode = (ModulePartNode) document.syntaxTree().rootNode();
LineRange lineRange = modulePartNode.location().lineRange();
TextRange textRange = modulePartNode.location().textRange();
BLangDiagnosticLocation location = new BLangDiagnosticLocation(lineRange.fileName(),
lineRange.startLine().line(), lineRange.endLine().line(),
lineRange.startLine().offset(), lineRange.endLine().offset(),
textRange.startOffset(), textRange.length());
reporter.reportIssue(document, location, 101);
List<Issue> issues = reporter.getIssues();
Issue issue = issues.get(0);
Assert.assertEquals(location, issue.location());
Assert.assertEquals(rule, issue.rule());
Assert.assertEquals(Source.BUILT_IN, issue.source());
}

@Test(description = "test creating a reporter and retrieving issues reported with a rule")
void testReporterWithRule() {
RuleImpl rule = new RuleImpl("B101", 101, "rule 101", Severity.BUG);
List<Rule> rules = new ArrayList<>();
rules.add(rule);
ReporterImpl reporter = new ReporterImpl(rules);
Path validBalProject = Paths.get("src", "test", "resources", "test-resources",
"valid-single-file-project", "main.bal");
Project project = SingleFileProject.load(validBalProject);
Expand Down

0 comments on commit e7ccd96

Please sign in to comment.