SonarDelphi v1.0.0 released!

We are pleased to announce the release of SonarDelphi v1.0.0.

SonarDelphi is a free and open-source Delphi language plugin for the SonarQube code quality platform.

GitHub: https://github.com/integrated-application-development/sonar-delphi
Release: https://github.com/integrated-application-development/sonar-delphi/releases/tag/v1.0.0

Background

If you’re thinking “I’ve seen this before”, you’re probably right!

  • SonarDelphi was originally open-sourced by Sabre Airline Solutions in 2012.
  • It’s bounced from maintainer to maintainer on GitHub (including Embarcadero).
  • This project is a greatly improved version that has been actively developed (and extensively rewritten) by IntegraDev for the last 4 years.

Features

  • Powerful semantic analysis
  • 120+ analysis rules
  • Custom rules via templates or a programmatic java API
  • Import NUnit test reports (compatible with DUnitX)
  • Import test coverage reports (compatible with DelphiCodeCoverage)

Feedback and contributions are welcome!

2 Likes

Great, but since most Delphi Developers are likely not very familiar with SonarCube and static code analysis at all it would be nice to show some demonstration. I guess only a few people would sign up for the SonarCube trial to check out the Delphi plugin.

You could run some open-source project through it (I am not even saying it has to be mine :smile: but I don’t mind all the embarrassment that it might reveal) and show us some of its results.

Hi Stefan,

That’s a great point. :slight_smile:
We’re actually running the plugin against various open-source libraries to shake out any bugs/false-positives. I’ll add Spring4D 2.0 to the list!

To anyone who’s unfamiliar - there’s no need to sign up for a trial or anything of the sort. SonarQube has a totally free Community Edition.
You can get it here: SonarQube Free & Open Source Community Edition

3 Likes

The SonarDelphi plugin is now available through the SonarQube Marketplace.

This makes installation even simpler:

After that, you just need to configure your project properties. (See CONFIGURATION)

1 Like

Looks like the scanner has a lot of work ahead - I got like 22k issues of which most looked like parsing errors and mistakenly taking parameterless const or var parameters as global variables telling me I should stick to the naming convention of prefixing them with a G :joy:

Guess Spring4D again will be a nice test suite for other tools :wink:

Maybe I am running the scan from the wrong folder but when I run from the Packages\Delphi12 folder is just scans the dpk files - but it should find all source files as they are referenced with their relative patch in a dpk.

Hi Stefan,

I got like 22k issues of which most looked like parsing errors and mistakenly taking parameterless const or var parameters as global variables telling me I should stick to the naming convention of prefixing them with a G

The VariableName issues you’re getting are actually because the names are not PascalCase.

  • The parser isn’t getting confused here.
  • We’ll adjust the rule description for better clarity. (I’ve raised an issue)

Guess Spring4D again will be a nice test suite for other tools :wink:

You’re right about that! Spring4D contains a lot of interesting constructs - some of which are pretty confusing to a static analysis engine.

For example, your usage of the undocumented &&op_* class functions in record helpers is quite evil and obscure. I tip my hat to you! :wink:

Maybe I am running the scan from the wrong folder…

No worries, here’s a sonar-project.properties file to place at the root of your repository. You can then run sonar-scanner from there.

sonar.projectKey=spring4d
sonar.sourceEncoding=windows-1252
sonar.projectBaseDir=.

sonar.sources=Source,Tests
sonar.delphi.searchPath=Source

# Configured for Delphi 11
sonar.delphi.installationPath=C:/Program Files (x86)/Embarcadero/Studio/22.0
sonar.delphi.compilerVersion=VER350

Looks like the scanner has a lot of work ahead

Of course, and you can help!
We’re continuously improving the analyzer, so please raise a GitHub Issue if you find any problems. :slight_smile:

Thanks that got me a bit further and it looked like it churned on the source files now but now it chokes on something else - I slightly changed the properties file to use utf-8 as encoding (because actually, they are ut8), removed the Tests directory and configured for Delphi 12.

This is the output:

