Start Free
10.6 | Analyzing source code | Languages | JCL

Was this page helpful?

JCL

On this page

JCL analysis is available starting in Enterprise Edition and supported by SonarLint for Eclipse when running in Connected Mode.

Language-specific properties

You can discover and update JCL-specific analysis parameters in Administration > General Settings > Languages  > JCL

Source code extraction

To analyze your source code with SonarQube, you first need to extract it onto a filesystem. You can use your own tool or an open-source tool; SonarSource does not provide any connectors or source code extraction tools.

JCL source format

Depending on your extraction process, your JCL source files may include extra characters beyond the 72nd columns, and include the 8 additional characters up to column 80, or even go beyond that column.

When that happens, the parser will:

  • consider everything up to the 71st column as valid JCL code,
  • look at the character in the 72nd column, to determine whether a continuation is present or not,
  • consider everything beyond the 72nd column as an inline comment, even when the text goes beyond the 80th column.

Adding custom rules to SonarQube

Overview

To get started you can download a sample plugin or browse and clone it from GitHub. The sample is a fully working prototype plugin, that can be built and run in SonarQube.

The JCL analyzer parses the source code, creates an Abstract Syntax Tree (AST), and then walks through the entire tree. A coding rule can subscribe to be notified every time a node of a certain type is visited.

As soon as the coding rule is notified, it can navigate the tree around the node (up and down) and raise issues if necessary.

Prerequisites

The following tools and artifacts are required for the following steps.

  • JDK 17
  • Maven
  • sonar-jcl-plugin 1.2+

Setup

Writing new JCL coding rules requires the following steps:

  1. Create a Maven project containing a new standard SonarQube plugin.
  2. Derive a custom plugin class from the plugin class.
  3. Define the rules via a repository of custom rules for the plugin.
  4. Implement the rules, writing as many custom rules as needed.
  5. Test the rules using the provided test kit.
  6. Add the rules to SonarQube by generating the jar file for SonarQube and deploying it.

Each step is described in detail in the sections down below.

Step 1: Create the Maven project

You should first create a Maven project to host the JCL custom plugin.

Re-using the pom.xml from the custom rules JCL example is a good start.

The following dependencies need to be defined in the pom.xml:

  • sonar-plugin-api to get access to SonarQube APIs.
  • sonar-jcl-plugin to use the APIs of the JCL plugin.

The plugin should also:

  • have testing dependencies, such as junit
  • reference the sonar-packaging-maven-plugin, to be able to pack the plugin into a format compatible with SonarQube, with the following configuration
    • sonarlintSupported set to true, so that custom rules defined in this plugin will be visible in SonarLint
    • requiredPlugins set to jcl:${version.jclPlugin}, to establish the requirement of the base JCL plugin
    • requiredForLanguages set to jcl , to establish the link between JCL files and this plugin

Step 2: Derive a custom plugin class from the plugin class

The entry point of the custom plugin is a class that implements org.sonar.api.Plugin and lists the SonarQube extensions required by the plugin. 

This list should contain the rules definition created in the next step.

An example of such a class is provided by the MyJclCustomPlugin.java file in the custom rules JCL example.

Step 3: Define the rules

One class in the Maven project should extend com.sonarsource.jcl.api.CustomRulesDefinition, in order to provide information about the custom rules that you’ll implement in the next step.

A complete example of such a class is provided by the MyJclCustomRulesDefinition.java file in the custom rules JCL example.

It should list the classes of the custom rules.

@Override
public List<Class<?>> checkClasses() {
  return List.of(MyCustomRule.class);
}

It should use the SonarQube API to define the metadata of these rules, such as name, HTML description, default impact, the Clean Code Attribute, and optional tags. 

NewRepository repository = context.createRepository(REPOSITORY_KEY, "jcl")
  .setName("My custom JCL repository");
NewRule rule = repository.createRule(DataStructureNamingConventionCheck.RULE_KEY)
  .setName("This is the title of my rule")
  .setHtmlDescription("This is the HTML description of my rule")
  .addDefaultImpact(SoftwareQuality.MAINTAINABILITY, Severity.HIGH)
  .setCleanCodeAttribute(CleanCodeAttribute.CLEAR)
  .addTags("confusing");
rule.setDebtRemediationFunction(
rule.debtRemediationFunctions().constantPerIssue("10min"));
repository.done();

The class should be registered as an extension in the Plugin defined in the previous step. 

@Override
public void define(Context context) {
  context.addExtension(MyJclCustomRulesDefinition.class);
}

Step 4: Implement the rules

You’ll need to implement every rule defined in the repository.

The MyCustomRule.java file from the custom rules JCL example provides a template of a simple JCL rule.

Each rule needs to be defined in a class which:

  • implements com.sonarsource.jcl.api.checks.JclCheck 
  • has an org.sonar.check.Rule annotation to define the key of the rule
  • is added to the repository registered in the Plugin class
@Rule(key = MyCustomRule.RULE_KEY)
public class MyCustomRule implements JclCheck {


  public static final String RULE_KEY = "Rule1";


  @Override
  public void init(InitContext context) {
    context.register(ExecStatementTree.class, (ctx, exec) -> {
      SyntaxToken name = exec.name();
      if (name != null && !name.value().startsWith("STEP")) {
        ctx.reportIssue(name, "EXEC statement names must start with 'STEP'");
      }
    });
  }
}

Step 5: Test the rules

The example project contains an example test class and the associated JCL file.

It's possible to write unit tests for custom rules using com.sonarsource.jcl.checks.testkit.JclVerifier. This utility class executes a custom rule against a given JCL test file. 

@Test
void test() {
  JclVerifier.verify("src/test/resources/checks/stepname.jcl", new MyCustomRule());
}

The JCL test file should contain comments denoting lines where issues should be expected.

//MYJOB JOB ,MSGLEVEL=1
//ASTEP1 EXEC PGM=IEFBR14 Noncompliant
//ASTEP EXEC PGM=IEFBR14 Noncompliant {{EXEC names must start with 'STEP'}}
//* Noncompliant@+1 {{EXEC names must start with 'STEP'}}
//NOSTEP EXEC PGM=IEFBR14
//STEP3 EXEC PGM=IEFBR14 

If the line ends with a "Noncompliant" inline comment field, JclVerifier expects an issue on that line, with any message.

If the line ends with a "Noncompliant {{the message}}" inline comment field, JclVerifier expects an issue on that line and checks that the issue message is "the message".

However, the recommended way of asserting a long message is to write the comment on a dedicated comment statement (i.e. starting with "//*"). That will help prevent issues with comment continuations when long messages need to be asserted and the 72nd character of the line is not whitespace.

Notation is also provided to assert issue location, as well as secondary locations and messages. 

You can refer to this page for more comprehensive examples of assertions, in the context of a C-like language.

Step 6: Add the rules to SonarQube

Once the coding rules have been implemented and tested, you need to perform the following steps.

  • Build the Maven project by running mvn install from the project directory. This will generate a SonarQube plugin jar file in the target directory.
  • Add your newly created jar into the $SONARQUBE_HOME/extensions/plugins directory.
  • Restart the SonarQube server.

If you now look at the JCL quality profiles, you will find the new coding rules defined in the previous step. Don’t forget to activate it. Run an analysis on a repository of JCL files, and you should find that issues are reported on those files.

More advanced features are documented in the API Javadoc.

© 2008-2024 SonarSource SA. All rights reserved. SONAR, SONARSOURCE, SONARLINT, SONARQUBE, SONARCLOUD, and CLEAN AS YOU CODE are trademarks of SonarSource SA.

Creative Commons License