Skip to content

Commit

Permalink
Merge pull request #16 from Xenowa/platform-plugin-integration
Browse files Browse the repository at this point in the history
Add support for loading and reporting analysis issues to platform plugins
  • Loading branch information
MaryamZi authored Sep 9, 2024
2 parents 13ac6e0 + 59d9098 commit a6091c8
Show file tree
Hide file tree
Showing 138 changed files with 1,342 additions and 782 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/full_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
env:
packageUser: ${{ github.actor }}
packagePAT: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew build
run: ./gradlew build --scan

- name: Generate Jacoco report
run: ./gradlew createCodeCoverageReport
Expand Down Expand Up @@ -66,10 +66,10 @@ jobs:
- name: Set Up Ballerina
uses: ballerina-platform/[email protected]
with:
version: '2201.9.1'
version: '2201.10.0'

- name: Build with Gradle
env:
packageUser: ${{ github.actor }}
packagePAT: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew build
run: ./gradlew build --scan
10 changes: 5 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ project(':scan-command') {
dependsOn ':test-compiler-plugins:exampleOrg-plugin:build'
dependsOn ':test-compiler-plugins:ballerina-plugin:build'
dependsOn ':test-compiler-plugins:ballerinax-plugin:build'
dependsOn ':test-compiler-plugins:invalid-rulefilemissing-plugin:build'
dependsOn ':test-compiler-plugins:invalid-rules-plugin:build'
dependsOn ':test-compiler-plugins:invalid-ruleformat-plugin:build'
dependsOn ':test-compiler-plugins:invalid-rulekind-plugin:build'
dependsOn ':test-static-code-analysis-platform-plugins:exampleOrg-static-code-analysis-platform-plugin:build'
}
}
}
Expand All @@ -56,25 +56,25 @@ project(':test-compiler-plugins:ballerinax-plugin') {
}
}

project(':test-compiler-plugins:invalid-rulefilemissing-plugin') {
project(':test-compiler-plugins:invalid-rules-plugin') {
dependencies {
implementation project(':scan-command')
}
}

project(':test-compiler-plugins:invalid-rules-plugin') {
project(':test-compiler-plugins:invalid-ruleformat-plugin') {
dependencies {
implementation project(':scan-command')
}
}

project(':test-compiler-plugins:invalid-ruleformat-plugin') {
project(':test-compiler-plugins:invalid-rulekind-plugin') {
dependencies {
implementation project(':scan-command')
}
}

project(':test-compiler-plugins:invalid-rulekind-plugin') {
project(':test-static-code-analysis-platform-plugins:exampleOrg-static-code-analysis-platform-plugin') {
dependencies {
implementation project(':scan-command')
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ releasePluginVersion=2.8.0
# Dependency versions
picoCLIVersion=4.7.5
gsonVersion=2.10.1
ballerinaLangVersion=2201.9.1
ballerinaLangVersion=2201.10.0
puppycrawlCheckstyleVersion=10.12.1
apacheCommonsLang3Version=3.0
commonsIoVersion=2.15.1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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 java.util.Map;

/**
* {@code PlatformPluginContext} represents a context passed from the scan tool to the platform plugins.
*
* @since 0.1.0
*/
public interface PlatformPluginContext {

/**
* <p>
* Returns the platform specific arguments that are defined in addition to the 'name' and 'path' arguments in the
* Scan.toml file as a map. These arguments can be used for modifying the behavior of the specific platform plugin.
*</p>
*
* @return in-memory representation of the additional platform specific arguments defined in the Scan.toml file.
*/
Map<String, String> platformArgs();

/**
* Returns whether the analysis is initiated by the platform.
*
* @return true if the analysis is initiated by the platform, false otherwise.
*/
boolean initiatedByPlatform();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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 java.util.List;

/**
* {@code StaticCodeAnalysisPlatformPlugin} Represents the interface to extend to report issues for a specific platform.
*
* @since 0.1.0
*/
public interface StaticCodeAnalysisPlatformPlugin {

/**
* Returns the platform name.
*
* @return platform name
*/
String platform();

/**
* Initializes the platform plugin with a {@link PlatformPluginContext}.
*
* @param platformPluginContext context passed from the scan tool to the platform plugins.
*/
void init(PlatformPluginContext platformPluginContext);

/**
* The method that gets invoked when the scan is complete.
*
* @param issues list of issues passed from the scan tool.
*/
void onScan(List<Issue> issues);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.PlatformPluginContext;

import java.util.Collections;
import java.util.Map;

/**
* Represents the implementation of the {@link PlatformPluginContext} interface.
*
* @param platformArgs in-memory representation of platform specific arguments defined in the Scan.toml file
* @param initiatedByPlatform true if the plugin is initiated by the platform, false otherwise
*
* @since 0.1.0
*/
public record PlatformPluginContextImpl(Map<String, String> platformArgs, boolean initiatedByPlatform) implements
PlatformPluginContext {
public PlatformPluginContextImpl {
platformArgs = Collections.unmodifiableMap(platformArgs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import io.ballerina.projects.DocumentId;
import io.ballerina.projects.Module;
import io.ballerina.projects.ModuleId;
import io.ballerina.projects.Package;
import io.ballerina.projects.PackageDependencyScope;
import io.ballerina.projects.PackageManifest;
import io.ballerina.projects.PackageResolution;
Expand Down Expand Up @@ -58,6 +57,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
Expand Down Expand Up @@ -122,9 +122,8 @@ Map<String, List<Rule>> getExternalAnalyzers() {
StringBuilder newImports = new StringBuilder();
StringBuilder tomlDependencies = new StringBuilder();
Set<ScanTomlFile.Analyzer> analyzers = scanTomlFile.getAnalyzers();
List<String> analyzerDescriptors = new ArrayList<>(analyzers.size());
for (ScanTomlFile.Analyzer analyzer : analyzers) {
analyzerDescriptors.add(extractAnalyzerImportsAndDependencies(analyzer, newImports, tomlDependencies));
extractAnalyzerImportsAndDependencies(analyzer, newImports, tomlDependencies);
}

Module defaultModule = project.currentPackage().getDefaultModule();
Expand All @@ -138,29 +137,32 @@ Map<String, List<Rule>> getExternalAnalyzers() {
ballerinaToml.modify().withContent(tomlFileContent + tomlDependencies).apply();
});

PackageResolution packageResolution = project.currentPackage().getResolution();
PackageResolution packageResolution = project.currentPackage().getResolution(project.currentPackage()
.compilationOptions());
ResolvedPackageDependency rootPkgNode = new ResolvedPackageDependency(project.currentPackage(),
PackageDependencyScope.DEFAULT);
List<Package> directDependencies = packageResolution.dependencyGraph().getDirectDependencies(rootPkgNode)
.stream().map(ResolvedPackageDependency::packageInstance).toList();
Map<String, List<Rule>> externalAnalyzers = new HashMap<>();
for (Package pkgDependency : directDependencies) {
PackageManifest pkgManifest = pkgDependency.manifest();
String org = pkgManifest.org().value();
String name = pkgManifest.name().value();
String pluginName = org + FORWARD_SLASH + name;
if (pkgManifest.compilerPluginDescriptor().isEmpty() || !analyzerDescriptors.contains(pluginName)) {
continue;
}
CompilerPluginDescriptor pluginDesc = pkgManifest.compilerPluginDescriptor().get();
String ruleFileContent = loadRuleFileContent(pluginName, pluginDesc);
List<Rule> externalRules = loadExternalRules(org, name, pluginName, ruleFileContent);
externalAnalyzers.put(pluginDesc.plugin().getClassName(), externalRules);
}
packageResolution.dependencyGraph().getDirectDependencies(rootPkgNode).stream()
.map(ResolvedPackageDependency::packageInstance).forEach(pkgDependency -> {
PackageManifest pkgManifest = pkgDependency.manifest();
String org = pkgManifest.org().value();
String name = pkgManifest.name().value();
String pluginName = org + FORWARD_SLASH + name;
if (pkgManifest.compilerPluginDescriptor().isEmpty()) {
return;
}
CompilerPluginDescriptor pluginDesc = pkgManifest.compilerPluginDescriptor().get();
Optional<String> ruleFileContent = loadRuleFileContent(pluginName, pluginDesc);
if (ruleFileContent.isEmpty()) {
return;
}
List<Rule> externalRules = loadExternalRules(org, name, pluginName, ruleFileContent.get());
externalAnalyzers.put(pluginDesc.plugin().getClassName(), externalRules);
});
return externalAnalyzers;
}

private String extractAnalyzerImportsAndDependencies(ScanTomlFile.Analyzer analyzer, StringBuilder imports,
private void extractAnalyzerImportsAndDependencies(ScanTomlFile.Analyzer analyzer, StringBuilder imports,
StringBuilder dependencies) {
String org = analyzer.org();
String name = analyzer.name();
Expand All @@ -180,17 +182,16 @@ private String extractAnalyzerImportsAndDependencies(ScanTomlFile.Analyzer analy
if (repository != null) {
buildStringWithNewLine(dependencies, "repository = '" + repository + "'");
}
return analyzerDescriptor;
}

private void buildStringWithNewLine(StringBuilder stringBuilder, String content) {
stringBuilder.append(content).append(System.lineSeparator());
}

private String loadRuleFileContent(String pluginName, CompilerPluginDescriptor pluginDesc) {
private Optional<String> loadRuleFileContent(String pluginName, CompilerPluginDescriptor pluginDesc) {
InputStream resource = loadResource(pluginDesc);
if (resource == null) {
throw new ScanToolException(DiagnosticLog.error(DiagnosticCode.MISSING_RULES_FILE, pluginName, RULES_FILE));
return Optional.empty();
}

String resourceContent;
Expand All @@ -201,7 +202,7 @@ private String loadRuleFileContent(String pluginName, CompilerPluginDescriptor p
throw new ScanToolException(DiagnosticLog.error(DiagnosticCode.READING_RULES_FILE, RULES_FILE, pluginName,
ex.getMessage()));
}
return resourceContent;
return Optional.of(resourceContent);
}

private InputStream loadResource(CompilerPluginDescriptor pluginDesc) {
Expand Down
Loading

0 comments on commit a6091c8

Please sign in to comment.