PS C:\Users\sglienke\OneDrive\Documents\Embarcadero\Studio\Libraries\spring4d> C:\sonar-scanner-5.0.1.3006-windows\bin\sonar-scanner.bat -D"sonar.host.url=http://localhost:9000" -D"sonar.token=sqp_9e34b79bb165d468c3a7b8a5573f752bdb395aaa"
INFO: Scanner configuration file: C:\sonar-scanner-5.0.1.3006-windows\bin\..\conf\sonar-scanner.properties
INFO: Project root configuration file: C:\Users\sglienke\OneDrive\Documents\Embarcadero\Studio\Libraries\spring4d\sonar-project.properties
INFO: SonarScanner 5.0.1.3006
INFO: Java 17.0.7 Eclipse Adoptium (64-bit)
INFO: Windows 11 10.0 amd64
INFO: User cache: C:\Users\sglienke\.sonar\cache
INFO: Analyzing on SonarQube server 10.3.0.82913
INFO: Default locale: "de_DE", source code encoding: "utf-8"
INFO: Load global settings
INFO: Load global settings (done) | time=34ms
INFO: Server id: 147B411E-AYv-1yiBCDRj3k1Ntklw
INFO: User cache: C:\Users\sglienke\.sonar\cache
INFO: Load/download plugins
INFO: Load plugins index
INFO: Load plugins index (done) | time=16ms
INFO: Load/download plugins (done) | time=60ms
INFO: Process project properties
INFO: Process project properties (done) | time=10ms
INFO: Execute project builders
INFO: Execute project builders (done) | time=1ms
INFO: Project key: spring4d
INFO: Base dir: C:\Users\sglienke\OneDrive\Documents\Embarcadero\Studio\Libraries\spring4d
INFO: Working dir: C:\Users\sglienke\OneDrive\Documents\Embarcadero\Studio\Libraries\spring4d\.scannerwork
INFO: Load project settings for component key: 'spring4d'
INFO: Load project settings for component key: 'spring4d' (done) | time=12ms
INFO: Load quality profiles
INFO: Load quality profiles (done) | time=51ms
INFO: Load active rules
INFO: Load active rules (done) | time=1202ms
INFO: Load analysis cache
INFO: Load analysis cache (262 bytes) | time=8ms
INFO: Load project repositories
INFO: Load project repositories (done) | time=11ms
INFO: Indexing files...
INFO: Project configuration:
INFO: 180 files indexed
INFO: 0 files ignored because of scm ignore settings
INFO: Quality profile for delphi: Sonar way
INFO: Quality profile for php: Sonar way
INFO: ------------- Run sensors on module spring4d
INFO: Load metrics repository
INFO: Load metrics repository (done) | time=25ms
INFO: Sensor JaCoCo XML Report Importer [jacoco]
INFO: 'sonar.coverage.jacoco.xmlReportPaths' is not defined. Using default locations: target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml
INFO: No report imported, no coverage information will be imported by JaCoCo XML Report Importer
INFO: Sensor JaCoCo XML Report Importer [jacoco] (done) | time=2ms
INFO: Sensor CSS Rules [javascript]
INFO: No CSS, PHP, HTML or VueJS files are found in the project. CSS analysis is skipped.
INFO: Sensor CSS Rules [javascript] (done) | time=0ms
INFO: Sensor C# Project Type Information [csharp]
INFO: Sensor C# Project Type Information [csharp] (done) | time=2ms
INFO: Sensor C# Analysis Log [csharp]
INFO: Sensor C# Analysis Log [csharp] (done) | time=40ms
INFO: Sensor C# Properties [csharp]
INFO: Sensor C# Properties [csharp] (done) | time=0ms
INFO: Sensor HTML [web]
INFO: Sensor HTML [web] (done) | time=29ms
INFO: Sensor DelphiSensor [communitydelphi]
INFO: Platform: WINDOWS
INFO: Architecture: X86
INFO: Compiler version: 36.0
INFO: Indexing 0 dproj file(s) and 0 groupproj file(s)...
INFO: Conditional defines: [ASSEMBLER, DCC, CPU386, CPUX86, UNICODE, MSWINDOWS, CPU32BITS, NATIVECODE, CONSOLE, WIN32, VER360, UNDERSCOREIMPORTNAME, CONDITIONALEXPRESSIONS]
INFO: Indexing System unit...
INFO: Indexing SysInit unit...
INFO: 176 source files to be indexed
INFO: 15/176 files indexed, current file: C:\Users\sglienke\OneDrive\Documents\Embarcadero\Studio\Libraries\spring4d\Source\Core\Container\Spring.Container.Core.pas
INFO: 22/176 files indexed, current file: C:\Users\sglienke\OneDrive\Documents\Embarcadero\Studio\Libraries\spring4d\Source\Base\Collections\Spring.Collections.pas
WARN: Ambiguous declarations could not be resolved
[Occurrence] RegisterType [441,12] <Spring.Container>java.util.stream.ReferencePipeline$3@735c49cc
WARN: Ambiguous declarations could not be resolved
[Occurrence] RegisterType [459,12] <Spring.Container>java.util.stream.ReferencePipeline$3@24411981
INFO: 176/176 source files have been indexed
INFO: 176 source files to be analyzed
ERROR: Error occurred while running DelphiCpdExecutor on file: Spring.pas
java.lang.IllegalArgumentException: Unable to register token in file Source/Base/Spring.pas
        at org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens.addToken(DefaultCpdTokens.java:69)
        at au.com.integradev.delphi.executor.DelphiCpdExecutor.handleToken(DelphiCpdExecutor.java:44)
        at au.com.integradev.delphi.executor.DelphiTokenExecutor.execute(DelphiTokenExecutor.java:31)
        at au.com.integradev.delphi.executor.DelphiMasterExecutor.executeExecutor(DelphiMasterExecutor.java:74)
        at au.com.integradev.delphi.executor.DelphiMasterExecutor.execute(DelphiMasterExecutor.java:52)
        at au.com.integradev.delphi.DelphiSensor.executeOnFiles(DelphiSensor.java:144)
        at au.com.integradev.delphi.DelphiSensor.execute(DelphiSensor.java:83)
        at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:64)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:88)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:61)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:79)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:61)
        at org.sonar.scanner.scan.SpringModuleScanContainer.doAfterStart(SpringModuleScanContainer.java:82)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:201)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:180)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scan(SpringProjectScanContainer.java:398)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scanRecursively(SpringProjectScanContainer.java:394)
        at org.sonar.scanner.scan.SpringProjectScanContainer.doAfterStart(SpringProjectScanContainer.java:363)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:201)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:180)
        at org.sonar.scanner.bootstrap.SpringGlobalContainer.doAfterStart(SpringGlobalContainer.java:139)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:201)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:180)
        at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:71)
        at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:65)
        at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
        at jdk.proxy1/jdk.proxy1.$Proxy0.execute(Unknown Source)
        at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189)
        at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138)
        at org.sonarsource.scanner.cli.Main.execute(Main.java:126)
        at org.sonarsource.scanner.cli.Main.execute(Main.java:81)
        at org.sonarsource.scanner.cli.Main.main(Main.java:62)
