diff --git a/.gitignore b/.gitignore index e271ac907..c0ad07982 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # ---- Maven target/ +*.class # ---- IntelliJ IDEA *.iws diff --git a/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/CyclomaticComplexityRoutine.html b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/CyclomaticComplexityRoutine.html index 4de071740..823a2881a 100644 --- a/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/CyclomaticComplexityRoutine.html +++ b/delphi-checks/src/main/resources/org/sonar/l10n/delphi/rules/community-delphi/CyclomaticComplexityRoutine.html @@ -4,11 +4,64 @@
+ High cyclomatic complexity can lead to: +
++function ProcessValue(Value: Integer; Mode: String): Integer; +begin + if Value > 0 then // +1 + begin + if Mode = 'ADD' then // +1 + Result := Value + 10 + else if Mode = 'MUL' then // +1 + Result := Value * 2 + else if Mode = 'DIV' then // +1 + Result := Value div 2 + else + Result := Value; + end + else if Value < 0 then // +1 + Result := -Value + else + Result := 0; +end; +// Cyclomatic Complexity = 6 +
Refactor this routine so it runs more linearly, for example by reducing the number of times - the control flow splits. + the control flow splits. Consider using polymorphism, strategy pattern, or breaking the routine + into smaller, more focused methods.
++function ProcessValue(Value: Integer; Mode: String): Integer; +begin + if Value <= 0 then + Exit(Abs(Value)); + + Result := ApplyMode(Value, Mode); +end; + +function ApplyMode(Value: Integer; Mode: String): Integer; +begin + case Mode of + 'ADD': Result := Value + 10; + 'MUL': Result := Value * 2; + 'DIV': Result := Value div 2; + else + Result := Value; + end; +end; +
This visitor traverses the AST and collects metrics including: + * + *
This class holds various metrics gathered during AST traversal, including: + *
These metrics are used to assess code quality and complexity.
+ */
public static class Data {
private int classes;
private int routines;
@@ -73,6 +99,17 @@ public Set This class handles the configuration of SonarQube rules based on annotations found on rule
+ * classes, particularly {@link RuleTemplate} annotations.
+ */
public final class RuleTemplateAnnotationReader {
+
+ /**
+ * Updates rule definitions in the repository based on rule template annotations.
+ *
+ * @param repository the rules repository to update
+ * @param ruleClasses the list of rule classes to process
+ * @throws IllegalArgumentException if repository or ruleClasses is null
+ */
public void updateRulesByAnnotatedClass(
RulesDefinition.NewRepository repository, List This class provides convenient methods for parsing Delphi source code and creating mock
+ * configurations commonly used in unit tests.
+ */
public final class DelphiFileUtils {
private DelphiFileUtils() {
// Utility class
}
+ /**
+ * Parses the given lines of Delphi source code into a DelphiFile.
+ *
+ * This method creates a temporary file with the provided content and parses it using a mock
+ * configuration. The temporary file is automatically deleted when the JVM exits.
+ *
+ * @param lines the lines of Delphi source code to parse
+ * @return a parsed DelphiFile instance
+ * @throws UncheckedIOException if an I/O error occurs during file creation or writing
+ */
public static DelphiFile parse(String... lines) {
try {
- Path path = Files.createTempFile(null, ".pas");
+ Path path = Files.createTempFile("delphi-test-", ".pas");
Files.writeString(path, "\uFEFF" + StringUtils.join(lines, '\n'), StandardCharsets.UTF_8);
path.toFile().deleteOnExit();
return DelphiFile.from(path.toFile(), mockConfig());
} catch (IOException e) {
- throw new UncheckedIOException(e);
+ throw new UncheckedIOException("Failed to create temporary Delphi file for parsing", e);
}
}
+ /**
+ * Creates a mock DelphiFileConfig with default settings suitable for testing.
+ *
+ * The mock configuration includes:
+ *
+ * My stupid rule to avoid routine declaration This rule detects routine declarations that should be avoided according to coding standards.
+Routine declarations in certain contexts can lead to maintenance issues and reduced code readability.
+ *
+ *
+ * @return a mock DelphiFileConfig instance
+ */
public static DelphiFileConfig mockConfig() {
DelphiFileConfig mock = mock(DelphiFileConfig.class);
when(mock.getEncoding()).thenReturn(StandardCharsets.UTF_8.name());
diff --git a/docs/delphi-custom-rules-example/src/main/resources/org/sonar/l10n/delphi/rules/mycompany-delphi/RoutineDeclaration.html b/docs/delphi-custom-rules-example/src/main/resources/org/sonar/l10n/delphi/rules/mycompany-delphi/RoutineDeclaration.html
index 9d4c81b1a..73559848f 100644
--- a/docs/delphi-custom-rules-example/src/main/resources/org/sonar/l10n/delphi/rules/mycompany-delphi/RoutineDeclaration.html
+++ b/docs/delphi-custom-rules-example/src/main/resources/org/sonar/l10n/delphi/rules/mycompany-delphi/RoutineDeclaration.html
@@ -1,10 +1,16 @@
Why is this an issue?
-Noncompliant Code Example
-TO DO
+procedure MyProcedure(); forward; // Noncompliant - forward declaration usage
+
+function Calculate(X: Integer): Integer; external; // Noncompliant - external routine
Compliant Solution
-TO DO
+function Calculate(X: Integer): Integer; // Compliant - proper implementation
+begin
+ Result := X * 2;
+end;