Skip to content

Commit

Permalink
Add core analyzer with analysis report generation
Browse files Browse the repository at this point in the history
  • Loading branch information
Xenowa committed Apr 24, 2024
1 parent 373e7d5 commit fcc9133
Show file tree
Hide file tree
Showing 31 changed files with 1,467 additions and 87 deletions.
7 changes: 6 additions & 1 deletion ScanCommand/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import org.apache.tools.ant.taskdefs.condition.Os

import java.nio.file.Paths

plugins {
id 'java'
id 'application'
Expand Down Expand Up @@ -271,12 +273,15 @@ build {

// Configuring tests
tasks.test {
systemProperty "ballerina.home", Paths.get(System.getenv("BALLERINA_HOME")).resolve("distributions")
.resolve("ballerina-${ballerinaLangVersion}").toString()

useTestNG() {
suites 'src/test/resources/testng.xml'
}
}

// Codecove configurations
// Codecov configurations
def execFile;
def classFileArray = []
task copyExecFilesAndJavaClassFiles {
Expand Down
47 changes: 47 additions & 0 deletions ScanCommand/src/main/java/io/ballerina/scan/Reporter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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;

import io.ballerina.projects.Document;
import io.ballerina.tools.diagnostics.Location;

/**
* {@code Reporter} represents the reporter used for reporting {@link Issue} instances during static code analysis.
*
* @since 0.1.0
* */
public interface Reporter {
/**
* Reports an issue identified during static code analysis with the use of the numeric identifier of the rule.
*
* @param reportedDocument the Ballerina document for which the issue is reported
* @param location location of reported issue
* @param ruleId numeric identifier of the violated static code analysis rule
* */
void reportIssue(Document reportedDocument, Location location, int ruleId);

/**
* Reports an issue identified during static code analysis with the use of the rule.
*
* @param reportedDocument the Ballerina document for which the issue is reported
* @param location location of reported issue
* @param rule static code analysis rule
* */
void reportIssue(Document reportedDocument, Location location, Rule rule);
}
6 changes: 3 additions & 3 deletions ScanCommand/src/main/java/io/ballerina/scan/Rule.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ public interface Rule {
String description();

/**
* Returns {@link Severity} of the rule.
* Returns {@link RuleKind} of the rule.
*
* @return severity of the rule
* @return rule kind of the rule
*/
Severity severity();
RuleKind kind();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
package io.ballerina.scan;

/**
* Represents the kind of severity of a {@link Rule} instance.
* Represents the kind of rule of a {@link Rule} instance.
*
* @since 0.1.0
*/
public enum Severity {
public enum RuleKind {
/**
* Label for marking rules related to code maintainability.
*/
Expand Down
33 changes: 33 additions & 0 deletions ScanCommand/src/main/java/io/ballerina/scan/ScannerContext.java
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;

/**
* {@code ScannerContext} represents a context that exposes properties required by scanner plugins from the scan tool.
*
* @since 0.1.0
* */
public interface ScannerContext {
/**
* Returns the {@link Reporter} to be used to report identified issues.
*
* @return reporter that needs to be used to report issues identified.
* */
Reporter getReporter();
}
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;

/**
* Represents the exception thrown for an unidentified static code analysis rule during reporting of 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
Expand Up @@ -16,13 +16,21 @@
* under the License.
*/

package io.ballerina.scan;
package io.ballerina.scan.internal;

import io.ballerina.scan.Rule;

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

/**
* This class contains the constant variables used within the Ballerina scan tool.
* {@code InbuiltRules} contains the core static code analysis rules.
*
* @since 0.1.0
*/
class ScanToolConstants {
static final String SCAN_COMMAND = "scan";
* */
public class InbuiltRules {
static final List<Rule> INBUILT_RULES = new ArrayList<>();

private InbuiltRules() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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.Issue;
import io.ballerina.scan.Rule;
import io.ballerina.scan.Source;
import io.ballerina.tools.diagnostics.Location;
import io.ballerina.tools.text.LineRange;
import io.ballerina.tools.text.TextRange;
import org.wso2.ballerinalang.compiler.diagnostic.BLangDiagnosticLocation;

/**
* Represents the implementation of the {@link Issue} interface.
*
* @since 0.1.0
* */
public class IssueImpl implements Issue {
private final BLangDiagnosticLocation location;
private final RuleImpl rule;
private final Source source;
private final String fileName;
private final String filePath;

IssueImpl(Location location,
Rule rule,
Source source,
String fileName,
String filePath) {
LineRange lineRange = location.lineRange();
TextRange textRange = location.textRange();
this.location = new BLangDiagnosticLocation(lineRange.fileName(), lineRange.startLine().line(),
lineRange.endLine().line(), lineRange.startLine().offset(), lineRange.endLine().offset(),
textRange.startOffset(), textRange.length());
this.rule = (RuleImpl) rule;
this.source = source;
this.fileName = fileName;
this.filePath = filePath;
}

@Override
public Location location() {
return location;
}

@Override
public Rule rule() {
return rule;
}

@Override
public Source source() {
return source;
}

public String filePath() {
return filePath;
}

public String fileName() {
return fileName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.projects.DocumentId;
import io.ballerina.projects.Module;
import io.ballerina.projects.Project;
import io.ballerina.scan.Issue;

import java.util.List;
import java.util.function.Consumer;

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

/**
* Represents the project analyzer used for analyzing projects.
*
* @since 0.1.0
* */
class ProjectAnalyzer {
List<Issue> analyze(Project project) {
ScannerContextImpl scannerContext = new ScannerContextImpl(INBUILT_RULES);
project.currentPackage().moduleIds().forEach(moduleId -> {
Module module = project.currentPackage().module(moduleId);
module.documentIds().forEach(analyzeDocument(module, scannerContext));
module.testDocumentIds().forEach(analyzeDocument(module, scannerContext));
});
return scannerContext.getReporter().getIssues();
}

private Consumer<DocumentId> analyzeDocument(Module module, ScannerContextImpl scannerContext) {
return documentId -> {
Document document = module.document(documentId);
StaticCodeAnalyzer analyzer = new StaticCodeAnalyzer(document, scannerContext);
analyzer.analyze();
};
}
}
Loading

0 comments on commit fcc9133

Please sign in to comment.