Caused by: java.lang.IllegalArgumentException: 152 is not a valid line offset for pointer. File Source/Base/Spring.pas has 16 character(s) at line 1175
        at org.sonar.api.utils.Preconditions.checkArgument(Preconditions.java:43)
        at org.sonar.api.batch.fs.internal.DefaultInputFile.checkValid(DefaultInputFile.java:374)
        at org.sonar.api.batch.fs.internal.DefaultInputFile.newPointer(DefaultInputFile.java:307)
        at org.sonar.api.batch.fs.internal.DefaultInputFile.newRange(DefaultInputFile.java:323)
        at org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens.addToken(DefaultCpdTokens.java:67)
        ... 36 common frames omitted

INFO: Continuing with next executor.
ERROR: Error occurred while running DelphiHighlightExecutor on file: Spring.pas
java.lang.IllegalArgumentException: Unable to highlight file Source/Base/Spring.pas
        at org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting.highlight(DefaultHighlighting.java:85)
        at org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting.highlight(DefaultHighlighting.java:37)
        at au.com.integradev.delphi.executor.DelphiHighlightExecutor.handleToken(DelphiHighlightExecutor.java:49)
        at au.com.integradev.delphi.executor.DelphiTokenExecutor.execute(DelphiTokenExecutor.java:31)
        at au.com.integradev.delphi.executor.DelphiMasterExecutor.executeExecutor(DelphiMasterExecutor.java:74)
        at au.com.integradev.delphi.executor.DelphiMasterExecutor.execute(DelphiMasterExecutor.java:52)
        at au.com.integradev.delphi.DelphiSensor.executeOnFiles(DelphiSensor.java:144)
        at au.com.integradev.delphi.DelphiSensor.execute(DelphiSensor.java:83)
        at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:64)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:88)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:61)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:79)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:61)
        at org.sonar.scanner.scan.SpringModuleScanContainer.doAfterStart(SpringModuleScanContainer.java:82)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:201)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:180)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scan(SpringProjectScanContainer.java:398)
        at org.sonar.scanner.scan.SpringProjectScanContainer.scanRecursively(SpringProjectScanContainer.java:394)
        at org.sonar.scanner.scan.SpringProjectScanContainer.doAfterStart(SpringProjectScanContainer.java:363)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:201)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:180)
        at org.sonar.scanner.bootstrap.SpringGlobalContainer.doAfterStart(SpringGlobalContainer.java:139)
        at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:201)
        at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:180)
        at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:71)
        at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:65)
        at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
        at jdk.proxy1/jdk.proxy1.$Proxy0.execute(Unknown Source)
        at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189)
        at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138)
        at org.sonarsource.scanner.cli.Main.execute(Main.java:126)
        at org.sonarsource.scanner.cli.Main.execute(Main.java:81)
        at org.sonarsource.scanner.cli.Main.main(Main.java:62)
Caused by: java.lang.IllegalArgumentException: 152 is not a valid line offset for pointer. File Source/Base/Spring.pas has 16 character(s) at line 1175
        at org.sonar.api.utils.Preconditions.checkArgument(Preconditions.java:43)
        at org.sonar.api.batch.fs.internal.DefaultInputFile.checkValid(DefaultInputFile.java:374)
        at org.sonar.api.batch.fs.internal.DefaultInputFile.newPointer(DefaultInputFile.java:307)
        at org.sonar.api.batch.fs.internal.DefaultInputFile.newRange(DefaultInputFile.java:323)
        at org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting.highlight(DefaultHighlighting.java:83)
        ... 37 common frames omitted

INFO: Continuing with next executor.
INFO: 104/176 files analyzed, current file: C:\Users\sglienke\OneDrive\Documents\Embarcadero\Studio\Libraries\spring4d\Source\Extensions\Utils\Spring.Utils.pas
INFO: 176/176 source files have been analyzed
INFO: Sensor DelphiSensor [communitydelphi] (done) | time=39484ms
INFO: Sensor DelphiCoverageSensor [communitydelphi]
INFO: Adding coverage reports.
INFO: No coverage reports specified (see 'sonar.delphi.coverage.reportPaths' property)
INFO: Sensor DelphiCoverageSensor [communitydelphi] (done) | time=0ms
INFO: Sensor Delphi NUnit Sensor [communitydelphi]
INFO: NUnit sensor execute...
INFO: No NUnit report directories specified (see 'sonar.delphi.nunit.reportPaths' property)
INFO: Sensor Delphi NUnit Sensor [communitydelphi] (done) | time=1ms
INFO: Sensor PHP sensor [php]
INFO: Starting PHP symbol indexer
INFO: 2 source files to be analyzed
INFO: 2/2 source files have been analyzed
INFO: Cached information of global symbols will be used for 0 out of 2 files. Global symbols were recomputed for the remaining files.
INFO: Starting PHP rules
INFO: 2 source files to be analyzed
INFO: 2/2 source files have been analyzed
INFO: The PHP analyzer was able to leverage cached data from previous analyses for 0 out of 2 files. These files were not parsed.
INFO: Sensor PHP sensor [php] (done) | time=103ms
INFO: Sensor Analyzer for "php.ini" files [php]
INFO: Sensor Analyzer for "php.ini" files [php] (done) | time=2ms
INFO: Sensor PHPUnit report sensor [php]
INFO: No PHPUnit tests reports provided (see 'sonar.php.tests.reportPath' property)
INFO: No PHPUnit coverage reports provided (see 'sonar.php.coverage.reportPaths' property)
INFO: Sensor PHPUnit report sensor [php] (done) | time=1ms
INFO: Sensor TextAndSecretsSensor [text]
INFO: 178 source files to be analyzed
INFO: 178/178 source files have been analyzed
INFO: Sensor TextAndSecretsSensor [text] (done) | time=2442ms
INFO: Sensor VB.NET Project Type Information [vbnet]
INFO: Sensor VB.NET Project Type Information [vbnet] (done) | time=1ms
INFO: Sensor VB.NET Analysis Log [vbnet]
INFO: Sensor VB.NET Analysis Log [vbnet] (done) | time=6ms
INFO: Sensor VB.NET Properties [vbnet]
INFO: Sensor VB.NET Properties [vbnet] (done) | time=0ms
INFO: Sensor IaC Docker Sensor [iac]
INFO: 0 source files to be analyzed
INFO: 0/0 source files have been analyzed
INFO: Sensor IaC Docker Sensor [iac] (done) | time=29ms
INFO: ------------- Run sensors on project
INFO: Sensor Analysis Warnings import [csharp]
INFO: Sensor Analysis Warnings import [csharp] (done) | time=1ms
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=1ms
INFO: CPD Executor 4 files had no CPD blocks
INFO: CPD Executor Calculating CPD for 173 files
INFO: CPD Executor CPD calculation finished (done) | time=112ms
INFO: Analysis report generated in 155ms, dir size=9.7 MB
INFO: Analysis report compressed in 396ms, zip size=2.3 MB
INFO: Analysis report uploaded in 41ms
INFO: ANALYSIS SUCCESSFUL, you can find the results at: http://localhost:9000/dashboard?id=spring4d
INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
INFO: More about the report processing at http://localhost:9000/api/ce/task?id=AYv-6jR1xrBsIcdgHneQ
INFO: Analysis total time: 48.758 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 49.346s
INFO: Final Memory: 43M/240M
INFO: ------------------------------------------------------------------------

Okay it produced something - but again, like hundreds and thousands of obviously false positives.

Example:

Like, no? That method is later implemented via interface.

Or this one:

image

Yeah, clearly I am not using that local variable - I am just assigning to it in the very first line :joy:

I could go on but I think you get the idea - don’t get me wrong - this looks promising but currently it does not provide any value with all the false positives.

I also did not find a way to turn off or modify the naming conventions because I know I name things a little different from classic Delphi code by using camelCase for parameters and local variables instead of PascalCase.
Edit: Nevermind, found it - extend and then in the child profile I can change :+1:

P.S. The good thing is I have only 1 vulnerability in my code which is this one :wink:

However after turning some of the noisy ones off there are some interesting ones - I am usually an “Assigned” user but apparently there are still like 130ish places that don’t :sweat_smile:
And most of the CognitiveComplexityRoutine are rather accurate - there are quite a few functions I would have split in smaller pieces if the Delphi compiler would properly inline :roll_eyes:

Already asked my coworker to put up the docker container and plug it into our self hosted gitlab instance - now that will be some fun :joy:

1 Like

Hi Stefan,

java.lang.IllegalArgumentException: Unable to highlight file Source/Base/Spring.pas

java.lang.IllegalArgumentException: Unable to register token in file Source/Base/Spring.pas

Good news, these errors are already fixed in master. (see issue #88)
You can build from master if you want those now, but otherwise the fix will be in the next release.

image

Yeah, clearly I am not using that local variable - I am just assigning to it in the very first line :joy:

The analyzer can see the assignment on line 1251, but the rule intentionally tries to catch cases where it thinks the variable is only assigned and never accessed.

Looks like the analyzer is getting confused by the hard-casted pointer arithmetic on the following line and not registering the variable access properly.

We’ll look into that, thanks. :+1:
(see issue #100)

However after turning some of the noisy ones off there are some interesting ones - I am usually an “Assigned” user but apparently there are still like 130ish places that don’t :sweat_smile:
And most of the CognitiveComplexityRoutine are rather accurate - there are quite a few functions I would have split in smaller pieces if the Delphi compiler would properly inline :roll_eyes:

Already asked my coworker to put up the docker container and plug it into our self hosted gitlab instance - now that will be some fun :joy:

I’m happy to hear that you’re getting some value out of the analysis!

Naturally, we’ll continue to improve the analysis engine based on feedback from users.
We’re trying to centralize feedback on GitHub issues wherever possible, and we also accept pull requests.

Scanning big and varied codebases is quite valuable for identifying potential problems with the analyzer. SonarDelphi has scanned codebases of several million lines, but Spring4D is quite a large and interesting library with a lot of potential for uncovering subtle issues and helping us make the analysis engine more robust.

Following from that, I’d very much appreciate if you raise issues (and if interested, open PRs) for any teething problems you encounter as you settle into using the tool internally.

Hi @sglienke,

We’re having some trouble reproducing this one:
image

What we’ve done is:

  • Changed the encoding property to utf-8
  • Removed Tests from sources
  • Installed Delphi 12 and configured sonar properties

We’ve tried scanning:

  • latest master
  • latest develop

In both cases, the issue is not raised.
What do you think, are we missing something about your setup/environment? :thinking:

No, that is exactly what I have done using the develop commit that was two commits ahead of master.

Would you mind generating a debug log file by running sonar-scanner -X | tee sonar.log, and sending it through to me?

Hi Stefan,

Thanks for sending that debug log through to me.
Alright, let’s take a look…

Problem

The analyzer isn’t picking up any of the project files in the Packages folder:

10:39:22.998 INFO: Indexing 0 dproj file(s) and 0 groupproj file(s)...

Since none of the project files are being indexed, the analyzer hasn’t read any of the unit scope names (including System), so it’s failing to resolve any standard library import where the unit scope has been omitted.

10:39:24.455 DEBUG: 				X Windows **Failed to locate unit**
10:39:24.455 DEBUG: 				X Classes **Failed to locate unit**
10:39:24.455 DEBUG: 				X Diagnostics **Failed to locate unit**
10:39:24.455 DEBUG: 				X Generics.Collections **Failed to locate unit**
10:39:24.455 DEBUG: 				X Generics.Defaults **Failed to locate unit**
10:39:24.455 DEBUG: 				X Rtti **Failed to locate unit**
10:39:24.455 DEBUG: 				X SyncObjs **Failed to locate unit**
10:39:24.455 DEBUG: 				X SysUtils **Failed to locate unit**
10:39:24.455 DEBUG: 				X TimeSpan **Failed to locate unit**
10:39:24.455 DEBUG: 				X Types **Failed to locate unit**
10:39:24.455 DEBUG: 				X TypInfo **Failed to locate unit**
10:39:24.455 DEBUG: 				X Variants **Failed to locate unit**

As a result, you’re missing all of the symbol/type information from most of your standard library imports.

Solution

This is the easy part - we just need to add a project file to sonar.sources.
Let’s add the Delphi 12 .groupproj, since that’s the version of Delphi you’re running analysis against.

Here’s an updated sonar-project.properties file:

sonar.projectKey=spring4d
sonar.sourceEncoding=utf-8
sonar.projectBaseDir=.

sonar.sources=Source,Packages/Delphi12/Spring4D.groupproj

sonar.delphi.installationPath=C:/Program Files (x86)/Embarcadero/Studio/23.0
sonar.delphi.compilerVersion=VER360

sonar.php.exclusions=**/*.inc

I hope that helps. :slight_smile:

Slowly getting somewhere :smiley:

That drop of almost 20k messages was disabling the "stuff has to be named PascalCase which I don’t adhere to for parameter names and local variables :innocent:

Still a lot to do - though some hundreds or even thousands are possibly false positives which I already reported:

1 Like
  • That drop of almost 20k messages was disabling the "stuff has to be named PascalCase which I don’t adhere to for parameter names and local variables :innocent:

Unbelievable, 20k ‘humans’ thought to make a message about something that a) the compiler doesn’t care about, b) doesn’t affect the perception/interpretation by a real human and c) results in a massive amount of extra work to create. Should send them to the naughty corner.

The SonarDelphi analyzer has several rules that help you adhere to the object pascal style guide, and the VariableName rule is one of them.

If you want consistency in your codebase, it makes a lot of sense.

Stefan clearly want consistency in his codebase too, he just likes a different naming convention. :slight_smile:

1 Like

Speaking of which - is it possible to modify the VariableName rule so it requires camelCase instead of PascalCase?

Hi @sglienke,

There are no plans to introduce alternative naming conventions in the core analysis rules.

However, SonarDelphi offers a powerful custom rules API. Custom rules are quite easy to implement and have access to the same APIs as rules in the core analyzer.

I went ahead and threw together a quick spring-sonar-delphi project with a custom spring-delphi:VariableName rule. I believe this rule should match your naming convention for local variables and parameter names.

You can deploy this spring-sonar-delphi plugin alongside the core sonar-delphi plugin.
spring-sonar-delphi.zip (58.0 KB)

For further instructions, see the README.

2 Likes