All Downloads are FREE. Search and download functionalities are using the official Maven repository.

domain.RegistrarsGenerator Maven / Gradle / Ivy

The newest version!
/*
 * SonarQube JavaScript Plugin
 * Copyright (C) 2011-2025 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the Sonar Source-Available License for more details.
 *
 * You should have received a copy of the Sonar Source-Available License
 * along with this program; if not, see https://sonarsource.com/license/ssal/
 */
package domain;

import java.util.ArrayList;
import java.util.stream.Collectors;
import org.apache.commons.text.StringEscapeUtils;

public class RegistrarsGenerator {

  private final Logger logger;
  private final RuleRepository ruleRepository;
  private final FileSystem fileSystem;

  public RegistrarsGenerator(Logger logger, RuleRepository ruleRepository, FileSystem fileSystem) {
    this.logger = logger;
    this.ruleRepository = ruleRepository;
    this.fileSystem = fileSystem;
  }

  public void execute(
    String packageName,
    String languageKey,
    String compatibleLanguageKey,
    String repositoryKey,
    String targetDirectory,
    String profileName
  ) throws Exception {
    logger.log(String.format("Fetching rules for language %s", languageKey));

    var rules = ruleRepository
      .getRulesByLanguage(languageKey)
      .stream()
      .filter(rule -> rule.compatibleLanguages().contains(compatibleLanguageKey))
      .toList();

    // generate the repository factory
    logger.log(
      String.format(
        "Generating the \"%s\" repository factory for language \"%s\" to %s",
        repositoryKey,
        compatibleLanguageKey,
        targetDirectory
      )
    );

    var entryPointBuilder = new StringBuilder();

    var className = String.format("%sRepositoryRegistrar", repositoryKey);

    entryPointBuilder.append(
      String.format(
        """
        package %s;
        import org.sonar.api.server.rule.RulesDefinition;
        import org.sonar.api.SonarRuntime;
        import org.sonarsource.analyzer.commons.RuleMetadataLoader;
        import org.sonarsource.analyzer.commons.domain.*;
        import java.util.Map;
        import java.util.List;
        """,
        packageName
      )
    );
    entryPointBuilder.append(
      String.format(
        """
        public class %s implements RulesDefinition {
          protected RuleMetadataLoader ruleMetadataLoader;

          public %s(SonarRuntime sonarRuntime) {
            this.ruleMetadataLoader = new RuleMetadataLoader(sonarRuntime);
          }
        """,
        className,
        className
      )
    );

    for (var rule : rules) {
      entryPointBuilder.append(
        String.format(
          """
            private void register%s(NewRepository repository) {
          """,
          rule.name()
        )
      );

      var tags = rule.tags().stream().map(tag -> String.format("\"%s\"", tag));
      var remediationCode = "null";
      var remediation = rule.remediation();

      if (remediation != null) {
        var linearFactorCode = "null";
        var linearFactor = remediation.linearFactor();

        if (linearFactor != null) {
          linearFactorCode = String.format("\"%s\"", linearFactor);
        }

        var linearOffsetCode = "null";
        var linearOffset = remediation.linearOffset();

        if (linearOffset != null) {
          linearOffsetCode = String.format("\"%s\"", linearOffset);
        }

        var linearDescriptionCode = "null";
        var linearDescription = remediation.linearDescription();

        if (linearDescription != null) {
          linearDescriptionCode = String.format(
            "\"%s\"",
            StringEscapeUtils.escapeJava(linearDescription)
          );
        }

        remediationCode = String.format(
          """
          new RuleManifestRemediation() {
            public String func() {
              return "%s";
            }
            public String constantCost() {
              return "%s";
            }
            public String linearFactor() {
              return %s;
            }
            public String linearOffset() {
              return %s;
            }
            public String linearDescription() {
              return %s;
            }
          }""",
          remediation.function(),
          remediation.cost(),
          linearFactorCode,
          linearOffsetCode,
          linearDescriptionCode
        );
      }

      var parametersCodes = new ArrayList();

      for (var parameter : rule.parameters()) {
        parametersCodes.add(
          String.format(
            """
            new RuleManifestParameter() {
              public String defaultValue() {
                return "%s";
              }
              public String description() {
                return "%s";
              }
              public String names() {
                return "%s";
              }
              public String type() {
                return "%s";
              }
            }""",
            StringEscapeUtils.escapeJava(parameter.defaultValue()),
            StringEscapeUtils.escapeJava(parameter.description()),
            parameter.name(),
            parameter.type()
          )
        );
      }

      // code
      var codeCode = "null";
      var code = rule.code();

      if (code != null) {
        String impactsCode = code
          .impacts()
          .entrySet()
          .stream()
          .map(impact -> {
            return String.format("\"%s\", \"%s\"", impact.getKey(), impact.getValue());
          })
          .collect(Collectors.joining(", "));

        codeCode = String.format(
          """
          new RuleManifestCode() {
            public Map impacts() {
              return Map.of(%s);
            }
            public String attribute() {
              return "%s";
            }
          }""",
          impactsCode,
          rule.code().attribute()
        );
      }

      entryPointBuilder.append(
        String.format(
          """
            this.ruleMetadataLoader.createRuleFromRuleManifest(repository, new RuleManifest() {
              public RuleManifestCode code() {
                return %s;
              }
              public String defaultSeverity() {
                return "%s";
              }
              public String htmlDocumentation() {
                return "%s";
              }
              public String name() {
                return "%s";
              }
              public List parameters() {
                return List.of(%s);
              }
              public RuleManifestRemediation remediation() {
                return %s;
              }
              public String scope() {
                return "%s";
              }
              public String status() {
                return "%s";
              }
              public List tags() {
                return List.of(%s);
              }
              public String title() {
                return "%s";
              }
              public String type() {
                return "%s";
              }
            });
          """,
          codeCode,
          rule.defaultSeverity(),
          StringEscapeUtils.escapeJava(rule.htmlDocumentation()),
          rule.name(),
          String.join(",", parametersCodes),
          remediationCode,
          rule.scope(),
          rule.status(),
          tags.collect(Collectors.joining(",")),
          StringEscapeUtils.escapeJava(rule.title()),
          rule.type()
        )
      );

      entryPointBuilder.append("}\n");
    }

    entryPointBuilder.append(
      String.format(
        """
        public void define(Context context) {
          NewRepository repository = context.createRepository("%s", "%s").setName("SonarAnalyzer");
        """,
        repositoryKey,
        compatibleLanguageKey
      )
    );

    for (var rule : rules) {
      entryPointBuilder.append(
        String.format(
          """
          this.register%s(repository);
          """,
          rule.name()
        )
      );
    }

    entryPointBuilder.append(
      """
          repository.done();
        }
      }
      """
    );

    var entryPointFileName = this.fileSystem.resolve(targetDirectory, className + ".java");

    this.fileSystem.write(entryPointFileName, entryPointBuilder.toString());

    // generate the profile definition class
    logger.log(
      String.format(
        "Generating the \"%s\" profile definition for language \"%s\" to %s",
        profileName,
        compatibleLanguageKey,
        targetDirectory
      )
    );

    var profileDefinitionClassName = String.format("%sProfileRegistrar", repositoryKey);
    var profileDefinitionBuilder = new StringBuilder();

    profileDefinitionBuilder.append(
      String.format(
        """
        package %s;
        import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
        """,
        packageName
      )
    );

    profileDefinitionBuilder.append(
      String.format(
        "public class %s implements BuiltInQualityProfilesDefinition {\n",
        profileDefinitionClassName
      )
    );
    profileDefinitionBuilder.append("public void define(Context context) {\n");

    profileDefinitionBuilder.append(
      String.format(
        """
        var newProfile = context.createBuiltInQualityProfile(
              "%s",
              "%s"
            );
        """,
        profileName,
        compatibleLanguageKey
      )
    );

    for (var rule : rules) {
      if (rule.qualityProfiles().contains(profileName)) {
        profileDefinitionBuilder.append(
          String.format("newProfile.activateRule(\"%s\", \"%s\");", repositoryKey, rule.name())
        );
      }
    }

    profileDefinitionBuilder.append("newProfile.done();}}");

    var profileDefinitionFileName =
      this.fileSystem.resolve(targetDirectory, profileDefinitionClassName + ".java");

    this.fileSystem.write(profileDefinitionFileName, profileDefinitionBuilder.toString());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy