├── .gitignore
├── .gitmodules
├── .travis.yml
├── LICENSE
├── README.md
├── examples
├── .gitignore
├── example1-rules
│ ├── Example.sln
│ ├── Example
│ │ ├── Example.sqlproj
│ │ ├── TestTable.sql
│ │ └── sp_Get.sql
│ ├── README.md
│ ├── customRules
│ │ └── myExampleRepo.customRules
│ ├── sonar-project.properties
│ └── sqlcodeguardsettings.xml
├── example2-coverage
│ ├── README.md
│ ├── build
│ │ └── Coverage.opencoverxml
│ ├── runSqlCover.ps1
│ ├── sonar-project.properties
│ └── src
│ │ ├── Accelerator
│ │ └── IsExperimentReady.sql
│ │ ├── AlertParticleDiscovered.sql
│ │ ├── GetStatusMessage.sql
│ │ └── SendHiggsBosonDiscoveryEmail.sql
├── example3-full
│ ├── 00-installTools.ps1
│ ├── 01-executeDBChanges.ps1
│ ├── 02-runSonar.ps1
│ ├── README.md
│ ├── imgs
│ │ └── sonarDashboard.png
│ └── src
│ │ └── ExampleDatabase
│ │ ├── ExampleDatabase.sln
│ │ └── ExampleDatabase
│ │ ├── .gitignore
│ │ ├── Billing.sql
│ │ ├── Billing
│ │ ├── CustomerDiscounts.sql
│ │ ├── Customers.sql
│ │ ├── IsCustomerEligibleForDiscount.sql
│ │ └── Orders.sql
│ │ ├── BillingTests.sql
│ │ ├── BillingTests
│ │ ├── test that customer with more than 3 orders and total over 2000 can discount.sql
│ │ └── test that not existing customer can not get discount.sql
│ │ └── ExampleDatabase.sqlproj
└── example4-adhoc
│ ├── Example.sln
│ ├── Example
│ ├── Example.sqlproj
│ ├── TestTable.sql
│ └── sp_Get.sql
│ ├── README.md
│ ├── customRules
│ └── myExampleRepo.customRules
│ ├── sonar-project.properties
│ └── sqlcodeguardsettings.xml
├── scripts
├── index.js
└── package.json
└── sonar-tsql-plugin
├── .classpath
├── .gitignore
├── .project
├── pom.xml
└── src
├── main
├── antlr4
│ └── org
│ │ └── sonar
│ │ └── plugins
│ │ └── tsql
│ │ └── antlr4
│ │ └── tsql.g4
├── java
│ └── org
│ │ ├── antlr
│ │ └── tsql
│ │ │ ├── TSqlLexer.java
│ │ │ ├── TSqlLexer.tokens
│ │ │ ├── TSqlParser.java
│ │ │ ├── TSqlParser.tokens
│ │ │ ├── TSqlParserBaseListener.java
│ │ │ ├── TSqlParserBaseVisitor.java
│ │ │ ├── TSqlParserListener.java
│ │ │ └── TSqlParserVisitor.java
│ │ ├── opencover
│ │ ├── Class.java
│ │ ├── Classes.java
│ │ ├── CoverageSession.java
│ │ ├── File.java
│ │ ├── FileRef.java
│ │ ├── Files.java
│ │ ├── Method.java
│ │ ├── Methods.java
│ │ ├── Module.java
│ │ ├── Modules.java
│ │ ├── ObjectFactory.java
│ │ ├── SequencePoint.java
│ │ ├── SequencePoints.java
│ │ └── Summary.java
│ │ └── sonar
│ │ └── plugins
│ │ └── tsql
│ │ ├── Constants.java
│ │ ├── TSQLPlugin.java
│ │ ├── antlr
│ │ ├── AntlrContext.java
│ │ ├── CandidateNode.java
│ │ ├── CandidateRule.java
│ │ ├── CaseChangingCharStream.java
│ │ ├── IParsedNode.java
│ │ ├── PluginHelper.java
│ │ ├── issues
│ │ │ ├── CustomIssuesProvider.java
│ │ │ ├── FoundViolationsAnalyzer.java
│ │ │ └── NodesMatchingRulesProvider.java
│ │ ├── lines
│ │ │ ├── DefaultLinesProvider.java
│ │ │ └── ILinesProvider.java
│ │ ├── nodes
│ │ │ ├── INodesProvider.java
│ │ │ ├── NodeUsesProvider.java
│ │ │ ├── ParsedNode.java
│ │ │ └── matchers
│ │ │ │ ├── ABaseMatcher.java
│ │ │ │ ├── ClassNameMatcher.java
│ │ │ │ ├── DistanceMatcher.java
│ │ │ │ ├── IMatcher.java
│ │ │ │ ├── IParentMatcher.java
│ │ │ │ ├── IndexMatcher.java
│ │ │ │ ├── NodeNameAndOrClassMatcher.java
│ │ │ │ ├── ParentsMatcher.java
│ │ │ │ ├── RulesMatcher.java
│ │ │ │ ├── SameTextMatcher.java
│ │ │ │ └── TextNameMatcher.java
│ │ └── visitors
│ │ │ ├── AntlrHighlighter.java
│ │ │ ├── CComplexityVisitor.java
│ │ │ ├── ComplexityVisitor.java
│ │ │ ├── CustomRulesVisitor.java
│ │ │ ├── CustomTreeVisitor.java
│ │ │ ├── IParseTreeItemVisitor.java
│ │ │ └── SourceLinesMeasuresFiller.java
│ │ ├── checks
│ │ ├── CustomAllChecksProvider.java
│ │ ├── CustomPluginChecks.java
│ │ ├── CustomUserChecksProvider.java
│ │ └── custom
│ │ │ ├── ChildrenRules.java
│ │ │ ├── CompliantRulesCodeExamples.java
│ │ │ ├── Names.java
│ │ │ ├── ObjectFactory.java
│ │ │ ├── ParentRules.java
│ │ │ ├── Rule.java
│ │ │ ├── RuleDistanceIndexMatchType.java
│ │ │ ├── RuleImplementation.java
│ │ │ ├── RuleMatchType.java
│ │ │ ├── RuleMode.java
│ │ │ ├── RuleResultType.java
│ │ │ ├── SiblingsRules.java
│ │ │ ├── SqlRules.java
│ │ │ ├── TextCheckType.java
│ │ │ ├── TextToFind.java
│ │ │ ├── UsesRules.java
│ │ │ └── ViolatingRulesCodeExamples.java
│ │ ├── coverage
│ │ ├── CoveredLinesReport.java
│ │ ├── FileNamesMatcher.java
│ │ ├── ICoveragProvider.java
│ │ ├── NameNormalizer.java
│ │ └── SqlCoverCoverageProvider.java
│ │ ├── languages
│ │ ├── TSQLLanguage.java
│ │ ├── TSQLQualityProfile.java
│ │ ├── TSQLRules.java
│ │ └── keywords
│ │ │ ├── IKeywordsProvider.java
│ │ │ └── KeywordsProvider.java
│ │ ├── lines
│ │ ├── SourceLine.java
│ │ └── SourceLinesProvider.java
│ │ ├── predicates
│ │ └── AbsolutePathCaseInsensitivePredicate.java
│ │ ├── rules
│ │ ├── definitions
│ │ │ ├── BaseRulesDefinition.java
│ │ │ ├── CodeGuardRulesDefinition.java
│ │ │ ├── CustomPluginChecksRulesDefinition.java
│ │ │ ├── CustomUserChecksRulesDefinition.java
│ │ │ └── MsRulesDefinition.java
│ │ ├── files
│ │ │ ├── BaseReportsProvider.java
│ │ │ ├── CodeGuardExecutingReportsProvider.java
│ │ │ ├── FilesProvider.java
│ │ │ └── IReportsProvider.java
│ │ ├── issues
│ │ │ ├── CodeGuardIssues.java
│ │ │ ├── CodeGuardIssuesProvider.java
│ │ │ ├── DefaultIssuesFiller.java
│ │ │ ├── IIssuesFiller.java
│ │ │ ├── IIssuesProvider.java
│ │ │ ├── MsIssues.java
│ │ │ ├── MsIssuesProvider.java
│ │ │ └── TsqlIssue.java
│ │ └── parsers
│ │ │ ├── CodeGuardIssuesParser.java
│ │ │ ├── IIssuesParser.java
│ │ │ └── MsIssuesParser.java
│ │ └── sensors
│ │ ├── BaseTsqlExternalSensor.java
│ │ ├── BaseTsqlSensor.java
│ │ ├── CodeGuardIssuesLoaderSensor.java
│ │ ├── CoverageSensor.java
│ │ ├── CustomChecksSensor.java
│ │ └── MsIssuesLoaderSensor.java
└── resources
│ ├── config
│ └── sqlcodeguardsettings.xml
│ ├── rules
│ ├── cgsql-rules.xml
│ └── vssql-rules.xml
│ ├── schemas
│ ├── codeGuard.xsd
│ ├── coverage.xsd
│ ├── customRules.xsd
│ ├── sqlRules.xsd
│ └── visualStudio.xsd
│ ├── tsql.keywords
│ └── tsql.odbc.keywords
└── test
├── java
└── org
│ └── sonar
│ └── plugins
│ └── tsql
│ ├── antlr
│ ├── AntlrContextTest.java
│ ├── CustomChecksTest.java
│ ├── CustomRulesVerificationTest.java
│ ├── issues
│ │ └── FoundViolationsAnalyzerTest.java
│ ├── lines
│ │ └── DefaultLinesProviderTest.java
│ └── nodes
│ │ ├── NodeUsesProviderTest.java
│ │ ├── NodesMatchingRulesProviderTest.java
│ │ ├── ParsedNodeTest.java
│ │ └── matchers
│ │ ├── DistanceMatcherTest.java
│ │ ├── IndexMatcherTest.java
│ │ └── RulesMatcherTest.java
│ ├── coverage
│ └── FileNamesMatcherTest.java
│ ├── helpers
│ ├── AntlrUtils.java
│ ├── AntrlResult.java
│ ├── ClassesLister.java
│ ├── CustomRulesPrinter.java
│ ├── CustomSqlCodePrinter.java
│ ├── RulesHelperTool.java
│ └── TestNode.java
│ ├── languages
│ ├── TSQLLanguageTest.java
│ └── keywords
│ │ └── KeywordsProviderTest.java
│ ├── lines
│ └── SourceLinesProviderTest.java
│ ├── rules
│ ├── BaseReportsProviderTest.java
│ ├── CgSqlIssuesParserTest.java
│ ├── VsSqlIssuesParserTest.java
│ ├── definitions
│ │ └── CustomUserChecksProviderTest.java
│ └── files
│ │ └── FilesProviderTest.java
│ └── sensors
│ ├── BaseTsqlSensorTest.java
│ ├── CoverageSensorTest.java
│ ├── CustomChecksSensorTest.java
│ └── antlr4
│ ├── CComplexityVisitorTest.java
│ └── ComplexityVisitorTest.java
└── resources
├── cgSample.xml
├── coverage
├── Coverage.opencoverxml
├── TestCode.sql
├── [Accelerator].[AlertParticleDiscovered]
├── [Accelerator].[GetStatusMessage]
├── [Accelerator].[IsExperimentReady]
└── [Accelerator].[SendHiggsBosonDiscoveryEmail]
├── customRulesSample.xml
├── customRulesSample2.xml
├── finalCusomRulesSample.xml
├── testFiles
├── TestTable.sql
├── cursorFlow.sql
├── cursorFlow2.sql
├── scriptExample.sql
├── scriptExample2.sql
├── scriptExample3.sql
└── sp_Get.sql
└── vsSample.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 | .settings
14 | node_modules
15 | scripts/rules/*.html
16 | rules.xml
17 | scripts/package-lock.json
18 | examples/**/bin/Debug/**
19 | examples/**/obj/Debug/**
20 | examples/**/.scannerwork/**
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "grammars"]
2 | path = grammars
3 | url = https://github.com/antlr/grammars-v4.git
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | sudo: false
3 | install: true
4 |
5 | jdk:
6 | - oraclejdk8
7 |
8 | script:
9 | - cd sonar-tsql-plugin
10 | - ./mvnw clean install
11 |
12 | cache:
13 | directories:
14 | - $HOME/.m2
15 |
16 |
--------------------------------------------------------------------------------
/examples/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 | .settings
14 | node_modules
15 | scripts/rules/*.html
16 | rules.xml
17 | scripts/package-lock.json
18 |
--------------------------------------------------------------------------------
/examples/example1-rules/Example.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "Example", "Example\Example.sqlproj", "{1491DCE3-0018-487C-9B9B-F7EEA6C863F8}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
18 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Release|Any CPU.Build.0 = Release|Any CPU
19 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Release|Any CPU.Deploy.0 = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | EndGlobal
25 |
--------------------------------------------------------------------------------
/examples/example1-rules/Example/TestTable.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE [dbo].[TestTable]
2 | (
3 | [Id] INT NOT NULL PRIMARY KEY,
4 | [Name] NVARCHAR(MAX) NULL
5 | )
6 |
--------------------------------------------------------------------------------
/examples/example1-rules/Example/sp_Get.sql:
--------------------------------------------------------------------------------
1 | CREATE PROCEDURE [dbo].[sp_Get]
2 | @param1 int = 0,
3 | @param2 int
4 | AS
5 | BEGIN
6 | SELECT * FROM TestTable;
7 | EXEC ('SELECT 1');
8 | insert into dbo.test values (1,2);
9 |
10 | EXECUTE sp_executesql N'select 1';
11 |
12 | RETURN 0
13 | END
14 | -- kasldjaskjd
--------------------------------------------------------------------------------
/examples/example1-rules/README.md:
--------------------------------------------------------------------------------
1 | # Example T-SQL project
2 | In order to get results to sonar server please:
3 |
4 | - (Optional) If needed update path to SQL code guard on sonar server or add **sonar.tsql.cg.path** setting with path in sonar.properties file
5 | - (Optional) Build sample project with setting /p:RunSqlCodeAnalysis=true if not using other means for building:
6 | - msbuild /p:RunSqlCodeAnalysis=true
7 | - (Optional) Update sonar-project.properties file as needed
8 | - Run sonar scanner
9 |
10 | ## Using custom rules ##
11 | - (Optional) Please update file **myExampleRepo.customRules** in *customRules* directory with your custom rules
12 | - Copy **myExampleRepo.customRules** file to SonarQube's server known place, i.e. **C:\\sonar\\rules** folder
13 | - Set on server sonar **sonar.tsql.customrules.paths** setting to **C:\\sonar\\rules\\** or **C:\\sonar\\rules\\myExampleRepo.customRules**
14 | - Restart SonarQube server
15 | - Run sonar scanner
--------------------------------------------------------------------------------
/examples/example1-rules/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.projectKey=example1.tsql.project
2 | sonar.projectName=Example1: TSQL project
3 | sonar.projectVersion=1.0
4 | sonar.sources=Example
5 | sonar.sourceEncoding=UTF-8
6 | sonar.language=tsql
7 | ## not needed to specify if rules are placed in the same place as on sonar server. Can be relative or absolute path.
8 | sonar.tsql.customrules.paths=./customRules
9 | ## not needed to update if matches server settings
10 | #sonar.tsql.customrules.prefix=.customRules
11 |
--------------------------------------------------------------------------------
/examples/example2-coverage/README.md:
--------------------------------------------------------------------------------
1 | # Example project 2 #
2 | This project illustrates plugin's ability to report SQLCover coverage for a sample database taken from [https://tsqlt.org/](https://tsqlt.org/) installation. Coverage report is already saved at **build** folder. When you run sonar-scanner that report will be parsed and reported to Sonarqube.
--------------------------------------------------------------------------------
/examples/example2-coverage/build/Coverage.opencoverxml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gretard/sonar-tsql-plugin/aadb5598bbb183c12df997ee9f3e053f962ce0f7/examples/example2-coverage/build/Coverage.opencoverxml
--------------------------------------------------------------------------------
/examples/example2-coverage/runSqlCover.ps1:
--------------------------------------------------------------------------------
1 | . .\SQLCover.ps1
2 | $result = Get-CoverTSql ".\SQLCover.dll" "server=.;initial catalog=tSQLt_Example;integrated security=sspi;" "tSQLt_Example" "exec tSQLt.RunAll"
3 | $result
4 | Export-OpenXml $result "$PSScriptRoot\build"
--------------------------------------------------------------------------------
/examples/example2-coverage/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.projectKey=example2.tsql.project
2 | sonar.projectName=Example2: TSQL project
3 | sonar.projectVersion=1.1
4 | sonar.sources=src
5 |
6 | ##flag if you want to skip coverage reports
7 | ##sonar.tsql.sqlcover.skip=true
8 |
9 | ##By default plugin will try to find Coverage.opencoverxml file in the base dir, however you could specify it if needed to some absolute or reltive path
10 | ##sonar.tsql.sqlcover.report=./build/Coverage.opencoverxml
--------------------------------------------------------------------------------
/examples/example2-coverage/src/Accelerator/IsExperimentReady.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE FUNCTION Accelerator.IsExperimentReady()
3 | RETURNS BIT
4 | AS
5 | BEGIN
6 | DECLARE @NumParticles INT;
7 |
8 | SELECT @NumParticles = COUNT(1) FROM Accelerator.Particle;
9 |
10 | IF @NumParticles > 2
11 | RETURN 1;
12 |
13 | RETURN 0;
14 | END;
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/example2-coverage/src/AlertParticleDiscovered.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE Accelerator.AlertParticleDiscovered
3 | @ParticleDiscovered NVARCHAR(MAX)
4 | AS
5 | BEGIN
6 | IF @ParticleDiscovered = 'Higgs Boson'
7 | BEGIN
8 | EXEC Accelerator.SendHiggsBosonDiscoveryEmail 'particle-discovery@new-era-particles.tsqlt.org';
9 | END;
10 | END;
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/example2-coverage/src/GetStatusMessage.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE FUNCTION Accelerator.GetStatusMessage()
3 | RETURNS NVARCHAR(MAX)
4 | AS
5 | BEGIN
6 | DECLARE @NumParticles INT;
7 | SELECT @NumParticles = COUNT(1) FROM Accelerator.Particle;
8 | RETURN 'The Accelerator is prepared with ' + CAST(@NumParticles AS NVARCHAR(MAX)) + ' particles.';
9 | END;
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/example2-coverage/src/SendHiggsBosonDiscoveryEmail.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE Accelerator.SendHiggsBosonDiscoveryEmail
3 | @EmailAddress NVARCHAR(MAX)
4 | AS
5 | BEGIN
6 | RAISERROR('Not Implemented - yet',16,10);
7 | END;
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/example3-full/00-installTools.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -AssemblyName System.IO.Compression.FileSystem
2 |
3 | function Uzip-File {
4 | param( [string]$ziparchive, [string]$extractpath )
5 | [System.IO.Compression.ZipFile]::ExtractToDirectory( $ziparchive, $extractpath )
6 | }
7 |
8 | $baseToolsDir = "$PSScriptRoot\tools";
9 | New-Item -ItemType Directory -Force -Path $baseToolsDir
10 |
11 | function Setup-SqlCodeGuard {
12 | $url = "http://download.red-gate.com/SQLCodeGuardCmdLine.zip"
13 | $output = "$baseToolsDir\SQLCodeGuardCmdLine.zip";
14 | $outputDir = "$baseToolsDir\SQLCodeGuardCmdLine"
15 | [Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
16 | $WebClient = New-Object System.Net.WebClient
17 | $WebClient.DownloadFile($url,$output)
18 | Uzip-File -ziparchive $output -extractpath $outputDir
19 | Write-output "Extracted SQLCodeGuardCmdLine to $outputDir"
20 | }
21 |
22 | function Setup-SonarScanner {
23 | $url = "https://sonarsource.bintray.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.2.0.1227-windows.zip"
24 | $output = "$baseToolsDir\scanner.zip";
25 | $outputDir = "$baseToolsDir\sonar-scanner"
26 | [Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
27 | $WebClient = New-Object System.Net.WebClient
28 | $WebClient.DownloadFile($url,$output)
29 | Uzip-File -ziparchive $output -extractpath $outputDir
30 | Write-output "Extracted sonar-scanner to $outputDir"
31 | }
32 |
33 | function Setup-SQLCover {
34 | $url = "https://github.com/GoEddie/SQLCover/releases/download/0.4.1/SQLCOver.0.4.1.zip";
35 | $output = "$baseToolsDir\sqlCover.zip";
36 | $outputDir = "$baseToolsDir\SQLCover"
37 | [Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
38 | $WebClient = New-Object System.Net.WebClient
39 | $WebClient.DownloadFile($url,$output)
40 | Uzip-File -ziparchive $output -extractpath $outputDir
41 | Write-output "Extracted SQLCover to $outputDir"
42 |
43 | }
44 | Setup-SqlCodeGuard
45 | Setup-SQLCover
46 | Setup-SonarScanner
--------------------------------------------------------------------------------
/examples/example3-full/01-executeDBChanges.ps1:
--------------------------------------------------------------------------------
1 | Add-Type -AssemblyName System.IO.Compression.FileSystem
2 | function Uzip-File {
3 | param( [string]$ziparchive, [string]$extractpath )
4 | [System.IO.Compression.ZipFile]::ExtractToDirectory( $ziparchive, $extractpath )
5 | }
6 |
7 | $baseToolsDir = "$PSScriptRoot\tools";
8 | $tsqltDir = "$PSScriptRoot\tools\TSQLT"
9 |
10 |
11 | $server = ".\SQLEXPRESS01"
12 | $database = "ExampleDatabase"
13 |
14 | function Setup-TSQLT {
15 | $url = "https://tsqlt.org/download/tsqlt/";
16 | $output = "$baseToolsDir\tsqlt.zip";
17 | [Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
18 | $WebClient = New-Object System.Net.WebClient
19 | $WebClient.DownloadFile($url,$output)
20 | Uzip-File -ziparchive $output -extractpath $tsqltDir
21 | }
22 |
23 | Setup-TSQLT
24 |
25 | &sqlcmd -S $server -i "$tsqltDir\SetClrEnabled.sql"
26 | &sqlcmd -S $server -Q "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'clr strict security', 0; RECONFIGURE;"
27 | &sqlcmd -S $server -Q "CREATE DATABASE $database;"
28 | &sqlcmd -S $server -d $database -i "$tsqltDir\tSQLt.class.sql"
29 | return
--------------------------------------------------------------------------------
/examples/example3-full/02-runSonar.ps1:
--------------------------------------------------------------------------------
1 | ## Run tests with SQLCover
2 | $database = "ExampleDatabase"
3 | $server = ".\SQLEXPRESS01"
4 | $cloverDir = "$PSScriptRoot\tools\SQLCover"
5 | $coverageOutputDir = "$PSScriptRoot\build\sqlcoverresults"
6 |
7 | . "$cloverDir\SQLCover.ps1"
8 | $results = Get-CoverTSql "$cloverDir\SQLCover.dll" "server=$server;initial catalog=$database;integrated security=sspi;" "$database " "exec tSQLt.RunAll"
9 | New-Item -ItemType Directory -Force -Path $coverageOutputDir
10 | Export-OpenXml $results "$coverageOutputDir"
11 |
12 |
13 | ## Build and run code analysis
14 | $dbProject = "$PSScriptRoot\src\ExampleDatabase\ExampleDatabase.sln"
15 | $msbuildpath = Resolve-Path "C:\Program Files*\MSBuild\*\Bin\*\MSBuild.exe" | select -ExpandProperty Path -First 1
16 |
17 |
18 | &$msbuildpath "$dbProject" /t:build /p:RunSqlCodeAnalysis=True
19 |
20 | ## Run SQLCodeGuard if needed manually
21 | $sqlCodeGuard = "$PSScriptRoot\tools\SQLCodeGuardCmdLine\SqlCodeGuard30.Cmd.exe"
22 | $sqlCodeGuardResults = "$PSScriptRoot\build\cgtestresults.xml"
23 | $sqlCodeGuardArgs = @(
24 | "-source",
25 | "$PSScriptRoot\src",
26 | "-out",
27 | "$sqlCodeGuardResults",
28 | "/include:all"
29 | )
30 | &$sqlCodeGuard $sqlCodeGuardArgs
31 |
32 |
33 |
34 | ## Run sonar-scanner
35 |
36 |
37 | $sonarScanner = "$PSScriptRoot\tools\sonar-scanner\sonar-scanner-3.2.0.1227-windows\bin\sonar-scanner.bat"
38 |
39 | $sonarArgs = @(
40 | "-Dsonar.projectKey=tsql.sample.project",
41 | "-Dsonar.projectName=TSQL sample project",
42 | "-Dsonar.projectVersion=1.0",
43 | "-Dsonar.sources=src",
44 | "-Dsonar.host.url=http://localhost:9000"
45 | "-Dsonar.exclusions=**/bin/**/*.*,**/obj/**/*.*,**/*.sqlproj", # skip build files from analysis
46 |
47 | # it is possible to specify absolute path to the SQLCover report or directory where file matching *Coverage.opencoverxml resides, by default plugin will try to find it in the base directory's subdirectories
48 | "-Dsonar.tsql.sqlcover.report=$coverageOutputDir\Coverage.opencoverxml",
49 |
50 | # it is possible to either specify path to sqlcodeguard executable and plugin will try to run it or you can specify actual path to report's xml
51 | # or directory where file matching *cgresults.xml resides by setting sonar.tsql.cg.report property
52 | "-Dsonar.tsql.cg.path=$sqlCodeGuard"
53 | #"-Dsonar.tsql.cg.report=$sqlCodeGuardResults",
54 |
55 | # it is possible to specify absolute path to the MSBuild code analysis report or directory where file matching *StaticCodeAnalysis.Results.xml resides, by default plugin will try to find it in the base directory's subdirectories
56 | #"-Dsonar.tsql.ms.report=$PSScriptRoot\src\ExampleDatabase\ExampleDatabase\bin\Debug"
57 |
58 | );
59 | &$sonarScanner $sonarArgs
--------------------------------------------------------------------------------
/examples/example3-full/README.md:
--------------------------------------------------------------------------------
1 | # TSQL project example #
2 | This folder contains example TSQL project and scripts allowing to setup required tools and illustrating usage of sonar-scanner with TSQL plugin.
3 |
4 | # Usage #
5 | Execute the following:
6 | 1. Update if needed and run *00-installTools.ps1*. It will download and extract to tools directory SqlCodeGuard, SonarScanner and SQLClover.
7 | 2. Update *01-executeDBChanges.ps1* with *server* name where to deploy tSQLt framework and run.
8 | 3. Publish database from src folder.
9 | 4. Update *server* and *sonarHost* parameters in *02-runSonar.ps1* file and run that script.
10 |
11 | TSQL sample project should now be visible in SonarQube server with coverage results depicted in the figure.
12 |
13 | 
14 |
15 |
--------------------------------------------------------------------------------
/examples/example3-full/imgs/sonarDashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gretard/sonar-tsql-plugin/aadb5598bbb183c12df997ee9f3e053f962ce0f7/examples/example3-full/imgs/sonarDashboard.png
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2026
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "ExampleDatabase", "ExampleDatabase\ExampleDatabase.sqlproj", "{1EE51303-9E3E-49F4-BCAC-92E9F5758931}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {1EE51303-9E3E-49F4-BCAC-92E9F5758931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {1EE51303-9E3E-49F4-BCAC-92E9F5758931}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {1EE51303-9E3E-49F4-BCAC-92E9F5758931}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17 | {1EE51303-9E3E-49F4-BCAC-92E9F5758931}.Release|Any CPU.ActiveCfg = Release|Any CPU
18 | {1EE51303-9E3E-49F4-BCAC-92E9F5758931}.Release|Any CPU.Build.0 = Release|Any CPU
19 | {1EE51303-9E3E-49F4-BCAC-92E9F5758931}.Release|Any CPU.Deploy.0 = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | GlobalSection(ExtensibilityGlobals) = postSolution
25 | SolutionGuid = {5391EDB2-010B-469F-8931-BD24084B38FF}
26 | EndGlobalSection
27 | EndGlobal
28 |
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/.gitignore:
--------------------------------------------------------------------------------
1 | /ExampleDatabase.sqlproj.user
2 | **/bin/**/*
3 | **/obj/**/*
4 |
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/Billing.sql:
--------------------------------------------------------------------------------
1 | CREATE SCHEMA [Billing]
2 | AUTHORIZATION [dbo];
3 |
4 |
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/Billing/CustomerDiscounts.sql:
--------------------------------------------------------------------------------
1 | CREATE VIEW [Billing].[CustomerDiscounts]
2 | AS
3 | SELECT *, CASE WHEN [Billing].IsCustomerEligibleForDiscount(id) = 1 THEN 'discount available' ELSE 'no discount' END AS 'discount options'
4 | FROM billing.Customers
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/Billing/Customers.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE [Billing].[Customers] (
2 | [id] INT NULL,
3 | [name] NCHAR (255) NULL
4 | );
5 |
6 |
7 | GO
8 | EXECUTE sp_addextendedproperty @name = N'tSQLt.FakeTable_OrgTableName', @value = N'tSQLt_tempobject_9ebb1c5d4b6944daace9941ebca2c6bc', @level0type = N'SCHEMA', @level0name = N'Billing', @level1type = N'TABLE', @level1name = N'Customers';
9 |
10 |
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/Billing/IsCustomerEligibleForDiscount.sql:
--------------------------------------------------------------------------------
1 | CREATE FUNCTION Billing.IsCustomerEligibleForDiscount
2 | (
3 | @customerId int
4 | )
5 | RETURNS bit
6 | AS
7 | BEGIN
8 | DECLARE @result bit = 0
9 | DECLARE @date DATETIME = GETDATE();
10 | DECLARE @prevMonth DATETIME = EOMONTH ( @date, -1 );
11 |
12 | SELECT @result = case when sum([sum]) > 2000 and count(*) > 3 then 1 else 0 end
13 | FROM Billing.Orders WHERE customerId = @customerId and [date] between @prevMonth and @date
14 |
15 | RETURN @result
16 |
17 | END
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/Billing/Orders.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE [Billing].[Orders] (
2 | [ordername] NCHAR (255) NULL,
3 | [customerId] INT NULL,
4 | [sum] FLOAT (53) NULL,
5 | [date] DATE NULL
6 | );
7 |
8 |
9 | GO
10 | EXECUTE sp_addextendedproperty @name = N'tSQLt.FakeTable_OrgTableName', @value = N'tSQLt_tempobject_f0c30fdb1c4a4fa697445d265ee80788', @level0type = N'SCHEMA', @level0name = N'Billing', @level1type = N'TABLE', @level1name = N'Orders';
11 |
12 |
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/BillingTests.sql:
--------------------------------------------------------------------------------
1 | CREATE SCHEMA [BillingTests]
2 | AUTHORIZATION [dbo];
3 |
4 |
5 | GO
6 | EXECUTE sp_addextendedproperty @name = N'tSQLt.TestClass', @value = 1, @level0type = N'SCHEMA', @level0name = N'BillingTests';
7 |
8 |
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/BillingTests/test that customer with more than 3 orders and total over 2000 can discount.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE [BillingTests].[test that customer with more than 3 orders and total over 2000 can discount]
3 | AS
4 | BEGIN
5 | --Assemble: Fake the Particle table to make sure it is empty and that constraints will not be a problem
6 | EXEC tSQLt.FakeTable 'Billing.Customers';
7 | EXEC tSQLt.FakeTable 'Billing.Orders';
8 | -- Populate the Particle table with rows that hug the rectangle boundaries
9 | INSERT INTO Billing.Customers VALUES ( 1, 'test');
10 | INSERT INTO Billing.Orders VALUES ('order1', 1, 1000, DATEADD(day,-1,GETDATE()));
11 | INSERT INTO Billing.Orders VALUES ('order2', 1, 2000, DATEADD(day,-1,GETDATE()));
12 | INSERT INTO Billing.Orders VALUES ('order3', 1, 3330, DATEADD(day,-1,GETDATE()));
13 | INSERT INTO Billing.Orders VALUES ('order4', 1, 12220, DATEADD(day,-1,GETDATE()));
14 | DECLARE @actualComputedResult BIT;
15 | SET @actualComputedResult = Billing.IsCustomerEligibleForDiscount(1);
16 | EXEC tSQLt.AssertEquals 1, @actualComputedResult;
17 | END;
--------------------------------------------------------------------------------
/examples/example3-full/src/ExampleDatabase/ExampleDatabase/BillingTests/test that not existing customer can not get discount.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE [BillingTests].[test that not existing customer can not get discount]
3 | AS
4 | BEGIN
5 | EXEC tSQLt.FakeTable 'Billing.Customers';
6 | EXEC tSQLt.FakeTable 'Billing.Orders';
7 | DECLARE @actualComputedResult BIT;
8 | SET @actualComputedResult = Billing.IsCustomerEligibleForDiscount(1);
9 | EXEC tSQLt.AssertEquals 0, @actualComputedResult;
10 | END;
--------------------------------------------------------------------------------
/examples/example4-adhoc/Example.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "Example", "Example\Example.sqlproj", "{1491DCE3-0018-487C-9B9B-F7EEA6C863F8}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
18 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Release|Any CPU.Build.0 = Release|Any CPU
19 | {1491DCE3-0018-487C-9B9B-F7EEA6C863F8}.Release|Any CPU.Deploy.0 = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | EndGlobal
25 |
--------------------------------------------------------------------------------
/examples/example4-adhoc/Example/TestTable.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE [dbo].[TestTable]
2 | (
3 | [Id] INT NOT NULL PRIMARY KEY,
4 | [Name] NVARCHAR(MAX) NULL
5 | )
6 |
--------------------------------------------------------------------------------
/examples/example4-adhoc/Example/sp_Get.sql:
--------------------------------------------------------------------------------
1 | CREATE PROCEDURE [dbo].[sp_Get]
2 | @param1 int = 0,
3 | @param2 int
4 | AS
5 | BEGIN
6 | SELECT * FROM TestTable;
7 | EXEC ('SELECT 1');
8 | insert into dbo.test values (1,2);
9 |
10 | EXECUTE sp_executesql N'select 1';
11 |
12 | RETURN 0
13 | END
14 | -- kasldjaskjd
--------------------------------------------------------------------------------
/examples/example4-adhoc/README.md:
--------------------------------------------------------------------------------
1 | # Example T-SQL project
2 | In order to get results to sonar server please:
3 |
4 | - (Optional) Please update file **myExampleRepo.customRules** in *customRules* directory with your custom rules
5 | - (Optional) If needed update path to SQL code guard on sonar server or add **sonar.tsql.cg.path** setting with path in sonar.properties file
6 | - (Optional) Build sample project with setting /p:RunSqlCodeAnalysis=true if not using other means for building:
7 | - msbuild /p:RunSqlCodeAnalysis=true
8 | - (Optional) Update sonar-project.properties file as needed
9 | - Run sonar scanner
10 |
--------------------------------------------------------------------------------
/examples/example4-adhoc/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.projectKey=example4.tsql.project.adhoc
2 | sonar.projectName=Example4: TSQL project with Adhoc rules
3 | sonar.projectVersion=1.0
4 | sonar.sources=Example
5 | sonar.sourceEncoding=UTF-8
6 | sonar.language=tsql
7 | sonar.tsql.customrules.paths=./customRules
8 | ## not needed to update if matches server settings
9 | #sonar.tsql.customrules.prefix=.customRules
10 |
--------------------------------------------------------------------------------
/scripts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scripts",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "cheerio": "^1.0.0-rc.2"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.scannerwork/
3 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | sonar-tsql-plugin
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.m2e.core.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.sonar.ide.eclipse.core.sonarNature
21 | org.eclipse.jdt.core.javanature
22 | org.eclipse.m2e.core.maven2Nature
23 |
24 |
25 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/opencover/Classes.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.08.15 at 09:03:12 PM EEST
6 | //
7 |
8 |
9 | package org.opencover;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlElement;
16 | import javax.xml.bind.annotation.XmlRootElement;
17 | import javax.xml.bind.annotation.XmlType;
18 |
19 |
20 | /**
21 | *
The following schema fragment specifies the expected content contained within this class.
24 | *
25 | *
clazz;
48 |
49 | /**
50 | * Gets the value of the clazz property.
51 | *
52 | *
53 | * This accessor method returns a reference to the live list,
54 | * not a snapshot. Therefore any modification you make to the
55 | * returned list will be present inside the JAXB object.
56 | * This is why there is not a set
method for the clazz property.
57 | *
58 | *
59 | * For example, to add a new item, do as follows:
60 | *
61 | * getClazz().add(newItem);
62 | *
63 | *
64 | *
65 | *
66 | * Objects of the following type(s) are allowed in the list
67 | * {@link Class }
68 | *
69 | *
70 | */
71 | public List getClazz() {
72 | if (clazz == null) {
73 | clazz = new ArrayList();
74 | }
75 | return this.clazz;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/opencover/CoverageSession.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.08.15 at 09:03:12 PM EEST
6 | //
7 |
8 |
9 | package org.opencover;
10 |
11 | import javax.xml.bind.annotation.XmlAccessType;
12 | import javax.xml.bind.annotation.XmlAccessorType;
13 | import javax.xml.bind.annotation.XmlElement;
14 | import javax.xml.bind.annotation.XmlRootElement;
15 | import javax.xml.bind.annotation.XmlType;
16 |
17 |
18 | /**
19 | * Java class for anonymous complex type.
20 | *
21 | *
The following schema fragment specifies the expected content contained within this class.
22 | *
23 | *
24 | * <complexType>
25 | * <complexContent>
26 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 | * <sequence>
28 | * <element ref="{}Summary"/>
29 | * <element ref="{}Modules"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "summary",
41 | "modules"
42 | })
43 | @XmlRootElement(name = "CoverageSession")
44 | public class CoverageSession {
45 |
46 | @XmlElement(name = "Summary", required = true)
47 | protected Summary summary;
48 | @XmlElement(name = "Modules", required = true)
49 | protected Modules modules;
50 |
51 | /**
52 | * Gets the value of the summary property.
53 | *
54 | * @return
55 | * possible object is
56 | * {@link Summary }
57 | *
58 | */
59 | public Summary getSummary() {
60 | return summary;
61 | }
62 |
63 | /**
64 | * Sets the value of the summary property.
65 | *
66 | * @param value
67 | * allowed object is
68 | * {@link Summary }
69 | *
70 | */
71 | public void setSummary(Summary value) {
72 | this.summary = value;
73 | }
74 |
75 | /**
76 | * Gets the value of the modules property.
77 | *
78 | * @return
79 | * possible object is
80 | * {@link Modules }
81 | *
82 | */
83 | public Modules getModules() {
84 | return modules;
85 | }
86 |
87 | /**
88 | * Sets the value of the modules property.
89 | *
90 | * @param value
91 | * allowed object is
92 | * {@link Modules }
93 | *
94 | */
95 | public void setModules(Modules value) {
96 | this.modules = value;
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/opencover/FileRef.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.08.15 at 09:03:12 PM EEST
6 | //
7 |
8 |
9 | package org.opencover;
10 |
11 | import javax.xml.bind.annotation.XmlAccessType;
12 | import javax.xml.bind.annotation.XmlAccessorType;
13 | import javax.xml.bind.annotation.XmlAttribute;
14 | import javax.xml.bind.annotation.XmlRootElement;
15 | import javax.xml.bind.annotation.XmlType;
16 | import javax.xml.bind.annotation.XmlValue;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <simpleContent>
27 | * <extension base="<http://www.w3.org/2001/XMLSchema>string">
28 | * <attribute name="uid" type="{http://www.w3.org/2001/XMLSchema}int" />
29 | * </extension>
30 | * </simpleContent>
31 | * </complexType>
32 | *
33 | *
34 | *
35 | */
36 | @XmlAccessorType(XmlAccessType.FIELD)
37 | @XmlType(name = "", propOrder = {
38 | "value"
39 | })
40 | @XmlRootElement(name = "FileRef")
41 | public class FileRef {
42 |
43 | @XmlValue
44 | protected String value;
45 | @XmlAttribute(name = "uid")
46 | protected Integer uid;
47 |
48 | /**
49 | * Gets the value of the value property.
50 | *
51 | * @return
52 | * possible object is
53 | * {@link String }
54 | *
55 | */
56 | public String getValue() {
57 | return value;
58 | }
59 |
60 | /**
61 | * Sets the value of the value property.
62 | *
63 | * @param value
64 | * allowed object is
65 | * {@link String }
66 | *
67 | */
68 | public void setValue(String value) {
69 | this.value = value;
70 | }
71 |
72 | /**
73 | * Gets the value of the uid property.
74 | *
75 | * @return
76 | * possible object is
77 | * {@link Integer }
78 | *
79 | */
80 | public Integer getUid() {
81 | return uid;
82 | }
83 |
84 | /**
85 | * Sets the value of the uid property.
86 | *
87 | * @param value
88 | * allowed object is
89 | * {@link Integer }
90 | *
91 | */
92 | public void setUid(Integer value) {
93 | this.uid = value;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/opencover/Files.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.08.15 at 09:03:12 PM EEST
6 | //
7 |
8 |
9 | package org.opencover;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlElement;
16 | import javax.xml.bind.annotation.XmlRootElement;
17 | import javax.xml.bind.annotation.XmlType;
18 |
19 |
20 | /**
21 | * Java class for anonymous complex type.
22 | *
23 | *
The following schema fragment specifies the expected content contained within this class.
24 | *
25 | *
26 | * <complexType>
27 | * <complexContent>
28 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
29 | * <sequence>
30 | * <element ref="{}File" maxOccurs="unbounded" minOccurs="0"/>
31 | * </sequence>
32 | * </restriction>
33 | * </complexContent>
34 | * </complexType>
35 | *
36 | *
37 | *
38 | */
39 | @XmlAccessorType(XmlAccessType.FIELD)
40 | @XmlType(name = "", propOrder = {
41 | "file"
42 | })
43 | @XmlRootElement(name = "Files")
44 | public class Files {
45 |
46 | @XmlElement(name = "File")
47 | protected List file;
48 |
49 | /**
50 | * Gets the value of the file property.
51 | *
52 | *
53 | * This accessor method returns a reference to the live list,
54 | * not a snapshot. Therefore any modification you make to the
55 | * returned list will be present inside the JAXB object.
56 | * This is why there is not a set
method for the file property.
57 | *
58 | *
59 | * For example, to add a new item, do as follows:
60 | *
61 | * getFile().add(newItem);
62 | *
63 | *
64 | *
65 | *
66 | * Objects of the following type(s) are allowed in the list
67 | * {@link File }
68 | *
69 | *
70 | */
71 | public List getFile() {
72 | if (file == null) {
73 | file = new ArrayList();
74 | }
75 | return this.file;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/opencover/Methods.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.08.15 at 09:03:12 PM EEST
6 | //
7 |
8 |
9 | package org.opencover;
10 |
11 | import javax.xml.bind.annotation.XmlAccessType;
12 | import javax.xml.bind.annotation.XmlAccessorType;
13 | import javax.xml.bind.annotation.XmlElement;
14 | import javax.xml.bind.annotation.XmlRootElement;
15 | import javax.xml.bind.annotation.XmlType;
16 |
17 |
18 | /**
19 | * Java class for anonymous complex type.
20 | *
21 | *
The following schema fragment specifies the expected content contained within this class.
22 | *
23 | *
24 | * <complexType>
25 | * <complexContent>
26 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 | * <sequence>
28 | * <element ref="{}Method"/>
29 | * </sequence>
30 | * </restriction>
31 | * </complexContent>
32 | * </complexType>
33 | *
34 | *
35 | *
36 | */
37 | @XmlAccessorType(XmlAccessType.FIELD)
38 | @XmlType(name = "", propOrder = {
39 | "method"
40 | })
41 | @XmlRootElement(name = "Methods")
42 | public class Methods {
43 |
44 | @XmlElement(name = "Method", required = true)
45 | protected Method method;
46 |
47 | /**
48 | * Gets the value of the method property.
49 | *
50 | * @return
51 | * possible object is
52 | * {@link Method }
53 | *
54 | */
55 | public Method getMethod() {
56 | return method;
57 | }
58 |
59 | /**
60 | * Sets the value of the method property.
61 | *
62 | * @param value
63 | * allowed object is
64 | * {@link Method }
65 | *
66 | */
67 | public void setMethod(Method value) {
68 | this.method = value;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/opencover/Modules.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.08.15 at 09:03:12 PM EEST
6 | //
7 |
8 |
9 | package org.opencover;
10 |
11 | import javax.xml.bind.annotation.XmlAccessType;
12 | import javax.xml.bind.annotation.XmlAccessorType;
13 | import javax.xml.bind.annotation.XmlElement;
14 | import javax.xml.bind.annotation.XmlRootElement;
15 | import javax.xml.bind.annotation.XmlType;
16 |
17 |
18 | /**
19 | * Java class for anonymous complex type.
20 | *
21 | *
The following schema fragment specifies the expected content contained within this class.
22 | *
23 | *
24 | * <complexType>
25 | * <complexContent>
26 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 | * <sequence>
28 | * <element ref="{}Module"/>
29 | * </sequence>
30 | * </restriction>
31 | * </complexContent>
32 | * </complexType>
33 | *
34 | *
35 | *
36 | */
37 | @XmlAccessorType(XmlAccessType.FIELD)
38 | @XmlType(name = "", propOrder = {
39 | "module"
40 | })
41 | @XmlRootElement(name = "Modules")
42 | public class Modules {
43 |
44 | @XmlElement(name = "Module", required = true)
45 | protected Module module;
46 |
47 | /**
48 | * Gets the value of the module property.
49 | *
50 | * @return
51 | * possible object is
52 | * {@link Module }
53 | *
54 | */
55 | public Module getModule() {
56 | return module;
57 | }
58 |
59 | /**
60 | * Sets the value of the module property.
61 | *
62 | * @param value
63 | * allowed object is
64 | * {@link Module }
65 | *
66 | */
67 | public void setModule(Module value) {
68 | this.module = value;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/opencover/SequencePoints.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.08.15 at 09:03:12 PM EEST
6 | //
7 |
8 |
9 | package org.opencover;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlElement;
16 | import javax.xml.bind.annotation.XmlRootElement;
17 | import javax.xml.bind.annotation.XmlType;
18 |
19 |
20 | /**
21 | * Java class for anonymous complex type.
22 | *
23 | *
The following schema fragment specifies the expected content contained within this class.
24 | *
25 | *
26 | * <complexType>
27 | * <complexContent>
28 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
29 | * <sequence>
30 | * <element ref="{}SequencePoint" maxOccurs="unbounded" minOccurs="0"/>
31 | * </sequence>
32 | * </restriction>
33 | * </complexContent>
34 | * </complexType>
35 | *
36 | *
37 | *
38 | */
39 | @XmlAccessorType(XmlAccessType.FIELD)
40 | @XmlType(name = "", propOrder = {
41 | "sequencePoint"
42 | })
43 | @XmlRootElement(name = "SequencePoints")
44 | public class SequencePoints {
45 |
46 | @XmlElement(name = "SequencePoint")
47 | protected List sequencePoint;
48 |
49 | /**
50 | * Gets the value of the sequencePoint property.
51 | *
52 | *
53 | * This accessor method returns a reference to the live list,
54 | * not a snapshot. Therefore any modification you make to the
55 | * returned list will be present inside the JAXB object.
56 | * This is why there is not a set
method for the sequencePoint property.
57 | *
58 | *
59 | * For example, to add a new item, do as follows:
60 | *
61 | * getSequencePoint().add(newItem);
62 | *
63 | *
64 | *
65 | *
66 | * Objects of the following type(s) are allowed in the list
67 | * {@link SequencePoint }
68 | *
69 | *
70 | */
71 | public List getSequencePoint() {
72 | if (sequencePoint == null) {
73 | sequencePoint = new ArrayList();
74 | }
75 | return this.sequencePoint;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/Constants.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql;
2 |
3 | import org.sonar.plugins.tsql.languages.TSQLLanguage;
4 |
5 | public final class Constants {
6 | public static final String PROFILE_NAME = "Sonar Way";
7 |
8 | public static final String CG_REPORT_FILE = "sonar.tsql.cg.report";
9 |
10 | public static final String CG_REPORT_FILE_DEFAULT_VALUE = "cgresults.xml";
11 |
12 | public static final String PLUGIN_SKIP = "sonar.tsql.skip";
13 |
14 | public static final String PLUGIN_SKIP_COVERAGE = "sonar.tsql.sqlcover.skip";
15 |
16 | public static final String PLUGIN_SKIP_CUSTOM = "sonar.tsql.custom.skip";
17 |
18 | public static final String PLUGIN_SKIP_MS = "sonar.tsql.ms.skip";
19 |
20 | public static final String PLUGIN_SKIP_CG = "sonar.tsql.cg.skip";
21 |
22 | public static final String PLUGIN_MAX_FILE_SIZE = "sonar.tsql.custom.max.file.size";
23 |
24 | public static final String CG_APP_PATH = "sonar.tsql.cg.path";
25 |
26 | public static final String COVERAGE_FILE = "sonar.tsql.sqlcover.report";
27 |
28 | public static final String COVERAGE_FILE_DEFAULT_VALUE = "Coverage.opencoverxml";
29 |
30 | public static final String MS_REPORT_FILE = "sonar.tsql.ms.report";
31 |
32 | public static final String MS_REPORT_FILE_DEFAULT_VALUE = "staticcodeanalysis.results.xml";
33 |
34 | public static final String PLUGIN_ANALYSIS_TIMEOUT = "sonar.tsql.timeout.analysis";
35 |
36 | public static final String PLUGIN_SUFFIXES = "sonar.tsql.file.suffixes";
37 |
38 | public static final String PLUGIN_SKIP_CUSTOM_RULES = "sonar.tsql.skip.custom.rules";
39 |
40 | public static final String CG_REPO_KEY = TSQLLanguage.KEY.toLowerCase() + "-sqlcodeguard";
41 |
42 | public static final String CG_REPO_NAME = TSQLLanguage.KEY.toLowerCase() + " SQL Code Guard";
43 |
44 | public static final String CG_RULES_FILE = "/rules/cgsql-rules.xml";
45 |
46 | public static final String MS_REPO_KEY = TSQLLanguage.KEY.toLowerCase() + "-mssql";
47 |
48 | public static final String MS_REPO_NAME = TSQLLanguage.KEY.toLowerCase() + " Microsoft T-SQL";
49 |
50 | public static final String MS_RULES_FILE = "/rules/vssql-rules.xml";
51 |
52 | public static final String PLUGIN_CUSTOM_RULES_PATH = "sonar.tsql.customrules.paths";
53 |
54 | public static final String PLUGIN_CUSTOM_RULES_PREFIX = "sonar.tsql.customrules.prefix";
55 |
56 | public static final String PLUGIN_RULES_FILE = "/rules/plugin-rules.xml";
57 |
58 | public static final String PLUGIN_REPO_NAME = TSQLLanguage.KEY.toLowerCase() + " plugin custom rules";
59 |
60 | public static final String PLUGIN_REPO_KEY = "tsqlPluginRepo";
61 | }
62 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/AntlrContext.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.nio.charset.Charset;
6 |
7 | import org.antlr.tsql.TSqlLexer;
8 | import org.antlr.tsql.TSqlParser;
9 | import org.antlr.v4.runtime.CharStream;
10 | import org.antlr.v4.runtime.CharStreams;
11 | import org.antlr.v4.runtime.CommonTokenStream;
12 | import org.antlr.v4.runtime.Token;
13 | import org.antlr.v4.runtime.tree.ParseTree;
14 | import org.sonar.api.batch.fs.InputFile;
15 | import org.sonar.plugins.tsql.lines.SourceLine;
16 | import org.sonar.plugins.tsql.lines.SourceLinesProvider;
17 |
18 | public class AntlrContext {
19 |
20 | public InputFile getFile() {
21 | return file;
22 | }
23 |
24 | public CommonTokenStream getStream() {
25 | return stream;
26 | }
27 |
28 | public SourceLine[] getLines() {
29 | return lines;
30 | }
31 |
32 | public Token[] getTokens() {
33 | return this.stream.getTokens().toArray(new Token[0]);
34 | }
35 |
36 | public ParseTree getRoot() {
37 | return root;
38 | }
39 |
40 | public int[] getLineAndColumn(final int global) {
41 |
42 | for (final SourceLine line : this.lines) {
43 | if (line.getEnd() > global) {
44 | return new int[] { line.getLine(), global - line.getStart() };
45 | }
46 | }
47 | return null;
48 | }
49 |
50 | private final InputFile file;
51 | private final CommonTokenStream stream;
52 | private final SourceLine[] lines;
53 | private final ParseTree root;
54 |
55 | public AntlrContext(InputFile file, CommonTokenStream stream, ParseTree root, SourceLine[] lines) {
56 | this.file = file;
57 | this.stream = stream;
58 | this.root = root;
59 | this.lines = lines;
60 | }
61 |
62 | public static AntlrContext fromInputFile(InputFile file, Charset charset) throws IOException {
63 | return fromStreams(file, file.inputStream(), file.inputStream(), charset);
64 | }
65 |
66 | public static AntlrContext fromStreams(InputFile inputFile, InputStream file, InputStream linesStream,
67 | Charset charset) throws IOException {
68 | final SourceLinesProvider linesProvider = new SourceLinesProvider();
69 | final CharStream charStream = new CaseChangingCharStream(CharStreams.fromStream(file, charset), true);
70 | final TSqlLexer lexer = new TSqlLexer(charStream);
71 | lexer.removeErrorListeners();
72 | final CommonTokenStream stream = new CommonTokenStream(lexer);
73 | stream.fill();
74 | final TSqlParser parser = new TSqlParser(stream);
75 | parser.removeErrorListeners();
76 | final ParseTree root = parser.tsql_file();
77 | final SourceLine[] lines = linesProvider.getLines(linesStream, charset);
78 | return new AntlrContext(inputFile, stream, root, lines);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/CandidateNode.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr;
2 |
3 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
4 |
5 | public class CandidateNode {
6 | private final CandidateRule rule;
7 | private final IParsedNode nnode;
8 |
9 | public CandidateNode(final CandidateRule rule, final IParsedNode nnode) {
10 | this.rule = rule;
11 | this.nnode = nnode;
12 | }
13 |
14 | public String getRepoKey() {
15 | return this.rule.getKey();
16 | }
17 | public String getKey() {
18 | return this.rule.getRule().getKey();
19 | }
20 | public boolean isAdhoc() {
21 | return this.rule.isAdHoc();
22 | }
23 |
24 | public RuleImplementation getRuleImplementation() {
25 | return this.rule.getRuleImplementation();
26 | }
27 |
28 | public IParsedNode getNode() {
29 | return nnode;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/CandidateRule.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr;
2 |
3 | import org.sonar.plugins.tsql.checks.custom.Rule;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 |
6 | public class CandidateRule {
7 | private final String key;
8 | private final Rule rule;
9 | private final boolean isAdHoc;
10 |
11 | public boolean isAdHoc() {
12 | return isAdHoc;
13 | }
14 |
15 | public String getKey() {
16 | return key;
17 | }
18 |
19 | public Rule getRule() {
20 | return rule;
21 | }
22 |
23 | public CandidateRule(final String key, final Rule rule) {
24 | this(key, rule, false);
25 | }
26 |
27 | public CandidateRule(final String key, final Rule rule, boolean isAdhoc) {
28 | this.key = key;
29 | this.rule = rule;
30 | this.isAdHoc = isAdhoc;
31 | }
32 |
33 | public RuleImplementation getRuleImplementation() {
34 | return this.rule.getRuleImplementation();
35 | }
36 |
37 | @Override
38 | public int hashCode() {
39 | final int prime = 31;
40 | int result = 1;
41 | result = prime * result + ((key == null) ? 0 : key.hashCode());
42 | result = prime * result + ((rule == null) ? 0 : rule.hashCode());
43 | return result;
44 | }
45 |
46 | @Override
47 | public boolean equals(Object obj) {
48 | if (this == obj)
49 | return true;
50 | if (obj == null)
51 | return false;
52 | if (getClass() != obj.getClass())
53 | return false;
54 | CandidateRule other = (CandidateRule) obj;
55 | if (key == null) {
56 | if (other.key != null)
57 | return false;
58 | } else if (!key.equals(other.key))
59 | return false;
60 | if (rule == null) {
61 | if (other.rule != null)
62 | return false;
63 | } else if (!rule.equals(other.rule))
64 | return false;
65 | return true;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/CaseChangingCharStream.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr;
2 |
3 | import org.antlr.v4.runtime.CharStream;
4 | import org.antlr.v4.runtime.misc.Interval;
5 |
6 | public class CaseChangingCharStream implements CharStream {
7 |
8 | private final CharStream stream;
9 | private final boolean upper;
10 |
11 | public CaseChangingCharStream(final CharStream stream, final boolean upper) {
12 | this.stream = stream;
13 | this.upper = upper;
14 | }
15 |
16 | @Override
17 | public String getText(Interval interval) {
18 | return stream.getText(interval);
19 | }
20 |
21 | @Override
22 | public void consume() {
23 | stream.consume();
24 | }
25 |
26 | @Override
27 | public int LA(int i) {
28 | int c = stream.LA(i);
29 | if (c <= 0) {
30 | return c;
31 | }
32 | if (upper) {
33 | return Character.toUpperCase(c);
34 | }
35 | return Character.toLowerCase(c);
36 | }
37 |
38 | @Override
39 | public int mark() {
40 | return stream.mark();
41 | }
42 |
43 | @Override
44 | public void release(int marker) {
45 | stream.release(marker);
46 | }
47 |
48 | @Override
49 | public int index() {
50 | return stream.index();
51 | }
52 |
53 | @Override
54 | public void seek(int index) {
55 | stream.seek(index);
56 | }
57 |
58 | @Override
59 | public int size() {
60 | return stream.size();
61 | }
62 |
63 | @Override
64 | public String getSourceName() {
65 | return stream.getSourceName();
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/IParsedNode.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr;
2 |
3 | import org.antlr.v4.runtime.tree.ParseTree;
4 |
5 | public interface IParsedNode {
6 |
7 | public String getText();
8 |
9 | public String getClassName();
10 |
11 | public int getDistance();
12 |
13 | public int getIndex();
14 |
15 | public int getIndex2();
16 |
17 | public ParseTree getItem();
18 |
19 | public IParsedNode[] getParents();
20 |
21 | public IParsedNode[] getChildren();
22 |
23 | public IParsedNode[] getSiblings();
24 |
25 | public IParsedNode getControlFlowParent();
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/PluginHelper.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.StringWriter;
8 | import java.nio.charset.Charset;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | import javax.xml.bind.JAXBContext;
13 | import javax.xml.bind.JAXBException;
14 | import javax.xml.bind.Marshaller;
15 |
16 | import org.antlr.tsql.TSqlLexer;
17 | import org.antlr.tsql.TSqlParser;
18 | import org.antlr.v4.runtime.CharStream;
19 | import org.antlr.v4.runtime.CharStreams;
20 | import org.antlr.v4.runtime.CommonTokenStream;
21 | import org.antlr.v4.runtime.tree.ParseTree;
22 | import org.apache.commons.io.input.BOMInputStream;
23 | import org.sonar.api.batch.fs.InputFile;
24 | import org.sonar.plugins.tsql.checks.custom.Rule;
25 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
26 | import org.sonar.plugins.tsql.lines.SourceLinesProvider;
27 |
28 | public final class PluginHelper {
29 |
30 |
31 |
32 |
33 |
34 |
35 | public static AntlrContext createRequestFromStream(final InputFile file, final Charset encoding,
36 | final CharStream mainStream, InputStream fileInputStream) {
37 | final SourceLinesProvider linesProvider = new SourceLinesProvider();
38 | final CharStream charStream = new CaseChangingCharStream(mainStream, true);
39 | final TSqlLexer lexer = new TSqlLexer(charStream);
40 |
41 | lexer.removeErrorListeners();
42 |
43 | final CommonTokenStream stream = new CommonTokenStream(lexer);
44 |
45 | stream.fill();
46 | final TSqlParser parser = new TSqlParser(stream);
47 | parser.removeErrorListeners();
48 | final ParseTree root = parser.tsql_file();
49 | final AntlrContext antrlFile = new AntlrContext(file, stream, root,
50 | linesProvider.getLines(fileInputStream, encoding));
51 | return antrlFile;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/issues/CustomIssuesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.issues;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Map;
6 |
7 | import org.sonar.plugins.tsql.antlr.AntlrContext;
8 | import org.sonar.plugins.tsql.antlr.CandidateNode;
9 | import org.sonar.plugins.tsql.antlr.IParsedNode;
10 | import org.sonar.plugins.tsql.antlr.lines.DefaultLinesProvider;
11 | import org.sonar.plugins.tsql.antlr.nodes.NodeUsesProvider;
12 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
13 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
14 |
15 | public class CustomIssuesProvider {
16 |
17 | public TsqlIssue[] getIssues(AntlrContext antlrContext, CandidateNode[] candidates) {
18 | final org.sonar.plugins.tsql.antlr.issues.FoundViolationsAnalyzer foundViolationsAnalyzer = new FoundViolationsAnalyzer(
19 | new DefaultLinesProvider(antlrContext.getStream()));
20 |
21 | final NodesMatchingRulesProvider nodesMatchingRulesProvider = new NodesMatchingRulesProvider(
22 | new NodeUsesProvider(antlrContext.getRoot()));
23 |
24 | final List issues = new ArrayList<>();
25 |
26 | for (final CandidateNode candidate : candidates) {
27 | final Map> results = nodesMatchingRulesProvider.check(candidate);
28 | final List foundIssues = foundViolationsAnalyzer.analyze(candidate, results);
29 | issues.addAll(foundIssues);
30 | }
31 | return issues.toArray(new TsqlIssue[0]);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/lines/DefaultLinesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.lines;
2 |
3 | import org.antlr.v4.runtime.CommonTokenStream;
4 | import org.antlr.v4.runtime.Token;
5 | import org.antlr.v4.runtime.misc.Interval;
6 | import org.sonar.plugins.tsql.antlr.IParsedNode;
7 |
8 | public class DefaultLinesProvider implements ILinesProvider {
9 |
10 | private final CommonTokenStream stream;
11 |
12 | public DefaultLinesProvider(final CommonTokenStream stream) {
13 | this.stream = stream;
14 | }
15 |
16 | @Override
17 | public int getLine(final IParsedNode node) {
18 | if (node == null || node.getItem() == null) {
19 | return 0;
20 | }
21 | final Interval sourceInterval = node.getItem().getSourceInterval();
22 | final Token firstToken = stream.get(sourceInterval.a);
23 | final int line = firstToken.getLine();
24 | return line;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/lines/ILinesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.lines;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.antlr.nodes.ParsedNode;
5 |
6 | public interface ILinesProvider {
7 | int getLine(IParsedNode node);
8 | }
9 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/INodesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 |
5 | public interface INodesProvider {
6 | IParsedNode[] getNodes(final T node);
7 | }
8 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/NodeUsesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
7 | import org.antlr.v4.runtime.tree.ParseTree;
8 | import org.antlr.v4.runtime.tree.RuleNode;
9 | import org.apache.commons.lang3.StringUtils;
10 | import org.sonar.plugins.tsql.antlr.IParsedNode;
11 |
12 | @SuppressWarnings("rawtypes")
13 | public class NodeUsesProvider extends AbstractParseTreeVisitor implements INodesProvider {
14 |
15 | private final ParseTree root;
16 | private final List nodes = new ArrayList<>();
17 |
18 | private String tempText;
19 |
20 | public NodeUsesProvider(final ParseTree root) {
21 | this.root = root;
22 | }
23 |
24 | @Override
25 | public IParsedNode[] getNodes(final IParsedNode node) {
26 | this.nodes.clear();
27 | this.tempText = null;
28 | if (node == null) {
29 | return new IParsedNode[0];
30 | }
31 | this.tempText = node.getText();
32 | visit(root);
33 | IParsedNode[] results = this.nodes.toArray(new IParsedNode[0]);
34 | this.nodes.clear();
35 | this.tempText = null;
36 | return results;
37 |
38 | }
39 |
40 | @SuppressWarnings("unchecked")
41 | @Override
42 | public Object visitChildren(final RuleNode node) {
43 |
44 | final int n = node.getChildCount();
45 |
46 | for (int i = 0; i < n; i++) {
47 | final ParseTree c = node.getChild(i);
48 | c.accept(this);
49 |
50 | }
51 | final String textToFind = node.getText();
52 | if (StringUtils.containsIgnoreCase(textToFind, tempText)
53 | || StringUtils.containsIgnoreCase(tempText, textToFind)) {
54 | nodes.add(new ParsedNode(node));
55 | }
56 | return null;
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/ABaseMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 |
6 | public abstract class ABaseMatcher implements IMatcher {
7 |
8 | protected abstract boolean innerMatch(RuleImplementation rule, IParsedNode item);
9 |
10 | protected abstract boolean shouldApply(RuleImplementation rule, IParsedNode item);
11 |
12 | @Override
13 | public boolean match(RuleImplementation rule, IParsedNode item) {
14 | if (rule == null || item == null) {
15 | return false;
16 | }
17 | if (shouldApply(rule, item)) {
18 | return innerMatch(rule, item);
19 | }
20 |
21 | return true;
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/ClassNameMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 |
6 | public class ClassNameMatcher extends ABaseMatcher {
7 |
8 | private final boolean isStrict;
9 |
10 | public ClassNameMatcher(boolean isStrict) {
11 | this.isStrict = isStrict;
12 |
13 | }
14 |
15 | public ClassNameMatcher() {
16 | this(false);
17 | }
18 |
19 | @Override
20 | protected boolean innerMatch(RuleImplementation rule, IParsedNode item) {
21 | final String name = item.getClassName();
22 | for (final String classNameToCheck : rule.getNames().getTextItem()) {
23 | if (name.equalsIgnoreCase(classNameToCheck)) {
24 | return true;
25 | }
26 | }
27 | return false;
28 | }
29 |
30 | @Override
31 | protected boolean shouldApply(RuleImplementation rule, IParsedNode item) {
32 | return !rule.getNames().getTextItem().isEmpty() || isStrict;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/DistanceMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleDistanceIndexMatchType;
5 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
6 |
7 | public class DistanceMatcher extends ABaseMatcher {
8 |
9 | @Override
10 | protected boolean innerMatch(RuleImplementation rule, IParsedNode node) {
11 |
12 | int val = node.getDistance();
13 | if (rule.getDistanceCheckType() == RuleDistanceIndexMatchType.LESS) {
14 | if (val > rule.getDistance()) {
15 | return false;
16 | }
17 | }
18 | if (rule.getDistanceCheckType() == RuleDistanceIndexMatchType.MORE) {
19 | if (val < rule.getDistance()) {
20 | return false;
21 | }
22 | }
23 | if (rule.getDistanceCheckType() == RuleDistanceIndexMatchType.EQUALS) {
24 | if (rule.getDistance() != val) {
25 | return false;
26 | }
27 | }
28 | return true;
29 |
30 | }
31 |
32 | @Override
33 | protected boolean shouldApply(RuleImplementation rule, IParsedNode item) {
34 | return rule.getDistance() != 0;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/IMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 |
6 | public interface IMatcher {
7 | boolean match(final RuleImplementation rule, final IParsedNode item);
8 | }
9 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/IParentMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 |
6 | public interface IParentMatcher {
7 | boolean isMatch(RuleImplementation rule, IParsedNode parent, IParsedNode child);
8 | }
9 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/IndexMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleDistanceIndexMatchType;
5 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
6 |
7 | public class IndexMatcher extends ABaseMatcher {
8 |
9 | @Override
10 | protected boolean innerMatch(RuleImplementation rule, IParsedNode node) {
11 | if (rule.getIndex() > 0) {
12 | int val = node.getIndex();
13 | if (rule.getIndexCheckType() == RuleDistanceIndexMatchType.LESS) {
14 | if (val > rule.getIndex()) {
15 | return false;
16 | }
17 | }
18 | if (rule.getIndexCheckType() == RuleDistanceIndexMatchType.EQUALS) {
19 | if (val != rule.getIndex()) {
20 | return false;
21 | }
22 | }
23 | if (rule.getIndexCheckType() == RuleDistanceIndexMatchType.MORE) {
24 | if (rule.getIndex() < val) {
25 | return false;
26 | }
27 | }
28 |
29 | }
30 | if (rule.getIndex() < 0) {
31 | int val = node.getIndex2();
32 | if (rule.getIndexCheckType() == RuleDistanceIndexMatchType.LESS) {
33 | if (val > rule.getIndex()) {
34 | return false;
35 | }
36 | }
37 | if (rule.getIndexCheckType() == RuleDistanceIndexMatchType.EQUALS) {
38 | if (val != rule.getIndex()) {
39 | return false;
40 | }
41 | }
42 | if (rule.getIndexCheckType() == RuleDistanceIndexMatchType.MORE) {
43 | if (rule.getIndex() < val) {
44 | return false;
45 | }
46 | }
47 |
48 | }
49 | return true;
50 |
51 | }
52 |
53 | @Override
54 | protected boolean shouldApply(RuleImplementation rule, IParsedNode item) {
55 | return rule.getIndex() != 0;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/NodeNameAndOrClassMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 |
6 | public class NodeNameAndOrClassMatcher implements IMatcher {
7 |
8 | private final IMatcher classMatcher = new ClassNameMatcher();
9 | private final IMatcher textMatcher = new TextNameMatcher();
10 |
11 | @Override
12 | public boolean match(RuleImplementation rule, IParsedNode item) {
13 | return this.classMatcher.match(rule, item) && this.textMatcher.match(rule, item);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/ParentsMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 |
6 | public class ParentsMatcher implements IParentMatcher {
7 |
8 | @Override
9 | public boolean isMatch(RuleImplementation rule, IParsedNode parent, IParsedNode child) {
10 | IParsedNode parent1 = parent.getControlFlowParent();
11 | IParsedNode parent2 = child.getControlFlowParent();
12 |
13 | if (parent1 == null || parent2 == null) {
14 | return false;
15 | }
16 | return parent.getControlFlowParent().getItem() == child.getControlFlowParent().getItem();
17 |
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/RulesMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.sonar.plugins.tsql.antlr.IParsedNode;
4 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
5 | import org.sonar.plugins.tsql.checks.custom.RuleMatchType;
6 |
7 | public class RulesMatcher {
8 |
9 | private final IMatcher[] matchers = new IMatcher[] { new DistanceMatcher(), new IndexMatcher() };
10 | private final IMatcher classNamesMatcher = new ClassNameMatcher();
11 | private final IMatcher textMatcher = new TextNameMatcher();
12 |
13 | private final IParentMatcher sameParentsMatcher = new ParentsMatcher();
14 | private final IParentMatcher sameTextMatcher = new SameTextMatcher();
15 |
16 | public boolean match(RuleImplementation rule, IParsedNode parent, IParsedNode node) {
17 |
18 | for (final IMatcher matcher : this.matchers) {
19 | if (!matcher.match(rule, node)) {
20 | return false;
21 | }
22 | }
23 |
24 | final RuleMatchType type = rule.getRuleMatchType();
25 |
26 | boolean classMatch = classNamesMatcher.match(rule, node);
27 | boolean textMatch = textMatcher.match(rule, node);
28 | switch (type) {
29 | case DEFAULT:
30 | case CLASS_ONLY:
31 | return classMatch;
32 | case TEXT_AND_CLASS:
33 | return classMatch && textMatch;
34 | case TEXT_ONLY:
35 | return textMatch;
36 | case FULL:
37 | if (parent == null) {
38 | throw new IllegalArgumentException("Can't do full check as parent is null");
39 | }
40 | boolean sameText = sameTextMatcher.isMatch(rule, parent, node);
41 | return textMatch && classMatch && sameText;
42 | case STRICT:
43 | if (parent == null) {
44 | throw new IllegalArgumentException("Can't do strict check as parent is null");
45 | }
46 | return textMatch && classMatch && sameTextMatcher.isMatch(rule, parent, node)
47 | && sameParentsMatcher.isMatch(rule, node, parent);
48 | default:
49 | break;
50 | }
51 | return false;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/SameTextMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.sonar.plugins.tsql.antlr.IParsedNode;
5 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
6 |
7 | public class SameTextMatcher implements IParentMatcher {
8 |
9 | @Override
10 | public boolean isMatch(RuleImplementation rule, IParsedNode parent, IParsedNode child) {
11 | String text1 = child.getText();
12 | String text2 = parent.getText();
13 |
14 | return StringUtils.contains(text1, text2) || StringUtils.contains(text2, text1);
15 |
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/nodes/matchers/TextNameMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.sonar.plugins.tsql.antlr.IParsedNode;
5 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
6 | import org.sonar.plugins.tsql.checks.custom.TextCheckType;
7 |
8 | public class TextNameMatcher extends ABaseMatcher {
9 | private final boolean isStrict;
10 |
11 | public TextNameMatcher(boolean isStrict) {
12 | this.isStrict = isStrict;
13 | }
14 |
15 | public TextNameMatcher() {
16 | this(false);
17 | }
18 |
19 | @Override
20 | protected boolean innerMatch(RuleImplementation rule, IParsedNode item) {
21 | final TextCheckType type = rule.getTextCheckType();
22 |
23 | final String text = item.getText();
24 |
25 | for (final String searchItem : rule.getTextToFind().getTextItem()) {
26 | switch (type) {
27 | case DEFAULT:
28 | case CONTAINS:
29 | if (StringUtils.containsIgnoreCase(text, searchItem)) {
30 | return true;
31 | }
32 | break;
33 |
34 | case REGEXP:
35 | if (text.matches(searchItem)) {
36 | return true;
37 | }
38 | break;
39 | case STRICT:
40 | if (text.equalsIgnoreCase(searchItem)) {
41 | return true;
42 | }
43 | break;
44 | default:
45 | break;
46 | }
47 | }
48 | return false;
49 | }
50 |
51 | @Override
52 | protected boolean shouldApply(RuleImplementation rule, IParsedNode item) {
53 | return !rule.getTextToFind().getTextItem().isEmpty() || isStrict;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/visitors/CComplexityVisitor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.visitors;
2 |
3 | import static java.lang.String.format;
4 |
5 | import org.antlr.tsql.TSqlParser.Search_condition_notContext;
6 | import org.antlr.tsql.TSqlParser.Try_catch_statementContext;
7 | import org.antlr.v4.runtime.tree.ParseTree;
8 | import org.sonar.api.batch.fs.InputFile;
9 | import org.sonar.api.batch.sensor.SensorContext;
10 | import org.sonar.api.measures.CoreMetrics;
11 | import org.sonar.api.utils.log.Logger;
12 | import org.sonar.api.utils.log.Loggers;
13 | import org.sonar.plugins.tsql.antlr.AntlrContext;
14 |
15 | public class CComplexityVisitor implements IParseTreeItemVisitor {
16 | int complexity = 1;
17 |
18 | public int getMeasure() {
19 | return complexity;
20 | }
21 |
22 | private static final Logger LOGGER = Loggers.get(CComplexityVisitor.class);
23 |
24 | @Override
25 | public void apply(final ParseTree tree) {
26 | final Class extends ParseTree> classz = tree.getClass();
27 | if (Search_condition_notContext.class.equals(classz)) {
28 | complexity++;
29 | }
30 |
31 | if (Try_catch_statementContext.class.equals(classz)) {
32 | complexity++;
33 | }
34 |
35 | }
36 |
37 | @Override
38 | public void fillContext(SensorContext sensorContext, AntlrContext antrlContext) {
39 |
40 | final InputFile file = antrlContext.getFile();
41 | synchronized (sensorContext) {
42 | try {
43 | sensorContext.newMeasure().on(file).forMetric(CoreMetrics.COMPLEXITY).withValue(complexity)
44 | .save();
45 | } catch (final Throwable e) {
46 | LOGGER.warn(format("Unexpected adding complexity measures on file %s", file.absolutePath()), e);
47 | }
48 | }
49 |
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/visitors/ComplexityVisitor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.visitors;
2 |
3 | import static java.lang.String.format;
4 |
5 | import org.antlr.tsql.TSqlParser.Dml_clauseContext;
6 | import org.antlr.tsql.TSqlParser.Function_callContext;
7 | import org.antlr.tsql.TSqlParser.Join_partContext;
8 | import org.antlr.tsql.TSqlParser.Order_by_expressionContext;
9 | import org.antlr.tsql.TSqlParser.Search_condition_notContext;
10 | import org.antlr.tsql.TSqlParser.Select_list_elemContext;
11 | import org.antlr.tsql.TSqlParser.Sql_unionContext;
12 | import org.antlr.v4.runtime.tree.ParseTree;
13 | import org.sonar.api.batch.fs.InputFile;
14 | import org.sonar.api.batch.sensor.SensorContext;
15 | import org.sonar.api.measures.CoreMetrics;
16 | import org.sonar.api.utils.log.Logger;
17 | import org.sonar.api.utils.log.Loggers;
18 | import org.sonar.plugins.tsql.antlr.AntlrContext;
19 |
20 | public class ComplexityVisitor implements IParseTreeItemVisitor {
21 | int complexity = 0;
22 |
23 | private static final Logger LOGGER = Loggers.get(ComplexityVisitor.class);
24 |
25 | public int getMeasure() {
26 | return complexity;
27 | }
28 |
29 | @Override
30 | public void apply(final ParseTree tree) {
31 | final Class extends ParseTree> classz = tree.getClass();
32 | if (Sql_unionContext.class.equals(classz)) {
33 | this.complexity++;
34 | }
35 | if (Function_callContext.class.isAssignableFrom(classz)) {
36 | this.complexity++;
37 | }
38 | if (Join_partContext.class.equals(classz)) {
39 | this.complexity++;
40 | }
41 | if (Order_by_expressionContext.class.equals(classz)) {
42 | this.complexity++;
43 | }
44 | if (Select_list_elemContext.class.equals(classz)) {
45 | this.complexity++;
46 | }
47 | if (Search_condition_notContext.class.equals(classz)) {
48 | this.complexity++;
49 | }
50 | if (Dml_clauseContext.class.equals(classz)) {
51 | this.complexity++;
52 | }
53 |
54 | }
55 |
56 | @Override
57 | public void fillContext(SensorContext sensorContext, AntlrContext antrlContext) {
58 | final InputFile file = antrlContext.getFile();
59 | synchronized (sensorContext) {
60 | try {
61 | sensorContext.newMeasure().on(file).forMetric(CoreMetrics.COGNITIVE_COMPLEXITY)
62 | .withValue(complexity).save();
63 | } catch (final Throwable e) {
64 | LOGGER.warn(format("Unexpected adding cognitive complexity measures on file %s", file.absolutePath()),
65 | e);
66 | }
67 | }
68 |
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/visitors/CustomRulesVisitor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.visitors;
2 |
3 | import java.util.HashMap;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import org.antlr.v4.runtime.tree.ParseTree;
9 | import org.sonar.api.batch.fs.InputFile;
10 | import org.sonar.api.batch.sensor.SensorContext;
11 | import org.sonar.plugins.tsql.antlr.AntlrContext;
12 | import org.sonar.plugins.tsql.antlr.CandidateNode;
13 | import org.sonar.plugins.tsql.antlr.CandidateRule;
14 | import org.sonar.plugins.tsql.antlr.issues.CustomIssuesProvider;
15 | import org.sonar.plugins.tsql.antlr.nodes.ParsedNode;
16 | import org.sonar.plugins.tsql.antlr.nodes.matchers.IMatcher;
17 | import org.sonar.plugins.tsql.antlr.nodes.matchers.NodeNameAndOrClassMatcher;
18 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
19 | import org.sonar.plugins.tsql.checks.custom.RuleMode;
20 | import org.sonar.plugins.tsql.rules.issues.DefaultIssuesFiller;
21 | import org.sonar.plugins.tsql.rules.issues.IIssuesFiller;
22 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
23 |
24 | public class CustomRulesVisitor implements IParseTreeItemVisitor {
25 |
26 | private final Map groupedNodes = new HashMap<>();
27 | private final List singleNodes = new LinkedList<>();
28 |
29 | private final IMatcher matcher = new NodeNameAndOrClassMatcher();
30 | private final CandidateRule[] rules;
31 |
32 | private final IIssuesFiller filler = new DefaultIssuesFiller();
33 | private final CustomIssuesProvider issuesProvider = new CustomIssuesProvider();
34 |
35 | public CustomRulesVisitor(final CandidateRule... rules) {
36 | this.rules = rules;
37 | }
38 |
39 | @Override
40 | public void apply(final ParseTree tree) {
41 | final ParsedNode parsedNode = new org.sonar.plugins.tsql.antlr.nodes.ParsedNode(tree);
42 |
43 | for (final CandidateRule rule : this.rules) {
44 |
45 | final RuleImplementation ruleImplemention = rule.getRuleImplementation();
46 | if (matcher.match(ruleImplemention, parsedNode)) {
47 | final CandidateNode node = new CandidateNode(rule, parsedNode);
48 | if (ruleImplemention.getRuleMode() == RuleMode.GROUP) {
49 | final String name = tree.getText();
50 | groupedNodes.putIfAbsent(name, node);
51 | } else {
52 | singleNodes.add(node);
53 | }
54 | }
55 |
56 | }
57 |
58 | }
59 |
60 | public CandidateNode[] getNodes() {
61 | singleNodes.addAll(groupedNodes.values());
62 | return singleNodes.toArray(new CandidateNode[0]);
63 | }
64 |
65 | @Override
66 | public void fillContext(SensorContext sensorContext, AntlrContext fillerRequest) {
67 | final InputFile file = fillerRequest.getFile();
68 | TsqlIssue[] foundIssues = issuesProvider.getIssues(fillerRequest, this.getNodes());
69 | filler.fill(sensorContext, file, foundIssues);
70 |
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/visitors/CustomTreeVisitor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.visitors;
2 |
3 | import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
4 | import org.antlr.v4.runtime.tree.ParseTree;
5 | import org.sonar.api.batch.sensor.SensorContext;
6 | import org.sonar.plugins.tsql.antlr.AntlrContext;
7 |
8 | @SuppressWarnings("rawtypes")
9 | public class CustomTreeVisitor extends AbstractParseTreeVisitor implements IParseTreeItemVisitor {
10 |
11 | private final IParseTreeItemVisitor[] visitors;
12 |
13 | public CustomTreeVisitor(final IParseTreeItemVisitor... visitors) {
14 | this.visitors = visitors;
15 | }
16 |
17 | @Override
18 | public Object visit(final ParseTree tree) {
19 |
20 | final int n = tree.getChildCount();
21 |
22 | for (int i = 0; i < n; i++) {
23 | final ParseTree c = tree.getChild(i);
24 | visit(c);
25 | }
26 | for (final IParseTreeItemVisitor visitor : this.visitors) {
27 | visitor.apply(tree);
28 | }
29 |
30 | return null;
31 | }
32 |
33 | @Override
34 | public void fillContext(SensorContext context, AntlrContext antlrContext) {
35 | this.apply(antlrContext.getRoot());
36 | for (final IParseTreeItemVisitor visitor : this.visitors) {
37 | visitor.fillContext(context, antlrContext);
38 | }
39 | }
40 |
41 | @Override
42 | public void apply(ParseTree tree) {
43 | this.visit(tree);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/antlr/visitors/IParseTreeItemVisitor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.visitors;
2 |
3 | import org.antlr.v4.runtime.tree.ParseTree;
4 | import org.sonar.api.batch.sensor.SensorContext;
5 | import org.sonar.plugins.tsql.antlr.AntlrContext;
6 |
7 | public interface IParseTreeItemVisitor {
8 | void apply(ParseTree tree);
9 |
10 | void fillContext(SensorContext context, AntlrContext antlrContext);
11 | }
12 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/CustomAllChecksProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.checks;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.apache.commons.lang3.StringUtils;
7 | import org.sonar.api.batch.rule.Severity;
8 | import org.sonar.api.batch.sensor.SensorContext;
9 | import org.sonar.api.config.Configuration;
10 | import org.sonar.api.rules.RuleType;
11 | import org.sonar.api.utils.log.Logger;
12 | import org.sonar.api.utils.log.Loggers;
13 | import org.sonar.plugins.tsql.Constants;
14 | import org.sonar.plugins.tsql.antlr.CandidateRule;
15 | import org.sonar.plugins.tsql.checks.custom.Rule;
16 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
17 |
18 | public class CustomAllChecksProvider {
19 |
20 | private final CustomUserChecksProvider provider = new CustomUserChecksProvider();
21 |
22 | private final CustomPluginChecks pluginChecksProvider = new CustomPluginChecks();
23 | private static final Logger LOGGER = Loggers.get(CustomAllChecksProvider.class);
24 |
25 | public CandidateRule[] getChecks(final SensorContext context) {
26 | final Configuration config = context.config();
27 | final boolean skipCustomRules = config.getBoolean(Constants.PLUGIN_SKIP_CUSTOM_RULES).orElse(false);
28 | final String baseDir = context.fileSystem().baseDir().getAbsolutePath();
29 |
30 | final String[] paths = config.getStringArray(Constants.PLUGIN_CUSTOM_RULES_PATH);
31 | final String rulesPrefix = config.get(Constants.PLUGIN_CUSTOM_RULES_PREFIX).orElse(".customRules");
32 |
33 | final List rules = new ArrayList<>();
34 |
35 | rules.addAll(provider.getRules(baseDir, rulesPrefix, paths).values());
36 |
37 | if (!skipCustomRules) {
38 | final SqlRules customRules = pluginChecksProvider.getRules();
39 | rules.add(customRules);
40 | }
41 |
42 | for (final SqlRules sqlRules : rules) {
43 | if (sqlRules.isIsAdhoc()) {
44 | for (final Rule r : sqlRules.getRule()) {
45 | context.newAdHocRule().description(r.getDescription()).engineId(sqlRules.getRepoKey())
46 | .ruleId(r.getKey()).type(RuleType.valueOf(r.getRuleType())).name(r.getName())
47 | .severity(Severity.valueOf(r.getSeverity())).save();
48 | }
49 | }
50 | }
51 |
52 | final SqlRules[] finalRules = rules.toArray(new SqlRules[0]);
53 |
54 | final CandidateRule[] candidateRules = convert(finalRules);
55 | LOGGER.info(String.format("Total %s custom rules repositories with total %s checks", rules.size(),
56 | candidateRules.length));
57 | return candidateRules;
58 |
59 | }
60 |
61 | private static CandidateRule[] convert(final SqlRules... rules) {
62 | final List convertedRules = new ArrayList<>();
63 | for (final SqlRules r : rules) {
64 | for (final Rule rule : r.getRule()) {
65 | convertedRules.add(new CandidateRule(r.getRepoKey(), rule, r.isIsAdhoc()));
66 | }
67 | }
68 | return convertedRules.toArray(new CandidateRule[0]);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/CustomPluginChecks.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gretard/sonar-tsql-plugin/aadb5598bbb183c12df997ee9f3e053f962ce0f7/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/CustomPluginChecks.java
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/CustomUserChecksProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.checks;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.nio.file.Files;
9 | import java.nio.file.Path;
10 | import java.util.HashMap;
11 | import java.util.LinkedList;
12 | import java.util.List;
13 | import java.util.Map;
14 | import java.util.stream.Stream;
15 |
16 | import javax.xml.bind.JAXBContext;
17 | import javax.xml.bind.JAXBException;
18 | import javax.xml.bind.Unmarshaller;
19 |
20 | import org.sonar.api.utils.log.Logger;
21 | import org.sonar.api.utils.log.Loggers;
22 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
23 |
24 | public class CustomUserChecksProvider {
25 | private static final Logger LOGGER = Loggers.get(CustomUserChecksProvider.class);
26 |
27 | public Map getRules(final String baseDir, final String prefix, final String... paths) {
28 |
29 | final HashMap rulesRepositories = new HashMap<>();
30 |
31 | final List updatedPaths = new LinkedList<>();
32 | for (final String path : paths) {
33 | File f = new File(path);
34 | if (baseDir != null && !f.isAbsolute()) {
35 | f = new File(baseDir, path);
36 | }
37 | try (final Stream stream = Files.walk(f.toPath())) {
38 | stream.filter(x -> x.toFile().isFile() && x.toString().contains(prefix))
39 | .forEach(x -> updatedPaths.add(x.toFile().getAbsolutePath()));
40 | } catch (IOException e) {
41 | LOGGER.info(String.format("Unexpected error ocurred while reading: %s", f.getAbsolutePath()), e);
42 | }
43 | }
44 |
45 | for (final String path : updatedPaths) {
46 |
47 | try (final InputStream file = new FileInputStream(path)) {
48 | final JAXBContext jaxbContext = JAXBContext.newInstance(SqlRules.class);
49 | final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
50 | final SqlRules rules = (SqlRules) jaxbUnmarshaller.unmarshal(file);
51 | rulesRepositories.put(path, rules);
52 | LOGGER.info(String.format("Read %s rules ok at: %s", rules.getRule().size(), path));
53 | } catch (final FileNotFoundException e) {
54 | LOGGER.info("Custom rule file not found at: " + path);
55 | } catch (final JAXBException e) {
56 | LOGGER.info("Was not able to read custom rule file not found at: " + path);
57 | } catch (final IOException e) {
58 | LOGGER.info("Was not able to close custom rule file at: " + path);
59 | }
60 | }
61 |
62 | return rulesRepositories;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/ChildrenRules.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}ruleImplementation" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "ruleImplementation"
41 | })
42 | @XmlRootElement(name = "childrenRules")
43 | public class ChildrenRules {
44 |
45 | protected List ruleImplementation;
46 |
47 | /**
48 | * Gets the value of the ruleImplementation property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the ruleImplementation property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getRuleImplementation().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link RuleImplementation }
66 | *
67 | *
68 | */
69 | public List getRuleImplementation() {
70 | if (ruleImplementation == null) {
71 | ruleImplementation = new ArrayList();
72 | }
73 | return this.ruleImplementation;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/CompliantRulesCodeExamples.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}ruleCodeExample" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "ruleCodeExample"
41 | })
42 | @XmlRootElement(name = "compliantRulesCodeExamples")
43 | public class CompliantRulesCodeExamples {
44 |
45 | protected List ruleCodeExample;
46 |
47 | /**
48 | * Gets the value of the ruleCodeExample property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the ruleCodeExample property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getRuleCodeExample().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link String }
66 | *
67 | *
68 | */
69 | public List getRuleCodeExample() {
70 | if (ruleCodeExample == null) {
71 | ruleCodeExample = new ArrayList();
72 | }
73 | return this.ruleCodeExample;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/Names.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}textItem" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "textItem"
41 | })
42 | @XmlRootElement(name = "names")
43 | public class Names {
44 |
45 | protected List textItem;
46 |
47 | /**
48 | * Gets the value of the textItem property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the textItem property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getTextItem().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link String }
66 | *
67 | *
68 | */
69 | public List getTextItem() {
70 | if (textItem == null) {
71 | textItem = new ArrayList();
72 | }
73 | return this.textItem;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/ParentRules.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}ruleImplementation" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "ruleImplementation"
41 | })
42 | @XmlRootElement(name = "parentRules")
43 | public class ParentRules {
44 |
45 | protected List ruleImplementation;
46 |
47 | /**
48 | * Gets the value of the ruleImplementation property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the ruleImplementation property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getRuleImplementation().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link RuleImplementation }
66 | *
67 | *
68 | */
69 | public List getRuleImplementation() {
70 | if (ruleImplementation == null) {
71 | ruleImplementation = new ArrayList();
72 | }
73 | return this.ruleImplementation;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/RuleDistanceIndexMatchType.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import javax.xml.bind.annotation.XmlEnum;
12 | import javax.xml.bind.annotation.XmlEnumValue;
13 | import javax.xml.bind.annotation.XmlType;
14 |
15 |
16 | /**
17 | * Java class for ruleDistanceIndexMatchType.
18 | *
19 | *
The following schema fragment specifies the expected content contained within this class.
20 | *
21 | *
22 | * <simpleType name="ruleDistanceIndexMatchType">
23 | * <restriction base="{http://www.w3.org/2001/XMLSchema}string">
24 | * <enumeration value="Default"/>
25 | * <enumeration value="More"/>
26 | * <enumeration value="Less"/>
27 | * <enumeration value="Equals"/>
28 | * </restriction>
29 | * </simpleType>
30 | *
31 | *
32 | */
33 | @XmlType(name = "ruleDistanceIndexMatchType")
34 | @XmlEnum
35 | public enum RuleDistanceIndexMatchType {
36 |
37 | @XmlEnumValue("Default")
38 | DEFAULT("Default"),
39 | @XmlEnumValue("More")
40 | MORE("More"),
41 | @XmlEnumValue("Less")
42 | LESS("Less"),
43 | @XmlEnumValue("Equals")
44 | EQUALS("Equals");
45 | private final String value;
46 |
47 | RuleDistanceIndexMatchType(String v) {
48 | value = v;
49 | }
50 |
51 | public String value() {
52 | return value;
53 | }
54 |
55 | public static RuleDistanceIndexMatchType fromValue(String v) {
56 | for (RuleDistanceIndexMatchType c: RuleDistanceIndexMatchType.values()) {
57 | if (c.value.equals(v)) {
58 | return c;
59 | }
60 | }
61 | throw new IllegalArgumentException(v);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/RuleMatchType.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import javax.xml.bind.annotation.XmlEnum;
12 | import javax.xml.bind.annotation.XmlEnumValue;
13 | import javax.xml.bind.annotation.XmlType;
14 |
15 |
16 | /**
17 | * Java class for ruleMatchType.
18 | *
19 | *
The following schema fragment specifies the expected content contained within this class.
20 | *
21 | *
22 | * <simpleType name="ruleMatchType">
23 | * <restriction base="{http://www.w3.org/2001/XMLSchema}string">
24 | * <enumeration value="Default"/>
25 | * <enumeration value="Full"/>
26 | * <enumeration value="TextOnly"/>
27 | * <enumeration value="TextAndClass"/>
28 | * <enumeration value="ClassOnly"/>
29 | * <enumeration value="Strict"/>
30 | * </restriction>
31 | * </simpleType>
32 | *
33 | *
34 | */
35 | @XmlType(name = "ruleMatchType")
36 | @XmlEnum
37 | public enum RuleMatchType {
38 |
39 | @XmlEnumValue("Default")
40 | DEFAULT("Default"),
41 | @XmlEnumValue("Full")
42 | FULL("Full"),
43 | @XmlEnumValue("TextOnly")
44 | TEXT_ONLY("TextOnly"),
45 | @XmlEnumValue("TextAndClass")
46 | TEXT_AND_CLASS("TextAndClass"),
47 | @XmlEnumValue("ClassOnly")
48 | CLASS_ONLY("ClassOnly"),
49 | @XmlEnumValue("Strict")
50 | STRICT("Strict");
51 | private final String value;
52 |
53 | RuleMatchType(String v) {
54 | value = v;
55 | }
56 |
57 | public String value() {
58 | return value;
59 | }
60 |
61 | public static RuleMatchType fromValue(String v) {
62 | for (RuleMatchType c: RuleMatchType.values()) {
63 | if (c.value.equals(v)) {
64 | return c;
65 | }
66 | }
67 | throw new IllegalArgumentException(v);
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/RuleMode.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import javax.xml.bind.annotation.XmlEnum;
12 | import javax.xml.bind.annotation.XmlEnumValue;
13 | import javax.xml.bind.annotation.XmlType;
14 |
15 |
16 | /**
17 | * Java class for ruleMode.
18 | *
19 | *
The following schema fragment specifies the expected content contained within this class.
20 | *
21 | *
22 | * <simpleType name="ruleMode">
23 | * <restriction base="{http://www.w3.org/2001/XMLSchema}string">
24 | * <enumeration value="Default"/>
25 | * <enumeration value="Group"/>
26 | * <enumeration value="Single"/>
27 | * </restriction>
28 | * </simpleType>
29 | *
30 | *
31 | */
32 | @XmlType(name = "ruleMode")
33 | @XmlEnum
34 | public enum RuleMode {
35 |
36 | @XmlEnumValue("Default")
37 | DEFAULT("Default"),
38 | @XmlEnumValue("Group")
39 | GROUP("Group"),
40 | @XmlEnumValue("Single")
41 | SINGLE("Single");
42 | private final String value;
43 |
44 | RuleMode(String v) {
45 | value = v;
46 | }
47 |
48 | public String value() {
49 | return value;
50 | }
51 |
52 | public static RuleMode fromValue(String v) {
53 | for (RuleMode c: RuleMode.values()) {
54 | if (c.value.equals(v)) {
55 | return c;
56 | }
57 | }
58 | throw new IllegalArgumentException(v);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/RuleResultType.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import javax.xml.bind.annotation.XmlEnum;
12 | import javax.xml.bind.annotation.XmlEnumValue;
13 | import javax.xml.bind.annotation.XmlType;
14 |
15 |
16 | /**
17 | * Java class for ruleResultType.
18 | *
19 | *
The following schema fragment specifies the expected content contained within this class.
20 | *
21 | *
22 | * <simpleType name="ruleResultType">
23 | * <restriction base="{http://www.w3.org/2001/XMLSchema}string">
24 | * <enumeration value="Default"/>
25 | * <enumeration value="FailIfFound"/>
26 | * <enumeration value="FailIfNotFound"/>
27 | * <enumeration value="FailIfLessFound"/>
28 | * <enumeration value="FailIfMoreFound"/>
29 | * <enumeration value="SkipIfFound"/>
30 | * <enumeration value="SkipIfNotFound"/>
31 | * </restriction>
32 | * </simpleType>
33 | *
34 | *
35 | */
36 | @XmlType(name = "ruleResultType")
37 | @XmlEnum
38 | public enum RuleResultType {
39 |
40 | @XmlEnumValue("Default")
41 | DEFAULT("Default"),
42 | @XmlEnumValue("FailIfFound")
43 | FAIL_IF_FOUND("FailIfFound"),
44 | @XmlEnumValue("FailIfNotFound")
45 | FAIL_IF_NOT_FOUND("FailIfNotFound"),
46 | @XmlEnumValue("FailIfLessFound")
47 | FAIL_IF_LESS_FOUND("FailIfLessFound"),
48 | @XmlEnumValue("FailIfMoreFound")
49 | FAIL_IF_MORE_FOUND("FailIfMoreFound"),
50 | @XmlEnumValue("SkipIfFound")
51 | SKIP_IF_FOUND("SkipIfFound"),
52 | @XmlEnumValue("SkipIfNotFound")
53 | SKIP_IF_NOT_FOUND("SkipIfNotFound");
54 | private final String value;
55 |
56 | RuleResultType(String v) {
57 | value = v;
58 | }
59 |
60 | public String value() {
61 | return value;
62 | }
63 |
64 | public static RuleResultType fromValue(String v) {
65 | for (RuleResultType c: RuleResultType.values()) {
66 | if (c.value.equals(v)) {
67 | return c;
68 | }
69 | }
70 | throw new IllegalArgumentException(v);
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/SiblingsRules.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}ruleImplementation" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "ruleImplementation"
41 | })
42 | @XmlRootElement(name = "siblingsRules")
43 | public class SiblingsRules {
44 |
45 | protected List ruleImplementation;
46 |
47 | /**
48 | * Gets the value of the ruleImplementation property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the ruleImplementation property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getRuleImplementation().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link RuleImplementation }
66 | *
67 | *
68 | */
69 | public List getRuleImplementation() {
70 | if (ruleImplementation == null) {
71 | ruleImplementation = new ArrayList();
72 | }
73 | return this.ruleImplementation;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/TextCheckType.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import javax.xml.bind.annotation.XmlEnum;
12 | import javax.xml.bind.annotation.XmlEnumValue;
13 | import javax.xml.bind.annotation.XmlType;
14 |
15 |
16 | /**
17 | * Java class for textCheckType.
18 | *
19 | *
The following schema fragment specifies the expected content contained within this class.
20 | *
21 | *
22 | * <simpleType name="textCheckType">
23 | * <restriction base="{http://www.w3.org/2001/XMLSchema}string">
24 | * <enumeration value="Default"/>
25 | * <enumeration value="Contains"/>
26 | * <enumeration value="Regexp"/>
27 | * <enumeration value="Strict"/>
28 | * </restriction>
29 | * </simpleType>
30 | *
31 | *
32 | */
33 | @XmlType(name = "textCheckType")
34 | @XmlEnum
35 | public enum TextCheckType {
36 |
37 | @XmlEnumValue("Default")
38 | DEFAULT("Default"),
39 | @XmlEnumValue("Contains")
40 | CONTAINS("Contains"),
41 | @XmlEnumValue("Regexp")
42 | REGEXP("Regexp"),
43 | @XmlEnumValue("Strict")
44 | STRICT("Strict");
45 | private final String value;
46 |
47 | TextCheckType(String v) {
48 | value = v;
49 | }
50 |
51 | public String value() {
52 | return value;
53 | }
54 |
55 | public static TextCheckType fromValue(String v) {
56 | for (TextCheckType c: TextCheckType.values()) {
57 | if (c.value.equals(v)) {
58 | return c;
59 | }
60 | }
61 | throw new IllegalArgumentException(v);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/TextToFind.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}textItem" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "textItem"
41 | })
42 | @XmlRootElement(name = "textToFind")
43 | public class TextToFind {
44 |
45 | protected List textItem;
46 |
47 | /**
48 | * Gets the value of the textItem property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the textItem property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getTextItem().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link String }
66 | *
67 | *
68 | */
69 | public List getTextItem() {
70 | if (textItem == null) {
71 | textItem = new ArrayList();
72 | }
73 | return this.textItem;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/UsesRules.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}ruleImplementation" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "ruleImplementation"
41 | })
42 | @XmlRootElement(name = "usesRules")
43 | public class UsesRules {
44 |
45 | protected List ruleImplementation;
46 |
47 | /**
48 | * Gets the value of the ruleImplementation property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the ruleImplementation property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getRuleImplementation().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link RuleImplementation }
66 | *
67 | *
68 | */
69 | public List getRuleImplementation() {
70 | if (ruleImplementation == null) {
71 | ruleImplementation = new ArrayList();
72 | }
73 | return this.ruleImplementation;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/checks/custom/ViolatingRulesCodeExamples.java:
--------------------------------------------------------------------------------
1 | //
2 | // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
3 | // See http://java.sun.com/xml/jaxb
4 | // Any modifications to this file will be lost upon recompilation of the source schema.
5 | // Generated on: 2018.12.22 at 03:20:06 PM EET
6 | //
7 |
8 |
9 | package org.sonar.plugins.tsql.checks.custom;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import javax.xml.bind.annotation.XmlAccessType;
14 | import javax.xml.bind.annotation.XmlAccessorType;
15 | import javax.xml.bind.annotation.XmlRootElement;
16 | import javax.xml.bind.annotation.XmlType;
17 |
18 |
19 | /**
20 | * Java class for anonymous complex type.
21 | *
22 | *
The following schema fragment specifies the expected content contained within this class.
23 | *
24 | *
25 | * <complexType>
26 | * <complexContent>
27 | * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
28 | * <sequence>
29 | * <element ref="{}ruleCodeExample" maxOccurs="unbounded" minOccurs="0"/>
30 | * </sequence>
31 | * </restriction>
32 | * </complexContent>
33 | * </complexType>
34 | *
35 | *
36 | *
37 | */
38 | @XmlAccessorType(XmlAccessType.FIELD)
39 | @XmlType(name = "", propOrder = {
40 | "ruleCodeExample"
41 | })
42 | @XmlRootElement(name = "violatingRulesCodeExamples")
43 | public class ViolatingRulesCodeExamples {
44 |
45 | protected List ruleCodeExample;
46 |
47 | /**
48 | * Gets the value of the ruleCodeExample property.
49 | *
50 | *
51 | * This accessor method returns a reference to the live list,
52 | * not a snapshot. Therefore any modification you make to the
53 | * returned list will be present inside the JAXB object.
54 | * This is why there is not a set
method for the ruleCodeExample property.
55 | *
56 | *
57 | * For example, to add a new item, do as follows:
58 | *
59 | * getRuleCodeExample().add(newItem);
60 | *
61 | *
62 | *
63 | *
64 | * Objects of the following type(s) are allowed in the list
65 | * {@link String }
66 | *
67 | *
68 | */
69 | public List getRuleCodeExample() {
70 | if (ruleCodeExample == null) {
71 | ruleCodeExample = new ArrayList();
72 | }
73 | return this.ruleCodeExample;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/coverage/CoveredLinesReport.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.coverage;
2 |
3 | public class CoveredLinesReport {
4 |
5 | private final String file;
6 |
7 | private final LineInfo[] hitLines;
8 |
9 | public CoveredLinesReport(String file, LineInfo... infos) {
10 | this.file = file;
11 | this.hitLines = infos;
12 | }
13 |
14 | public String getFile() {
15 | return file;
16 | }
17 |
18 | public LineInfo[] getHitLines() {
19 | return hitLines;
20 | }
21 |
22 | public static class LineInfo {
23 | private final int line;
24 | private final int hitsCount;
25 |
26 | public LineInfo(final int line, final int hits) {
27 | this.line = line;
28 | this.hitsCount = hits;
29 | }
30 |
31 | public int getLine() {
32 | return line;
33 | }
34 |
35 | public int getHitsCount() {
36 | return hitsCount;
37 | }
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/coverage/FileNamesMatcher.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.coverage;
2 |
3 | import java.util.LinkedList;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.Map.Entry;
7 |
8 | import org.apache.commons.io.FilenameUtils;
9 |
10 | public class FileNamesMatcher {
11 | private final NameNormalizer nameNormalizer = new NameNormalizer();
12 |
13 | public CoveredLinesReport[] match(String fileName, String parentDirName, Map coverage) {
14 | final String name = FilenameUtils.removeExtension(fileName);
15 | final String normalizedName = nameNormalizer.normalize(name);
16 | String schema = nameNormalizer.normalize(parentDirName);
17 | String objName = normalizedName;
18 |
19 | if (normalizedName.contains(".")) {
20 | String[] names = name.split("\\.");
21 | objName = names[names.length-1];
22 | schema = names[names.length-2];
23 | }
24 | List possibleMatches = new LinkedList();
25 | for (Entry info : coverage.entrySet()) {
26 | if (info.getKey().equals(normalizedName)) {
27 | possibleMatches.add(info.getValue());
28 | break;
29 | }
30 | if (info.getKey().equals(schema+"."+objName)) {
31 | possibleMatches.add(info.getValue());
32 | break;
33 | }
34 | if (info.getKey().contains(objName)) {
35 | possibleMatches.add(info.getValue());
36 | }
37 |
38 | }
39 | return possibleMatches.toArray(new CoveredLinesReport[0]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/coverage/ICoveragProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.coverage;
2 |
3 | import java.util.Map;
4 |
5 | public interface ICoveragProvider {
6 | Map getHitLines();
7 | }
8 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/coverage/NameNormalizer.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.coverage;
2 |
3 | public class NameNormalizer {
4 | public String normalize(String name) {
5 | if (name == null) {
6 | return "";
7 | }
8 | return name.replace("[", "").replace("]", "").replace(" ", "").toLowerCase();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/languages/TSQLLanguage.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.languages;
2 |
3 | import org.sonar.api.config.Settings;
4 | import org.sonar.api.resources.AbstractLanguage;
5 | import org.sonar.plugins.tsql.Constants;
6 |
7 | public final class TSQLLanguage extends AbstractLanguage {
8 |
9 | public static final String NAME = "T-SQL";
10 |
11 | public static final String KEY = "tsql";
12 |
13 | public static final String[] DEFAULT_FILE_SUFFIXES = new String[] { ".sql" };
14 |
15 | private final Settings settings;
16 |
17 | public TSQLLanguage(final Settings settings) {
18 | super(KEY, NAME);
19 | this.settings = settings;
20 |
21 | }
22 |
23 | public String[] getFileSuffixes() {
24 | final String[] suffixes = settings.getStringArray(Constants.PLUGIN_SUFFIXES);
25 | if (suffixes == null || suffixes.length == 0) {
26 | return DEFAULT_FILE_SUFFIXES;
27 | }
28 | return suffixes;
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/languages/keywords/IKeywordsProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.languages.keywords;
2 |
3 | public interface IKeywordsProvider {
4 | boolean isKeyword(final String name);
5 | }
6 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/languages/keywords/KeywordsProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.languages.keywords;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStream;
5 | import java.io.InputStreamReader;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import org.apache.commons.lang3.StringUtils;
10 | import org.sonar.api.utils.log.Logger;
11 | import org.sonar.api.utils.log.Loggers;
12 | import org.sonar.plugins.tsql.sensors.CustomChecksSensor;
13 |
14 | public class KeywordsProvider implements IKeywordsProvider {
15 |
16 | private static final Logger LOGGER = Loggers.get(CustomChecksSensor.class);
17 |
18 | private final List keywords = new ArrayList();
19 |
20 | public KeywordsProvider() {
21 | this("/tsql.keywords", "/tsql.odbc.keywords");
22 | }
23 |
24 | public KeywordsProvider(final String... files) {
25 | for (final String file : files) {
26 | init(file);
27 | }
28 | }
29 |
30 | private void init(final String file) {
31 | try {
32 | final InputStream stream = this.getClass().getResourceAsStream(file);
33 |
34 | final BufferedReader br = new BufferedReader(new InputStreamReader(stream));
35 |
36 | for (String line; (line = br.readLine()) != null;) {
37 | if (!StringUtils.isEmpty(line)) {
38 | final String keyword = line.toUpperCase().trim();
39 | if (!this.keywords.contains(keyword)) {
40 | this.keywords.add(keyword);
41 | }
42 |
43 | }
44 | }
45 | } catch (final Throwable e) {
46 | LOGGER.warn(String.format("Error reading keywords file: %s", file), e);
47 | }
48 |
49 | }
50 |
51 | public boolean isKeyword(final String name) {
52 | return this.keywords.contains(name);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/lines/SourceLine.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.lines;
2 |
3 | public final class SourceLine {
4 |
5 | private final int count;
6 | private final int start;
7 | private final int end;
8 | private final int line;
9 |
10 | public SourceLine(final int line, final int count, final int start, final int end) {
11 | this.line = line;
12 | this.count = count;
13 | this.start = start;
14 | this.end = end;
15 |
16 | }
17 |
18 | @Override
19 | public String toString() {
20 | return "SourceLine [line=" + line + ", count=" + count + ", start=" + start + ", end=" + end + "]";
21 | }
22 |
23 | public int getLine() {
24 | return line;
25 | }
26 |
27 | public int getCount() {
28 | return count;
29 | }
30 |
31 | public int getEnd() {
32 | return end;
33 | }
34 |
35 | public int getStart() {
36 | return start;
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/lines/SourceLinesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.lines;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStream;
5 | import java.io.InputStreamReader;
6 | import java.nio.charset.Charset;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | import org.apache.commons.io.input.BOMInputStream;
11 | import org.sonar.api.utils.log.Logger;
12 | import org.sonar.api.utils.log.Loggers;
13 |
14 | public class SourceLinesProvider {
15 | private static final Logger LOGGER = Loggers.get(SourceLinesProvider.class);
16 |
17 | public SourceLine[] getLines(final InputStream inputStream, final Charset charset) {
18 | if (inputStream == null) {
19 | return new SourceLine[0];
20 | }
21 | final List sourceLines = new ArrayList<>();
22 |
23 | try (final BufferedReader bufferedReader = new BufferedReader(
24 | new InputStreamReader(new BOMInputStream(inputStream, false), charset))) {
25 | int totalLines = 1;
26 | int global = 0;
27 | int count = 0;
28 |
29 | int currentChar;
30 | while ((currentChar = bufferedReader.read()) != -1) {
31 |
32 | global++;
33 | count++;
34 | if (currentChar == 10) {
35 | sourceLines.add(new SourceLine(totalLines, count, global - count, global));
36 | totalLines++;
37 | count = 0;
38 | }
39 |
40 | }
41 | sourceLines.add(new SourceLine(totalLines, count, global - count, global));
42 | } catch (final Throwable e) {
43 | LOGGER.warn("Error occured reading file", e);
44 | }
45 |
46 | return sourceLines.toArray(new SourceLine[0]);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/predicates/AbsolutePathCaseInsensitivePredicate.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.predicates;
2 |
3 | import org.sonar.api.batch.fs.FilePredicate;
4 | import org.sonar.api.batch.fs.InputFile;
5 |
6 | public class AbsolutePathCaseInsensitivePredicate implements FilePredicate {
7 |
8 | private final String path;
9 |
10 | public AbsolutePathCaseInsensitivePredicate(final String path) {
11 | this.path = path.replace('\\', '/');
12 | }
13 |
14 | @Override
15 | public boolean apply(final InputFile inputFile) {
16 | return this.path.equalsIgnoreCase(inputFile.absolutePath().replace('\\', '/'));
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/definitions/BaseRulesDefinition.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.definitions;
2 |
3 | import java.io.InputStream;
4 | import java.nio.charset.StandardCharsets;
5 |
6 | import org.sonar.api.server.rule.RulesDefinition;
7 | import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
8 | import org.sonar.plugins.tsql.languages.TSQLLanguage;
9 |
10 | public abstract class BaseRulesDefinition implements RulesDefinition {
11 | private final String rulesPath;
12 | private final String repositoryName;
13 | private final String repositoryKey;
14 |
15 | public BaseRulesDefinition(String repositoryKey, String repositoryName, String rulesPath) {
16 | this.repositoryKey = repositoryKey;
17 | this.repositoryName = repositoryName;
18 | this.rulesPath = rulesPath;
19 |
20 | }
21 |
22 | private void defineRulesForLanguage(final Context context) {
23 | final NewRepository repository = context.createRepository(this.repositoryKey, TSQLLanguage.KEY)
24 | .setName(this.repositoryName);
25 |
26 | final InputStream rulesXml = this.getClass().getResourceAsStream(this.rulesPath);
27 | if (rulesXml != null) {
28 | final RulesDefinitionXmlLoader rulesLoader = new RulesDefinitionXmlLoader();
29 | rulesLoader.load(repository, rulesXml, StandardCharsets.UTF_8.name());
30 | }
31 |
32 | repository.done();
33 | }
34 |
35 | @Override
36 | public void define(final Context context) {
37 | defineRulesForLanguage(context);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/definitions/CodeGuardRulesDefinition.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.definitions;
2 |
3 | import org.sonar.plugins.tsql.Constants;
4 |
5 | public final class CodeGuardRulesDefinition extends BaseRulesDefinition {
6 |
7 | public CodeGuardRulesDefinition() {
8 | super(Constants.CG_REPO_KEY, Constants.CG_REPO_NAME, Constants.CG_RULES_FILE);
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/definitions/CustomUserChecksRulesDefinition.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.definitions;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.nio.charset.StandardCharsets;
8 | import java.util.Map;
9 |
10 | import org.sonar.api.config.Settings;
11 | import org.sonar.api.server.rule.RulesDefinition;
12 | import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
13 | import org.sonar.api.utils.log.Logger;
14 | import org.sonar.api.utils.log.Loggers;
15 | import org.sonar.plugins.tsql.Constants;
16 | import org.sonar.plugins.tsql.checks.CustomUserChecksProvider;
17 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
18 | import org.sonar.plugins.tsql.languages.TSQLLanguage;
19 |
20 | public class CustomUserChecksRulesDefinition implements RulesDefinition {
21 |
22 | private final Settings settings;
23 | private final CustomUserChecksProvider provider = new CustomUserChecksProvider();
24 |
25 | private static final Logger LOGGER = Loggers.get(CustomUserChecksRulesDefinition.class);
26 |
27 | public CustomUserChecksRulesDefinition(Settings settings) {
28 | this.settings = settings;
29 | }
30 |
31 | private void defineRulesForLanguage(final Context context) {
32 |
33 | final String[] paths = settings.getStringArray(Constants.PLUGIN_CUSTOM_RULES_PATH);
34 | final String rulesPrefix = settings.getString(Constants.PLUGIN_CUSTOM_RULES_PREFIX);
35 | final Map rules = provider.getRules(null, rulesPrefix, paths);
36 |
37 | for (final String key : rules.keySet()) {
38 | final SqlRules type = rules.get(key);
39 | if (type.isIsAdhoc()) {
40 | continue;
41 | }
42 | final String repositoryKey = type.getRepoKey();
43 | final String repositoryName = type.getRepoName();
44 | final NewRepository repository = context.createRepository(repositoryKey, TSQLLanguage.KEY)
45 | .setName(repositoryName);
46 | try (final InputStream rulesXml = new FileInputStream(key)) {
47 | final RulesDefinitionXmlLoader rulesLoader = new RulesDefinitionXmlLoader();
48 | rulesLoader.load(repository, rulesXml, StandardCharsets.UTF_8.name());
49 | } catch (FileNotFoundException e) {
50 | LOGGER.info("File was not found: " + key);
51 | } catch (IOException e1) {
52 | LOGGER.info("Error reading file: " + key);
53 | }
54 |
55 | repository.done();
56 | }
57 |
58 | }
59 |
60 | @Override
61 | public void define(final Context context) {
62 | defineRulesForLanguage(context);
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/definitions/MsRulesDefinition.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.definitions;
2 |
3 | import org.sonar.plugins.tsql.Constants;
4 |
5 | public final class MsRulesDefinition extends BaseRulesDefinition {
6 |
7 | public MsRulesDefinition() {
8 | super(Constants.MS_REPO_KEY, Constants.MS_REPO_NAME, Constants.MS_RULES_FILE);
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/files/BaseReportsProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.files;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 | import java.util.List;
7 |
8 | import org.apache.commons.lang.StringUtils;
9 |
10 | public class BaseReportsProvider implements IReportsProvider {
11 |
12 | private final String searchName;
13 |
14 | public BaseReportsProvider(final String searchName) {
15 | this.searchName = searchName.toLowerCase();
16 | }
17 |
18 | @Override
19 | public File[] get(final String baseDir) {
20 | if (StringUtils.isEmpty(this.searchName)) {
21 | return new File[0];
22 | }
23 |
24 | final List res = new ArrayList<>();
25 | final List files = listf(baseDir);
26 | for (final File f : files) {
27 | if (f.getName().toLowerCase().endsWith(this.searchName)) {
28 | res.add(f);
29 | }
30 | }
31 | return res.toArray(new File[0]);
32 | }
33 |
34 | private static List listf(final String directoryName) {
35 | final File directory = new File(directoryName);
36 |
37 | final List resultList = new ArrayList();
38 |
39 | if (!directory.exists()) {
40 | return resultList;
41 | }
42 |
43 | final File[] fList = directory.listFiles();
44 | resultList.addAll(Arrays.asList(fList));
45 | for (final File file : fList) {
46 | if (file.isDirectory()) {
47 | resultList.addAll(listf(file.getAbsolutePath()));
48 | }
49 | }
50 | return resultList;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/files/FilesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.files;
2 |
3 | import java.io.File;
4 | import java.util.Arrays;
5 | import java.util.LinkedList;
6 | import java.util.List;
7 | import java.util.stream.Collectors;
8 |
9 | import org.sonar.api.utils.log.Logger;
10 | import org.sonar.api.utils.log.Loggers;
11 |
12 | public class FilesProvider {
13 | private static final Logger LOGGER = Loggers.get(FilesProvider.class);
14 |
15 | public File[] getFiles(String prefix, String actualValue, String baseDir) {
16 | final List foundFiles = new LinkedList<>();
17 | try {
18 | final File temp = new File(actualValue);
19 | // actual file specified
20 | if (temp.exists() && temp.isFile()) {
21 | foundFiles.add(temp);
22 | }
23 |
24 | // directory specified
25 |
26 | if (temp.exists() && temp.isDirectory()) {
27 | final IReportsProvider reportsProvider = new BaseReportsProvider(prefix);
28 | final File[] files = reportsProvider.get(temp.getAbsolutePath());
29 | foundFiles.addAll(Arrays.asList(files).stream().filter(File::isFile).collect(Collectors.toList()));
30 | }
31 |
32 | // relative or search path specified
33 | if (!temp.exists()) {
34 | final IReportsProvider reportsProvider = new BaseReportsProvider(actualValue);
35 | final File[] files = reportsProvider.get(baseDir);
36 | foundFiles.addAll(Arrays.asList(files).stream().filter(File::isFile).collect(Collectors.toList()));
37 | }
38 |
39 | } catch (final Throwable e) {
40 |
41 | LOGGER.warn(
42 | "Unexpected error was thrown while searching for files: prefix {} actualValue {} baseDir {}. Exception was: {} ",
43 | prefix, actualValue, baseDir, e);
44 | }
45 | return foundFiles.stream().distinct().collect(Collectors.toList()).toArray(new File[0]);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/files/IReportsProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.files;
2 |
3 | import java.io.File;
4 |
5 | public interface IReportsProvider {
6 | File[] get(String file);
7 | }
8 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/issues/CodeGuardIssuesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.issues;
2 |
3 | import static java.lang.String.format;
4 |
5 | import java.io.File;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | import org.sonar.api.config.Settings;
11 | import org.sonar.api.utils.TempFolder;
12 | import org.sonar.api.utils.log.Logger;
13 | import org.sonar.api.utils.log.Loggers;
14 | import org.sonar.plugins.tsql.rules.files.CodeGuardExecutingReportsProvider;
15 | import org.sonar.plugins.tsql.rules.files.IReportsProvider;
16 | import org.sonar.plugins.tsql.rules.parsers.CodeGuardIssuesParser;
17 | import org.sonar.plugins.tsql.rules.parsers.IIssuesParser;
18 |
19 | public class CodeGuardIssuesProvider implements IIssuesProvider {
20 |
21 | private final IIssuesParser issuesParser = new CodeGuardIssuesParser();
22 | private final IReportsProvider reportsProvider;
23 |
24 | private static final Logger LOGGER = Loggers.get(CodeGuardIssuesProvider.class);
25 |
26 | public CodeGuardIssuesProvider(final Settings settings, final TempFolder tempFolder) {
27 | this.reportsProvider = new CodeGuardExecutingReportsProvider(settings, tempFolder);
28 | }
29 |
30 | @Override
31 | public TsqlIssue[] getIssues(final String baseDir) {
32 | final List foundIssues = new ArrayList();
33 | for (final File reportPath : this.reportsProvider.get(baseDir)) {
34 | final TsqlIssue[] errors = this.issuesParser.parse(reportPath);
35 | LOGGER.debug(format("Found total %d issues at %s.", errors.length, reportPath));
36 | foundIssues.addAll(Arrays.asList(errors));
37 | }
38 | return foundIssues.toArray(new TsqlIssue[0]);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/issues/DefaultIssuesFiller.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.issues;
2 |
3 | import static java.lang.String.format;
4 |
5 | import org.sonar.api.batch.fs.FileSystem;
6 | import org.sonar.api.batch.fs.InputFile;
7 | import org.sonar.api.batch.rule.Severity;
8 | import org.sonar.api.batch.sensor.SensorContext;
9 | import org.sonar.api.batch.sensor.issue.NewExternalIssue;
10 | import org.sonar.api.batch.sensor.issue.NewIssue;
11 | import org.sonar.api.batch.sensor.issue.NewIssueLocation;
12 | import org.sonar.api.rule.RuleKey;
13 | import org.sonar.api.rules.RuleType;
14 | import org.sonar.api.utils.log.Logger;
15 | import org.sonar.api.utils.log.Loggers;
16 |
17 | public class DefaultIssuesFiller implements IIssuesFiller {
18 | private static final Logger LOGGER = Loggers.get(DefaultIssuesFiller.class);
19 |
20 | @Override
21 | public void fill(final SensorContext context, final InputFile inputFile, final TsqlIssue... issues) {
22 |
23 | for (final TsqlIssue tsqlIssue : issues) {
24 | InputFile file = inputFile;
25 | if (tsqlIssue == null) {
26 | continue;
27 | }
28 | try {
29 | if (tsqlIssue.getLine() < 1) {
30 | LOGGER.warn(format("Can't add issue %s on file %s as line is 0", tsqlIssue.getType(),
31 | tsqlIssue.getFilePath()));
32 | continue;
33 | }
34 |
35 | if (file == null) {
36 | final FileSystem fileSystem = context.fileSystem();
37 | file = fileSystem.inputFile(fileSystem.predicates().and(tsqlIssue.getPredicate()));
38 |
39 | if (file == null) {
40 | LOGGER.debug(format("Cound not find file %s to add issue %s at line %d.",
41 | tsqlIssue.getFilePath(), tsqlIssue.getType(), tsqlIssue.getLine()));
42 | continue;
43 | }
44 | }
45 | final RuleKey rule = RuleKey.of(tsqlIssue.getRepositoryKey(), tsqlIssue.getType());
46 |
47 | if (tsqlIssue.isExternal()) {
48 | final NewExternalIssue externalIssue = context.newExternalIssue().engineId(tsqlIssue.getRepositoryKey())
49 | .ruleId(tsqlIssue.getType()).severity(Severity.INFO).type(RuleType.CODE_SMELL);
50 | final NewIssueLocation loc = externalIssue.newLocation().on(file)
51 | .at(file.selectLine(tsqlIssue.getLine()));
52 | if (tsqlIssue.getDescription() != null) {
53 | loc.message(tsqlIssue.getDescription());
54 | }
55 | externalIssue.at(loc).save();
56 | continue;
57 | }
58 |
59 | final NewIssue issue = context.newIssue().forRule(rule);
60 | final NewIssueLocation loc = issue.newLocation().on(file).at(file.selectLine(tsqlIssue.getLine()));
61 | if (tsqlIssue.getDescription() != null) {
62 | loc.message(tsqlIssue.getDescription());
63 | }
64 |
65 | issue.at(loc).save();
66 | } catch (final Throwable e) {
67 | LOGGER.warn(format("Can't add issue %s on file %s at line %d.", tsqlIssue.getType(), file,
68 | tsqlIssue.getLine()), e);
69 | }
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/issues/IIssuesFiller.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.issues;
2 |
3 | import org.sonar.api.batch.fs.InputFile;
4 | import org.sonar.api.batch.sensor.SensorContext;
5 |
6 | public interface IIssuesFiller {
7 | void fill(SensorContext context, final InputFile file, TsqlIssue... issues);
8 | }
9 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/issues/IIssuesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.issues;
2 |
3 | public interface IIssuesProvider {
4 | TsqlIssue[] getIssues(final String baseDir);
5 | }
6 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/issues/MsIssuesProvider.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.issues;
2 |
3 | import static java.lang.String.format;
4 |
5 | import java.io.File;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | import org.sonar.api.config.Settings;
11 | import org.sonar.api.utils.log.Logger;
12 | import org.sonar.api.utils.log.Loggers;
13 | import org.sonar.plugins.tsql.Constants;
14 | import org.sonar.plugins.tsql.rules.files.FilesProvider;
15 | import org.sonar.plugins.tsql.rules.parsers.IIssuesParser;
16 | import org.sonar.plugins.tsql.rules.parsers.MsIssuesParser;
17 |
18 | public class MsIssuesProvider implements IIssuesProvider {
19 |
20 | private final IIssuesParser issuesParser = new MsIssuesParser();
21 |
22 | private static final Logger LOGGER = Loggers.get(MsIssuesProvider.class);
23 | private final FilesProvider filesProvider = new FilesProvider();
24 | private final Settings settings;
25 |
26 | public MsIssuesProvider(final Settings settings) {
27 | this.settings = settings;
28 | }
29 |
30 | @Override
31 | public TsqlIssue[] getIssues(String baseDir) {
32 | final List foundIssues = new ArrayList();
33 | File[] files = filesProvider.getFiles(Constants.MS_REPORT_FILE_DEFAULT_VALUE,
34 | settings.getString(Constants.MS_REPORT_FILE), baseDir);
35 | for (final File reportPath : files) {
36 | final TsqlIssue[] errors = this.issuesParser.parse(reportPath);
37 | LOGGER.debug(format("Found total %d issues at %s.", errors.length, reportPath));
38 | foundIssues.addAll(Arrays.asList(errors));
39 | }
40 | return foundIssues.toArray(new TsqlIssue[0]);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/issues/TsqlIssue.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.issues;
2 |
3 | import org.sonar.api.batch.fs.FilePredicate;
4 | import org.sonar.plugins.tsql.predicates.AbsolutePathCaseInsensitivePredicate;
5 |
6 | public class TsqlIssue {
7 |
8 | private String type;
9 |
10 | private String description;
11 | private boolean isExternal;
12 | public boolean isExternal() {
13 | return isExternal;
14 | }
15 |
16 | public void setExternal(boolean isExternal) {
17 | this.isExternal = isExternal;
18 | }
19 |
20 | private String filePath;
21 | private int line;
22 | private String repositoryKey;
23 | public String getRepositoryKey() {
24 | return repositoryKey;
25 | }
26 |
27 | public void setRepositoryKey(String repositoryKey) {
28 | this.repositoryKey = repositoryKey;
29 | }
30 |
31 | public String getType() {
32 | return type;
33 | }
34 |
35 | public void setType(final String type) {
36 | this.type = type;
37 | }
38 |
39 | public String getDescription() {
40 | return description;
41 | }
42 |
43 | public void setDescription(final String description) {
44 | this.description = description;
45 | }
46 |
47 | public String getFilePath() {
48 | return filePath;
49 | }
50 |
51 | public void setFilePath(final String filePath) {
52 | this.filePath = filePath;
53 | }
54 |
55 | public int getLine() {
56 | return line;
57 | }
58 |
59 | public void setLine(final int line) {
60 | this.line = line;
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | return this.getType() + " " + this.getDescription() + " " + this.getFilePath() + " " + this.getLine();
66 | }
67 |
68 | public FilePredicate getPredicate() {
69 | return new AbsolutePathCaseInsensitivePredicate(this.getFilePath());
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/parsers/CodeGuardIssuesParser.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.parsers;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import javax.xml.bind.JAXBContext;
8 | import javax.xml.bind.Unmarshaller;
9 |
10 | import org.sonar.api.utils.log.Logger;
11 | import org.sonar.api.utils.log.Loggers;
12 | import org.sonar.plugins.tsql.rules.issues.CodeGuardIssues;
13 | import org.sonar.plugins.tsql.rules.issues.CodeGuardIssues.File.Issue;
14 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
15 |
16 | public class CodeGuardIssuesParser implements IIssuesParser {
17 |
18 | private static final Logger LOGGER = Loggers.get(CodeGuardIssuesParser.class);
19 |
20 | @Override
21 | public TsqlIssue[] parse(final File file) {
22 | final List list = new ArrayList();
23 | try {
24 | final JAXBContext jaxbContext = JAXBContext.newInstance(CodeGuardIssues.class);
25 | final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
26 | final CodeGuardIssues issues = (CodeGuardIssues) jaxbUnmarshaller.unmarshal(file);
27 | for (final org.sonar.plugins.tsql.rules.issues.CodeGuardIssues.File f : issues.getFile()) {
28 | for (final Issue is : f.getIssue()) {
29 | final TsqlIssue issue = new TsqlIssue();
30 | issue.setDescription(is.getText());
31 | issue.setFilePath(f.getFullname());
32 | issue.setLine(is.getLine());
33 | issue.setType(is.getCode());
34 | list.add(issue);
35 | }
36 |
37 | }
38 | return list.toArray(new TsqlIssue[0]);
39 |
40 | } catch (final Throwable e) {
41 | LOGGER.warn("Unexpected error occured redading file "+file, e);
42 | }
43 | return new TsqlIssue[0];
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/parsers/IIssuesParser.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.parsers;
2 |
3 | import java.io.File;
4 |
5 | public interface IIssuesParser {
6 | T[] parse(final File file);
7 | }
8 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/rules/parsers/MsIssuesParser.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.parsers;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import javax.xml.bind.JAXBContext;
8 | import javax.xml.bind.Unmarshaller;
9 |
10 | import org.sonar.api.utils.log.Logger;
11 | import org.sonar.api.utils.log.Loggers;
12 | import org.sonar.plugins.tsql.rules.issues.MsIssues;
13 | import org.sonar.plugins.tsql.rules.issues.MsIssues.Problem;
14 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
15 |
16 | public class MsIssuesParser implements IIssuesParser {
17 |
18 | private static final Logger LOGGER = Loggers.get(MsIssuesParser.class);
19 |
20 | @Override
21 | public TsqlIssue[] parse(final File file) {
22 | final List list = new ArrayList();
23 | try {
24 | final JAXBContext jaxbContext = JAXBContext.newInstance(MsIssues.class);
25 | final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
26 | final MsIssues issues = (MsIssues) jaxbUnmarshaller.unmarshal(file);
27 | for (final Problem p : issues.getProblem()) {
28 | final TsqlIssue issue = new TsqlIssue();
29 | issue.setDescription(p.getProblemDescription());
30 | issue.setFilePath(p.getSourceFile());
31 | issue.setLine(p.getLine());
32 | issue.setType(p.getRule());
33 | list.add(issue);
34 | }
35 | return list.toArray(new TsqlIssue[0]);
36 | } catch (final Throwable e) {
37 | LOGGER.warn("Unexpected error occured reading file: " + file, e);
38 | }
39 | return new TsqlIssue[0];
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/sensors/BaseTsqlExternalSensor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.sensors;
2 |
3 | import static java.lang.String.format;
4 |
5 | import org.sonar.plugins.tsql.rules.issues.DefaultIssuesFiller;
6 | import org.sonar.plugins.tsql.rules.issues.IIssuesFiller;
7 | import org.sonar.plugins.tsql.rules.issues.IIssuesProvider;
8 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
9 |
10 | public class BaseTsqlExternalSensor extends BaseTsqlSensor {
11 |
12 | private final IIssuesProvider issuesProvider;
13 | private final String repositoryKey;
14 | private final IIssuesFiller filler = new DefaultIssuesFiller();
15 |
16 | public BaseTsqlExternalSensor(final IIssuesProvider issuesProvider, final String sensorName,
17 | final String repositoryKey) {
18 | super(sensorName);
19 | this.issuesProvider = issuesProvider;
20 | this.repositoryKey = repositoryKey;
21 |
22 | }
23 |
24 | protected void innerExecute(final org.sonar.api.batch.sensor.SensorContext context) {
25 |
26 | final String baseDir = context.fileSystem().baseDir().getAbsolutePath();
27 |
28 | final TsqlIssue[] issues = this.issuesProvider.getIssues(baseDir);
29 |
30 | for (final TsqlIssue i : issues) {
31 | i.setRepositoryKey(this.repositoryKey);
32 | }
33 | LOGGER.info(format("Found %d issues", issues.length));
34 |
35 | filler.fill(context, null, issues);
36 |
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/sensors/BaseTsqlSensor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.sensors;
2 |
3 | import org.sonar.api.batch.sensor.SensorDescriptor;
4 | import org.sonar.api.config.Settings;
5 | import org.sonar.api.utils.log.Logger;
6 | import org.sonar.api.utils.log.Loggers;
7 | import org.sonar.plugins.tsql.Constants;
8 | import org.sonar.plugins.tsql.languages.TSQLLanguage;
9 |
10 | public abstract class BaseTsqlSensor implements org.sonar.api.batch.sensor.Sensor {
11 |
12 | protected static final Logger LOGGER = Loggers.get(BaseTsqlSensor.class);
13 | private final String sensorName;
14 |
15 | public BaseTsqlSensor(final String sensorName) {
16 | this.sensorName = sensorName;
17 | }
18 |
19 | @Override
20 | public String toString() {
21 | return this.getClass().getSimpleName();
22 | }
23 |
24 | @Override
25 | public void describe(final SensorDescriptor descriptor) {
26 | descriptor.name(this.getClass().getSimpleName()).onlyOnLanguage(TSQLLanguage.KEY);
27 | }
28 |
29 | @Override
30 | public void execute(final org.sonar.api.batch.sensor.SensorContext context) {
31 |
32 | final Settings settings = context.settings();
33 | final boolean skipAnalysis = settings.getBoolean(Constants.PLUGIN_SKIP);
34 |
35 | if (skipAnalysis) {
36 | LOGGER.debug(String.format("Skipping plugin as skip flag is set: %s", Constants.PLUGIN_SKIP));
37 | return;
38 | }
39 | final boolean skipSensor = settings.getBoolean(sensorName);
40 |
41 | if (skipSensor) {
42 | LOGGER.debug(String.format("Skipping sensor as skip flag is set: %s", sensorName));
43 | return;
44 | }
45 | try {
46 | innerExecute(context);
47 | } catch (Throwable e) {
48 | e.printStackTrace();
49 | }
50 | }
51 |
52 | protected abstract void innerExecute(final org.sonar.api.batch.sensor.SensorContext context);
53 | }
54 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/sensors/CodeGuardIssuesLoaderSensor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.sensors;
2 |
3 | import org.sonar.api.config.Settings;
4 | import org.sonar.api.utils.TempFolder;
5 | import org.sonar.plugins.tsql.Constants;
6 | import org.sonar.plugins.tsql.rules.issues.CodeGuardIssuesProvider;
7 |
8 | public class CodeGuardIssuesLoaderSensor extends BaseTsqlExternalSensor {
9 |
10 | public CodeGuardIssuesLoaderSensor(final Settings settings, final TempFolder tempFolder) {
11 | super(new CodeGuardIssuesProvider(settings, tempFolder), Constants.PLUGIN_SKIP_CG, Constants.CG_REPO_KEY);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/java/org/sonar/plugins/tsql/sensors/MsIssuesLoaderSensor.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.sensors;
2 |
3 | import org.sonar.api.config.Settings;
4 | import org.sonar.plugins.tsql.Constants;
5 | import org.sonar.plugins.tsql.rules.issues.MsIssuesProvider;
6 |
7 | public class MsIssuesLoaderSensor extends BaseTsqlExternalSensor {
8 |
9 | public MsIssuesLoaderSensor(final Settings settings) {
10 | super(new MsIssuesProvider(settings), Constants.PLUGIN_SKIP_MS, Constants.MS_REPO_KEY);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/resources/schemas/codeGuard.xsd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gretard/sonar-tsql-plugin/aadb5598bbb183c12df997ee9f3e053f962ce0f7/sonar-tsql-plugin/src/main/resources/schemas/codeGuard.xsd
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/resources/schemas/sqlRules.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/resources/schemas/visualStudio.xsd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gretard/sonar-tsql-plugin/aadb5598bbb183c12df997ee9f3e053f962ce0f7/sonar-tsql-plugin/src/main/resources/schemas/visualStudio.xsd
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/main/resources/tsql.keywords:
--------------------------------------------------------------------------------
1 | ADD
2 | EXTERNAL
3 | PROCEDURE
4 | ALL
5 | FETCH
6 | PUBLIC
7 | ALTER
8 | FILE
9 | RAISERROR
10 | AND
11 | FILLFACTOR
12 | READ
13 | ANY
14 | FOR
15 | READTEXT
16 | AS
17 | FOREIGN
18 | RECONFIGURE
19 | ASC
20 | FREETEXT
21 | REFERENCES
22 | AUTHORIZATION
23 | FREETEXTTABLE
24 | REPLICATION
25 | BACKUP
26 | FROM
27 | RESTORE
28 | BEGIN
29 | FULL
30 | RESTRICT
31 | BETWEEN
32 | FUNCTION
33 | RETURN
34 | BREAK
35 | GOTO
36 | REVERT
37 | BROWSE
38 | GRANT
39 | REVOKE
40 | BULK
41 | GROUP
42 | RIGHT
43 | BY
44 | HAVING
45 | ROLLBACK
46 | CASCADE
47 | HOLDLOCK
48 | ROWCOUNT
49 | CASE
50 | IDENTITY
51 | ROWGUIDCOL
52 | CHECK
53 | IDENTITY_INSERT
54 | RULE
55 | CHECKPOINT
56 | IDENTITYCOL
57 | SAVE
58 | CLOSE
59 | IF
60 | SCHEMA
61 | CLUSTERED
62 | IN
63 | SECURITYAUDIT
64 | COALESCE
65 | INDEX
66 | SELECT
67 | COLLATE
68 | INNER
69 | SEMANTICKEYPHRASETABLE
70 | COLUMN
71 | INSERT
72 | SEMANTICSIMILARITYDETAILSTABLE
73 | COMMIT
74 | INTERSECT
75 | SEMANTICSIMILARITYTABLE
76 | COMPUTE
77 | INTO
78 | SESSION_USER
79 | CONSTRAINT
80 | IS
81 | SET
82 | CONTAINS
83 | JOIN
84 | SETUSER
85 | CONTAINSTABLE
86 | KEY
87 | SHUTDOWN
88 | CONTINUE
89 | KILL
90 | SOME
91 | CONVERT
92 | LEFT
93 | STATISTICS
94 | CREATE
95 | LIKE
96 | SYSTEM_USER
97 | CROSS
98 | LINENO
99 | TABLE
100 | CURRENT
101 | LOAD
102 | TABLESAMPLE
103 | CURRENT_DATE
104 | MERGE
105 | TEXTSIZE
106 | CURRENT_TIME
107 | NATIONAL
108 | THEN
109 | CURRENT_TIMESTAMP
110 | NOCHECK
111 | TO
112 | CURRENT_USER
113 | NONCLUSTERED
114 | TOP
115 | CURSOR
116 | NOT
117 | TRAN
118 | DATABASE
119 | NULL
120 | TRANSACTION
121 | DBCC
122 | NULLIF
123 | TRIGGER
124 | DEALLOCATE
125 | OF
126 | TRUNCATE
127 | DECLARE
128 | OFF
129 | TRY_CONVERT
130 | DEFAULT
131 | OFFSETS
132 | TSEQUAL
133 | DELETE
134 | ON
135 | UNION
136 | DENY
137 | OPEN
138 | UNIQUE
139 | DESC
140 | OPENDATASOURCE
141 | UNPIVOT
142 | DISK
143 | OPENQUERY
144 | UPDATE
145 | DISTINCT
146 | OPENROWSET
147 | UPDATETEXT
148 | DISTRIBUTED
149 | OPENXML
150 | USE
151 | DOUBLE
152 | OPTION
153 | USER
154 | DROP
155 | OR
156 | VALUES
157 | DUMP
158 | ORDER
159 | VARYING
160 | ELSE
161 | OUTER
162 | VIEW
163 | END
164 | OVER
165 | WAITFOR
166 | ERRLVL
167 | PERCENT
168 | WHEN
169 | ESCAPE
170 | PIVOT
171 | WHERE
172 | EXCEPT
173 | PLAN
174 | WHILE
175 | EXEC
176 | PRECISION
177 | WITH
178 | EXECUTE
179 | PRIMARY
180 | WITHIN GROUP
181 | EXISTS
182 | PRINT
183 | WRITETEXT
184 | EXIT
185 | PROC
186 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/antlr/CustomRulesVerificationTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr;
2 |
3 | import java.util.Collection;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 |
7 | import org.junit.Assert;
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 | import org.junit.runners.Parameterized;
11 | import org.junit.runners.Parameterized.Parameters;
12 | import org.sonar.plugins.tsql.checks.CustomPluginChecks;
13 | import org.sonar.plugins.tsql.checks.custom.Rule;
14 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
15 | import org.sonar.plugins.tsql.helpers.AntlrUtils;
16 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
17 |
18 | @RunWith(Parameterized.class)
19 | public class CustomRulesVerificationTest {
20 | private Rule rule;
21 | private String text;
22 | private boolean issuesFound;
23 | private String key;
24 | private String ruleName;
25 |
26 | @Parameters(name = "{index}: {1}={2}")
27 | public static Collection data() {
28 | final List objects = new LinkedList<>();
29 | final CustomPluginChecks provider = new CustomPluginChecks();
30 | final SqlRules rules = provider.getRules();
31 | for (Rule r : rules.getRule()) {
32 |
33 | for (String c : r.getRuleImplementation().getCompliantRulesCodeExamples().getRuleCodeExample()) {
34 | objects.add(new Object[] { r, r.getKey(), r.getName(), c, false });
35 | }
36 |
37 | for (String c : r.getRuleImplementation().getViolatingRulesCodeExamples().getRuleCodeExample()) {
38 | objects.add(new Object[] { r, r.getKey(), r.getName(), c, true });
39 | }
40 | }
41 | return objects;
42 | }
43 |
44 | public CustomRulesVerificationTest(Rule rule, String key, String ruleName, String text, boolean issuesFound) {
45 | this.rule = rule;
46 | this.key = key;
47 | this.ruleName = ruleName;
48 | this.text = text;
49 | this.issuesFound = issuesFound;
50 |
51 | }
52 |
53 | @Test
54 | public void test() throws Throwable{
55 | Assert.assertNotNull("Rule's debt remiationfunction not specified", this.rule.getRemediationFunction());
56 | Assert.assertNotNull("Rule's DebtRemediationFunctionCoefficient not specified",
57 | this.rule.getDebtRemediationFunctionCoefficient());
58 | Assert.assertEquals(this.rule.getKey(), this.rule.getInternalKey());
59 | TsqlIssue[] issues = AntlrUtils.verify(this.rule, this.text);
60 | Assert.assertEquals(String.format("Expected rule %s [%s] for text %s to find issues: %s", this.rule.getName(),
61 | this.key, this.text, this.issuesFound), this.issuesFound, issues.length != 0);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/antlr/lines/DefaultLinesProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.lines;
2 |
3 | import org.antlr.tsql.TSqlLexer;
4 | import org.antlr.tsql.TSqlParser;
5 | import org.antlr.v4.runtime.CharStream;
6 | import org.antlr.v4.runtime.CharStreams;
7 | import org.antlr.v4.runtime.CommonTokenStream;
8 | import org.antlr.v4.runtime.tree.ParseTree;
9 | import org.junit.Assert;
10 | import org.junit.Test;
11 | import org.sonar.plugins.tsql.antlr.lines.DefaultLinesProvider;
12 | import org.sonar.plugins.tsql.antlr.nodes.ParsedNode;
13 |
14 | public class DefaultLinesProviderTest {
15 |
16 | @Test
17 | public void test() {
18 |
19 | final CharStream charStream = CharStreams.fromString("\r\nSELECT\r\n 1");
20 |
21 | final TSqlLexer lexer = new TSqlLexer(charStream);
22 |
23 | final CommonTokenStream stream = new CommonTokenStream(lexer);
24 |
25 | stream.fill();
26 | TSqlParser parser = new TSqlParser(stream);
27 | ParseTree child = parser.tsql_file().getChild(0);
28 | DefaultLinesProvider lines = new DefaultLinesProvider(stream);
29 | int line = lines.getLine(new ParsedNode(child));
30 | Assert.assertEquals(2, line);
31 |
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/antlr/nodes/NodeUsesProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes;
2 |
3 | import org.antlr.v4.runtime.tree.ParseTree;
4 | import org.junit.Assert;
5 | import org.junit.Test;
6 | import org.sonar.plugins.tsql.antlr.IParsedNode;
7 | import org.sonar.plugins.tsql.helpers.AntlrUtils;
8 | import org.sonar.plugins.tsql.helpers.TestNode;
9 |
10 | public class NodeUsesProviderTest {
11 |
12 | @Test
13 | public void testGetUsesNodes() throws Throwable {
14 | String s = "SELECT *,test from dbo.test where name like '%test%' ;";
15 | ParseTree tree = AntlrUtils.getRequest(s).getRoot();
16 | NodeUsesProvider provider = new NodeUsesProvider(tree);
17 | IParsedNode[] nodes = provider.getNodes(new TestNode("test", null, 0));
18 | Assert.assertEquals(28, nodes.length);
19 | }
20 |
21 | @Test
22 | public void testGetUsesNodesNull() throws Throwable {
23 | String s = "SELECT *,test from dbo.test where name like '%test%' ;";
24 | ParseTree tree = AntlrUtils.getRequest(s).getRoot();
25 | NodeUsesProvider provider = new NodeUsesProvider(tree);
26 | IParsedNode[] nodes = provider.getNodes(null);
27 | Assert.assertEquals(0, nodes.length);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/antlr/nodes/NodesMatchingRulesProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 |
6 | import org.junit.Test;
7 | import org.sonar.plugins.tsql.antlr.CandidateNode;
8 | import org.sonar.plugins.tsql.antlr.CandidateRule;
9 | import org.sonar.plugins.tsql.antlr.IParsedNode;
10 | import org.sonar.plugins.tsql.antlr.issues.NodesMatchingRulesProvider;
11 | import org.sonar.plugins.tsql.checks.custom.Rule;
12 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
13 | import org.sonar.plugins.tsql.helpers.TestNode;
14 |
15 | import junit.framework.Assert;
16 |
17 | public class NodesMatchingRulesProviderTest {
18 | NodesMatchingRulesProvider sut = new NodesMatchingRulesProvider(new INodesProvider() {
19 |
20 | @Override
21 | public IParsedNode[] getNodes(IParsedNode node) {
22 | return new IParsedNode[] { new TestNode("test", "test", 2) };
23 | }
24 | });
25 |
26 | @Test
27 | public void testCheck() {
28 | Rule rule = new Rule();
29 | RuleImplementation child = new RuleImplementation();
30 | RuleImplementation imp = new RuleImplementation();
31 | imp.getChildrenRules().getRuleImplementation().add(child);
32 | rule.setRuleImplementation(imp);
33 | CandidateRule candidateRule = new CandidateRule("test", rule);
34 | IParsedNode nnode = new TestNode("test", "testClass", 1);
35 | Map> results = sut.check(new CandidateNode(candidateRule, nnode));
36 | Assert.assertEquals(2, results.size());
37 | Assert.assertEquals(1, results.get(rule.getRuleImplementation()).size());
38 | }
39 |
40 | @Test(expected = IllegalArgumentException.class)
41 | public void testCheckNull() {
42 | Map> results = sut.check(null);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/antlr/nodes/ParsedNodeTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes;
2 |
3 | import org.antlr.tsql.TSqlParser.Cfl_statementContext;
4 | import org.antlr.v4.runtime.tree.ParseTree;
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.sonar.plugins.tsql.antlr.IParsedNode;
8 | import org.sonar.plugins.tsql.helpers.AntlrUtils;
9 |
10 | public class ParsedNodeTest {
11 |
12 | @Test
13 | public void testGetChildren() throws Throwable {
14 | String s = "SELECT * from dbo.test where name like '%test%' ;";
15 | ParseTree tree = AntlrUtils.getRequest(s).getRoot();
16 | ParsedNode node = new ParsedNode(tree);
17 | IParsedNode[] nodes = node.getChildren();
18 |
19 | Assert.assertEquals(43, nodes.length);
20 |
21 | }
22 |
23 | @Test
24 | public void testControlFlowParent() throws Throwable {
25 | String s = "IF @a > 0 SELECT 1 else SELECT 2;";
26 | ParseTree tree = AntlrUtils.getRequest(s).getRoot();
27 | ParsedNode node = new ParsedNode(tree.getChild(0).getChild(0).getChild(0).getChild(0).getChild(0).getChild(0));
28 | IParsedNode parentNode = node.getControlFlowParent();
29 | Assert.assertNotNull(parentNode);
30 | Assert.assertEquals(Cfl_statementContext.class.getSimpleName(), parentNode.getClassName());
31 | }
32 |
33 | @Test
34 | public void testControlFlowParentNotContrl() throws Throwable {
35 | String s = "SELECT 1;";
36 | ParseTree tree = AntlrUtils.getRequest(s).getRoot();
37 | ParsedNode node = new ParsedNode(tree.getChild(0).getChild(0));
38 | IParsedNode parentNode = node.getControlFlowParent();
39 | Assert.assertNotNull(parentNode);
40 | Assert.assertEquals(null, parentNode.getClassName());
41 | }
42 |
43 | @Test
44 | public void testGetItemNull() throws Throwable {
45 | ParsedNode node = new ParsedNode(null);
46 | Assert.assertEquals(0, node.getChildren().length);
47 | Assert.assertEquals(0, node.getParents().length);
48 | Assert.assertEquals(0, node.getSiblings().length);
49 | Assert.assertNotNull(node.getControlFlowParent());
50 | Assert.assertNull(node.getText());
51 | }
52 |
53 | @Test
54 | public void testSiblings() throws Throwable {
55 | String s = "SELECT * from dbo.test where name like '%test%' ;";
56 | ParseTree tree = AntlrUtils.getRequest(s).getRoot().getChild(0).getChild(0).getChild(0).getChild(0);
57 | ParsedNode node = new ParsedNode(tree);
58 | IParsedNode[] nodes = node.getSiblings();
59 | Assert.assertEquals(39, nodes.length);
60 |
61 | }
62 |
63 | @Test
64 | public void testParents() throws Throwable {
65 | String s = "SELECT * from dbo.test where name like '%test%' ;";
66 | ParseTree tree = AntlrUtils.getRequest(s).getRoot().getChild(0).getChild(0).getChild(0).getChild(0);
67 | ParsedNode node = new ParsedNode(tree);
68 | IParsedNode[] nodes = node.getParents();
69 | Assert.assertEquals(4, nodes.length);
70 |
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/antlr/nodes/matchers/DistanceMatcherTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.antlr.nodes.matchers;
2 |
3 | import java.util.Arrays;
4 | import java.util.Collection;
5 |
6 | import org.junit.Assert;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.junit.runners.Parameterized;
10 | import org.junit.runners.Parameterized.Parameters;
11 | import org.sonar.plugins.tsql.antlr.IParsedNode;
12 | import org.sonar.plugins.tsql.antlr.nodes.matchers.DistanceMatcher;
13 | import org.sonar.plugins.tsql.checks.custom.RuleDistanceIndexMatchType;
14 | import org.sonar.plugins.tsql.checks.custom.RuleImplementation;
15 | import org.sonar.plugins.tsql.helpers.TestNode;
16 |
17 | @RunWith(Parameterized.class)
18 | public class DistanceMatcherTest {
19 | @Parameters
20 | public static Collection data() {
21 | return Arrays.asList(
22 | new Object[][] { { RuleDistanceIndexMatchType.DEFAULT, 0, new TestNode("test", "test", 1, 1, 1), true },
23 | { RuleDistanceIndexMatchType.MORE, 1, new TestNode("test", "test", 0, 2, 1), false },
24 | { RuleDistanceIndexMatchType.MORE, 1, new TestNode("test", "test", 1, 0, 1), true },
25 | { RuleDistanceIndexMatchType.LESS, 1, new TestNode("test", "test", 0, 1, 2), true },
26 | { RuleDistanceIndexMatchType.LESS, 2, new TestNode("test", "test", 1, 1, 2), true },
27 | { RuleDistanceIndexMatchType.LESS, 2, new TestNode("test", "test", 10, 5, 2), false },
28 | { RuleDistanceIndexMatchType.EQUALS, 2, new TestNode("test", "test", 2, 2, 2), true },
29 | { RuleDistanceIndexMatchType.EQUALS, 2, new TestNode("test", "test", 1, 5, 2), false },
30 |
31 | });
32 | }
33 |
34 | private boolean result;
35 | private IParsedNode node;
36 | private int distance;
37 | private RuleDistanceIndexMatchType type;
38 | private final DistanceMatcher matcher = new DistanceMatcher();
39 |
40 | public DistanceMatcherTest(RuleDistanceIndexMatchType type, int distance, IParsedNode node, boolean result) {
41 | this.type = type;
42 | this.distance = distance;
43 | this.node = node;
44 | this.result = result;
45 |
46 | }
47 |
48 | @Test
49 | public void test() {
50 | RuleImplementation rule = new RuleImplementation();
51 | rule.setDistance(this.distance);
52 | rule.setDistanceCheckType(this.type);
53 | Assert.assertEquals(String.format("Expected %s, %s with type %s index1: %s index2 %s", result, type,
54 | this.distance, node.getIndex(), node.getIndex2()),
55 |
56 | this.result, matcher.match(rule, this.node));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/coverage/FileNamesMatcherTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.coverage;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import com.google.common.collect.ImmutableMap;
7 |
8 | public class FileNamesMatcherTest {
9 | FileNamesMatcher sut = new FileNamesMatcher();
10 | @Test
11 | public void testMatchWithNoSchema() {
12 | CoveredLinesReport[] lines = sut.match("[tes t].sql","src",
13 | ImmutableMap.of("dbo.test", new CoveredLinesReport("[dbo].[test]"), "other.test", new CoveredLinesReport("[other].[test")));
14 | Assert.assertEquals(2, lines.length);
15 | }
16 |
17 | @Test
18 | public void testMatchWithNoSchemaAndParent() {
19 | CoveredLinesReport[] lines = sut.match("[tes t].sql","dbo",
20 | ImmutableMap.of("dbo.test", new CoveredLinesReport("[dbo].[test]"), "other.test", new CoveredLinesReport("[other].[test")));
21 | Assert.assertEquals(1, lines.length);
22 | }
23 | @Test
24 | public void testMatchWithSchemaAndParent() {
25 | CoveredLinesReport[] lines = sut.match("dbo.[tes t].sql","dbo",
26 | ImmutableMap.of("dbo.test", new CoveredLinesReport("[dbo].[test]"), "other.test", new CoveredLinesReport("[other].[test")));
27 | Assert.assertEquals(1, lines.length);
28 | }
29 | @Test
30 | public void testNoMatch() {
31 |
32 | CoveredLinesReport[] lines = sut.match("[test2].sql", "src",
33 | ImmutableMap.of("dbo.test", new CoveredLinesReport("[dbo].[test]"), "other.test", new CoveredLinesReport("[other].[test")));
34 | Assert.assertEquals(0, lines.length);
35 | }
36 |
37 | @Test
38 | public void testMatchWithSchema() {
39 | CoveredLinesReport[] lines = sut.match("dbo.t est.sql","src",
40 | ImmutableMap.of("dbo.test", new CoveredLinesReport("[dbo].[test]"), "other.test", new CoveredLinesReport("[other].[test")));
41 | Assert.assertEquals(1, lines.length);
42 | }
43 |
44 | @Test
45 | public void testMatchWithSchema2() {
46 | CoveredLinesReport[] lines = sut.match("dbo.test.sql", "src",ImmutableMap.of("dbo.test", new CoveredLinesReport("[dbo].[test]"), "other.test", new CoveredLinesReport("[other].[test")));
47 | Assert.assertEquals(1, lines.length);
48 | }
49 |
50 | @Test
51 | public void testMatchWithSchema3() {
52 | CoveredLinesReport[] lines = sut.match("db.dbo.test.sql", "src",ImmutableMap.of("dbo.test", new CoveredLinesReport("[dbo].[test]"), "other.test", new CoveredLinesReport("[other].[test")));
53 | Assert.assertEquals(1, lines.length);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/helpers/AntrlResult.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.helpers;
2 |
3 | import org.antlr.tsql.TSqlParser;
4 | import org.antlr.v4.runtime.CommonTokenStream;
5 | import org.antlr.v4.runtime.tree.ParseTree;
6 |
7 | public class AntrlResult {
8 | private ParseTree tree;
9 | private CommonTokenStream stream;
10 | private TSqlParser parser;
11 | public ParseTree getTree() {
12 | return tree;
13 | }
14 | public void setTree(ParseTree tree) {
15 | this.tree = tree;
16 | }
17 | public CommonTokenStream getStream() {
18 | return stream;
19 | }
20 | public void setStream(CommonTokenStream stream) {
21 | this.stream = stream;
22 | }
23 | public void setParser(TSqlParser parser) {
24 | this.parser = parser;
25 | // TODO Auto-generated method stub
26 |
27 | }
28 | public TSqlParser getParser() {
29 | return parser;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/helpers/ClassesLister.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.helpers;
2 |
3 | import java.util.Set;
4 | import java.util.TreeSet;
5 |
6 | import org.antlr.v4.runtime.ParserRuleContext;
7 | import org.antlr.v4.runtime.tree.ParseTree;
8 | import org.reflections.Reflections;
9 |
10 | public class ClassesLister {
11 |
12 | public static void main(String[] args) {
13 | Reflections reflections = new Reflections("org.antlr.tsql");
14 | Set> subTypes = reflections.getSubTypesOf(ParserRuleContext.class);
15 | TreeSet ordered = new TreeSet<>();
16 | for (@SuppressWarnings("rawtypes") Class c : subTypes) {
17 | ordered.add(c.getSimpleName());
18 | }
19 | for (String x : ordered) {
20 | System.out.println("- " + x);
21 | }
22 | System.out.println(ordered.size());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/helpers/CustomRulesPrinter.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.helpers;
2 |
3 | import org.sonar.plugins.tsql.checks.CustomPluginChecks;
4 | import org.sonar.plugins.tsql.checks.custom.Rule;
5 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
6 |
7 | public class CustomRulesPrinter {
8 |
9 | public static void main(String[] args) {
10 | final CustomPluginChecks provider = new CustomPluginChecks();
11 | final SqlRules rules = provider.getRules();
12 |
13 | for (Rule r : rules.getRule()) {
14 | for (String c : r.getRuleImplementation().getCompliantRulesCodeExamples().getRuleCodeExample()) {
15 | System.out.println(String.format("-- OK: %s", r.getKey()));
16 | System.out.println(String.format("%s", c));
17 | }
18 | for (String c : r.getRuleImplementation().getViolatingRulesCodeExamples().getRuleCodeExample()) {
19 | System.out.println(String.format("-- KO: %s", r.getKey()));
20 | System.out.println(String.format("%s", c));
21 | }
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/helpers/CustomSqlCodePrinter.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.helpers;
2 |
3 | import org.sonar.plugins.tsql.checks.CustomPluginChecks;
4 | import org.sonar.plugins.tsql.checks.custom.Rule;
5 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
6 |
7 | public class CustomSqlCodePrinter {
8 |
9 | public static void main(String[] args) {
10 | final CustomPluginChecks provider = new CustomPluginChecks();
11 | final SqlRules rules = provider.getRules();
12 | System.out.println("# Rules #");
13 | System.out.println();
14 | System.out.println(String.format("Plugin supports the following %s rules:", rules.getRule().size()));
15 | System.out.println();
16 | for (Rule r : rules.getRule()) {
17 | System.out.println(String.format("- %s - %s", r.getKey(), r.getName()));
18 | }
19 | System.out.println();
20 | for (Rule r : rules.getRule()) {
21 | System.out.println(String.format("## %s - %s ##", r.getKey(), r.getName()));
22 | System.out.println(r.getDescription().replace("Description ", ""));
23 | System.out.println();
24 | if (!r.getRuleImplementation().getCompliantRulesCodeExamples().getRuleCodeExample().isEmpty()) {
25 | System.out.println("### Compliant examples ###");
26 | System.out.println();
27 | for (String c : r.getRuleImplementation().getCompliantRulesCodeExamples().getRuleCodeExample()) {
28 | System.out.println(String.format("`%s`\r\n", c));
29 | }
30 | }
31 |
32 | if (!r.getRuleImplementation().getViolatingRulesCodeExamples().getRuleCodeExample().isEmpty()) {
33 | System.out.println("### Non-compliant examples ###");
34 | System.out.println();
35 | for (String c : r.getRuleImplementation().getViolatingRulesCodeExamples().getRuleCodeExample()) {
36 | System.out.println(String.format("`%s`\r\n", c));
37 | }
38 | }
39 | }
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/helpers/RulesHelperTool.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.helpers;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.IOException;
6 |
7 | import org.apache.commons.io.IOUtils;
8 | import org.sonar.plugins.tsql.antlr.AntlrContext;
9 | import org.sonar.plugins.tsql.checks.custom.Rule;
10 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
11 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
12 |
13 | public class RulesHelperTool {
14 |
15 | public static void main(String[] args) throws FileNotFoundException, IOException {
16 | if (args.length != 3) {
17 | System.out.println("Please pass the following: ");
18 | System.out.println("\taction (print or verify)");
19 | System.out.println("\ttype (text or file)");
20 | System.out.println("\tvalue (sql string or path to folder) ");
21 | System.out.println("Example:\r\nprint text \"SELECT * FROM dbo.test;\"");
22 | System.out.println("Example:\r\nverify file \"c:/tests/customRules.rules;\"");
23 |
24 | return;
25 | }
26 |
27 | String action = args[0];
28 | String type = args[1];
29 | String value = args[2];
30 | String text = value;
31 | if (!"text".equals(type)) {
32 | text = IOUtils.toString(new FileInputStream(value), "UTF-8");
33 | }
34 | if ("print".equalsIgnoreCase(action)) {
35 | System.out.println("Printing tree:\r\n");
36 | AntlrContext result = AntlrUtils.getRequest(text);
37 |
38 | AntlrUtils.print(result.getRoot(), 0, result.getStream());
39 | return;
40 |
41 | }
42 | System.out.println("text");
43 | SqlRules[] rules = AntlrUtils.read(value);
44 |
45 | for (SqlRules rule : rules) {
46 | System.out.println("Checking repository: " + rule.getRepoName());
47 | for (Rule r : rule.getRule()) {
48 | System.out.println("Checking rule: " + r.getKey());
49 | for (String s : r.getRuleImplementation().getCompliantRulesCodeExamples().getRuleCodeExample()) {
50 | boolean res = AntlrUtils.verify(r, s).length == 0;
51 | System.out.println("\tc passed: " + res + " for " + s);
52 | }
53 | for (String s : r.getRuleImplementation().getViolatingRulesCodeExamples().getRuleCodeExample()) {
54 | TsqlIssue[] iss = AntlrUtils.verify(r, s);
55 | boolean res = iss.length > 0;
56 | System.out.println("\tv passed: " + res + " for " + s);
57 | }
58 |
59 | }
60 | }
61 |
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/helpers/TestNode.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.helpers;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.antlr.v4.runtime.tree.ParseTree;
7 | import org.sonar.plugins.tsql.antlr.IParsedNode;
8 |
9 | public class TestNode implements IParsedNode {
10 |
11 | private String text;
12 | private String className;
13 | private int distance;
14 | private TestNode parent;
15 | private int index;
16 | private int index2;
17 | private final List innerParents = new ArrayList<>();
18 | private final List innerChildren = new ArrayList<>();
19 |
20 | public List getInnerParents() {
21 | return innerParents;
22 | }
23 |
24 | public List getInnerChildren() {
25 | return innerChildren;
26 | }
27 |
28 | public List getInnerSiblings() {
29 | return innerSiblings;
30 | }
31 |
32 | private final List innerSiblings = new ArrayList<>();
33 |
34 | public void setParent(TestNode parent) {
35 | this.parent = parent;
36 | }
37 |
38 | public TestNode(String text, String className, int distance) {
39 | this.text = text;
40 | this.className = className;
41 | this.distance = distance;
42 | }
43 |
44 | public TestNode(String text, String className, int distance, int index) {
45 | this.text = text;
46 | this.className = className;
47 | this.distance = distance;
48 | this.index = index;
49 | }
50 |
51 | public TestNode(String text, String className, int distance, int index, int index2) {
52 | this.text = text;
53 | this.className = className;
54 | this.distance = distance;
55 | this.index = index;
56 | this.index2 = index2;
57 |
58 | }
59 |
60 | @Override
61 | public String getText() {
62 | return text;
63 | }
64 |
65 | @Override
66 | public String getClassName() {
67 | return className;
68 | }
69 |
70 | @Override
71 | public int getDistance() {
72 | return distance;
73 | }
74 |
75 | @Override
76 | public ParseTree getItem() {
77 | return null;
78 | }
79 |
80 | @Override
81 | public IParsedNode getControlFlowParent() {
82 | return parent;
83 | }
84 |
85 | @Override
86 | public int getIndex() {
87 | // TODO Auto-generated method stub
88 | return index;
89 | }
90 |
91 | @Override
92 | public int getIndex2() {
93 | // TODO Auto-generated method stub
94 | return this.index2;
95 | }
96 |
97 | @Override
98 | public IParsedNode[] getParents() {
99 | return this.innerParents.toArray(new IParsedNode[0]);
100 | }
101 |
102 | @Override
103 | public IParsedNode[] getChildren() {
104 | return this.innerChildren.toArray(new IParsedNode[0]);
105 | }
106 |
107 | @Override
108 | public IParsedNode[] getSiblings() {
109 | return this.innerSiblings.toArray(new IParsedNode[0]);
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/languages/TSQLLanguageTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.languages;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 | import org.sonar.api.config.Settings;
6 | import org.sonar.plugins.tsql.Constants;
7 |
8 | public class TSQLLanguageTest {
9 |
10 | @Test
11 | public void testDefaultSuffixes() {
12 | final Settings settings = new org.sonar.api.config.internal.MapSettings();
13 | final TSQLLanguage language = new TSQLLanguage(settings);
14 | Assert.assertArrayEquals(new String[] { ".sql" }, language.getFileSuffixes());
15 | }
16 |
17 | @Test
18 | public void testDefinedSuffixes() {
19 | final Settings settings = new org.sonar.api.config.internal.MapSettings();
20 | settings.setProperty(Constants.PLUGIN_SUFFIXES, ".sql,.test");
21 | final TSQLLanguage language = new TSQLLanguage(settings);
22 | Assert.assertArrayEquals(new String[] { ".sql", ".test" }, language.getFileSuffixes());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/languages/keywords/KeywordsProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.languages.keywords;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class KeywordsProviderTest {
7 |
8 | @Test
9 | public void test() {
10 | KeywordsProvider provider = new KeywordsProvider();
11 | Assert.assertFalse(provider.isKeyword("test"));
12 | }
13 |
14 | @Test
15 | public void testKeyword() {
16 | KeywordsProvider provider = new KeywordsProvider();
17 | Assert.assertTrue(provider.isKeyword("SELECT"));
18 | }
19 |
20 | @Test
21 | public void testInitializeNonExisting() {
22 | KeywordsProvider provider = new KeywordsProvider("nonExisting");
23 | Assert.assertFalse(provider.isKeyword("SELECT"));
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/lines/SourceLinesProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.lines;
2 |
3 | import java.io.BufferedWriter;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.OutputStreamWriter;
9 | import java.nio.charset.Charset;
10 | import java.nio.charset.StandardCharsets;
11 |
12 | import org.apache.commons.io.FileUtils;
13 | import org.junit.Assert;
14 | import org.junit.Rule;
15 | import org.junit.Test;
16 | import org.junit.rules.TemporaryFolder;
17 |
18 | public class SourceLinesProviderTest {
19 | @Rule
20 | public TemporaryFolder folder = new TemporaryFolder();
21 |
22 | @Test
23 | public void testGetLines() throws IOException {
24 | folder.create();
25 | String s = "select * from dbo.test\r\n" + "--test";
26 | File ff = folder.newFile("test.sql");
27 | FileUtils.write(ff, s, StandardCharsets.UTF_8);
28 | SourceLinesProvider sut = new SourceLinesProvider();
29 | SourceLine[] results = sut.getLines(new FileInputStream(ff), Charset.defaultCharset());
30 | Assert.assertEquals(2, results.length);
31 | Assert.assertEquals(24, results[0].getCount());
32 |
33 | }
34 |
35 | @Test
36 | public void testGetLines2() throws IOException {
37 | SourceLinesProvider sut = new SourceLinesProvider();
38 | SourceLine[] results = sut.getLines(null, Charset.defaultCharset());
39 | Assert.assertEquals(0, results.length);
40 |
41 | }
42 |
43 | @Test
44 | public void testGetLinesBOM() throws IOException {
45 | folder.create();
46 | File ff = folder.newFile("test.sql");
47 | BufferedWriter out = new BufferedWriter(
48 | new OutputStreamWriter(new FileOutputStream(ff), StandardCharsets.UTF_8));
49 | out.write('\ufeff');
50 | out.write('a');
51 | out.flush();
52 | out.close();
53 |
54 | SourceLinesProvider sut = new SourceLinesProvider();
55 | SourceLine[] results = sut.getLines(new FileInputStream(ff), StandardCharsets.UTF_8);
56 | Assert.assertEquals(1, results.length);
57 | Assert.assertEquals(1, results[0].getCount());
58 |
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/rules/BaseReportsProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules;
2 |
3 | import java.io.File;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.sonar.plugins.tsql.rules.files.BaseReportsProvider;
8 |
9 | public class BaseReportsProviderTest {
10 |
11 | @Test
12 | public void testGetNonExistingDir() {
13 | BaseReportsProvider cut = new BaseReportsProvider("test.xml");
14 | File[] files = cut.get("./test");
15 | Assert.assertEquals(0, files.length);
16 | }
17 |
18 | @Test
19 | public void testGetFilesInExistingDir() {
20 | String file = this.getClass().getClassLoader().getResource(".").getFile();
21 |
22 | BaseReportsProvider cut = new BaseReportsProvider(".xml");
23 | File[] files = cut.get(file);
24 | Assert.assertEquals(5, files.length);
25 | }
26 |
27 | @Test
28 | public void testGetSpecificFile() {
29 | String file = this.getClass().getClassLoader().getResource(".").getFile();
30 |
31 | BaseReportsProvider cut = new BaseReportsProvider("Gsample.xml");
32 | File[] files = cut.get(file);
33 | Assert.assertEquals(1, files.length);
34 | }
35 | }
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/rules/CgSqlIssuesParserTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules;
2 |
3 | import java.io.File;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
8 | import org.sonar.plugins.tsql.rules.parsers.CodeGuardIssuesParser;
9 |
10 | public class CgSqlIssuesParserTest {
11 |
12 | @Test
13 | public void testParser() {
14 |
15 | String file = this.getClass().getClassLoader().getResource("cgSample.xml").getFile();
16 | CodeGuardIssuesParser parser = new CodeGuardIssuesParser();
17 |
18 | TsqlIssue[] issues = parser.parse(new File(file));
19 | Assert.assertNotNull("Returned issues was null", issues);
20 | Assert.assertEquals("Expected 1 issues", 1, issues.length);
21 | TsqlIssue issue = issues[0];
22 | Assert.assertEquals("Descpriptions did not match",
23 | "Script should end with GO",
24 | issue.getDescription());
25 | Assert.assertEquals("File path", "C:\\TestTable.sql", issue.getFilePath());
26 | Assert.assertEquals("Line did not match", 6, issue.getLine());
27 | Assert.assertEquals("Descpriptions did not match", "SC001", issue.getType());
28 |
29 |
30 | }
31 |
32 | @Test
33 | public void testParserNonExising() {
34 |
35 | String file = "test.file";
36 | CodeGuardIssuesParser parser = new CodeGuardIssuesParser();
37 |
38 | TsqlIssue[] issues = parser.parse(new File(file));
39 | Assert.assertNotNull("Returned issues was null", issues);
40 |
41 |
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/rules/VsSqlIssuesParserTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules;
2 |
3 | import java.io.File;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.sonar.plugins.tsql.rules.issues.TsqlIssue;
8 | import org.sonar.plugins.tsql.rules.parsers.MsIssuesParser;
9 |
10 | public class VsSqlIssuesParserTest {
11 |
12 | private final MsIssuesParser parser = new MsIssuesParser();
13 |
14 | @Test
15 | public void testParser() {
16 | String file = this.getClass().getClassLoader().getResource("vsSample.xml").getFile();
17 | TsqlIssue[] issues = parser.parse(new File(file));
18 | Assert.assertNotNull("Returned issues was null", issues);
19 | Assert.assertEquals("Expected a single issue", 1, issues.length);
20 | TsqlIssue issue = issues[0];
21 | Assert.assertEquals("Descpriptions did not match",
22 | "The shape of the result set produced by a SELECT * statement will change if the underlying table or view structure changes.",
23 | issue.getDescription());
24 | Assert.assertEquals("File path", "c:\\Database1\\Procedure1.sql", issue.getFilePath());
25 | Assert.assertEquals("Line did not match", 6, issue.getLine());
26 | Assert.assertEquals("Descpriptions did not match", "Microsoft.Rules.Data.SR0001", issue.getType());
27 |
28 | }
29 |
30 | @Test
31 | public void testParserNonExistingFile() {
32 | final String file = "test";
33 | TsqlIssue[] issues = parser.parse(new File(file));
34 | Assert.assertNotNull("Returned issues was null", issues);
35 | Assert.assertEquals("Expected a single issue", 0, issues.length);
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/rules/definitions/CustomUserChecksProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.definitions;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.Map;
6 |
7 | import org.apache.commons.io.FileUtils;
8 | import org.junit.Assert;
9 | import org.junit.Test;
10 | import org.sonar.api.utils.internal.JUnitTempFolder;
11 | import org.sonar.plugins.tsql.checks.CustomUserChecksProvider;
12 | import org.sonar.plugins.tsql.checks.custom.SqlRules;
13 |
14 | public class CustomUserChecksProviderTest {
15 | @org.junit.Rule
16 | public JUnitTempFolder temp = new JUnitTempFolder();
17 |
18 | @Test
19 | public void testGetRules() throws IOException {
20 | File baseFile = temp.newFile("rulesTest", "xml");
21 | FileUtils.copyURLToFile(getClass().getResource("/customrulesSample.xml"), baseFile);
22 |
23 | CustomUserChecksProvider provider = new CustomUserChecksProvider();
24 | Map rules = provider.getRules(null, "rules", baseFile.getParentFile().getAbsolutePath());
25 | Assert.assertEquals(1, rules.size());
26 | Assert.assertEquals(8, rules.values().toArray(new SqlRules[0])[0].getRule().size());
27 | }
28 |
29 | @Test
30 | public void testNoRules() throws IOException {
31 |
32 | File baseFile = temp.newFile("ruledsTest", "xml");
33 | FileUtils.copyURLToFile(getClass().getResource("/customrulesSample.xml"), baseFile);
34 |
35 | CustomUserChecksProvider provider = new CustomUserChecksProvider();
36 | Map rules = provider.getRules(null, "rules", baseFile.getParentFile().getAbsolutePath());
37 | Assert.assertEquals(0, rules.size());
38 | }
39 |
40 | @Test
41 | public void testReadFile() throws IOException {
42 |
43 | File baseFile = temp.newFile("rulesTest", "xml");
44 | FileUtils.copyURLToFile(getClass().getResource("/customrulesSample.xml"), baseFile);
45 |
46 | CustomUserChecksProvider provider = new CustomUserChecksProvider();
47 | Map rules = provider.getRules(null, "rules", baseFile.getAbsolutePath());
48 | Assert.assertEquals(1, rules.size());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/rules/files/FilesProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.rules.files;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 |
6 | import org.junit.Assert;
7 | import org.junit.Rule;
8 | import org.junit.Test;
9 | import org.junit.rules.TemporaryFolder;
10 |
11 | public class FilesProviderTest {
12 |
13 | FilesProvider sut = new FilesProvider();
14 | @Rule
15 | public TemporaryFolder folder = new TemporaryFolder();
16 |
17 | @Test
18 | public void testNonExisting() {
19 | File[] files = sut.getFiles("test", "test", ".");
20 | Assert.assertEquals(0, files.length);
21 | }
22 |
23 | @Test
24 | public void testDefaultValues() throws IOException {
25 | folder.newFile("aatest.xml");
26 | File[] files = sut.getFiles("test.xml", "test.xml", folder.getRoot().getAbsolutePath());
27 | Assert.assertEquals(1, files.length);
28 |
29 | }
30 |
31 | @Test
32 | public void testFolderSpecified() throws IOException {
33 | folder.newFile("aatest.xml");
34 | File fsFolder = folder.newFolder("sample");
35 | File[] files = sut.getFiles("test.xml", folder.getRoot().getAbsolutePath(), fsFolder.getAbsolutePath());
36 | Assert.assertEquals(1, files.length);
37 | }
38 |
39 | @Test
40 | public void testSearchPathSpecified() throws IOException {
41 | folder.newFile("aatest.xml");
42 | File[] files = sut.getFiles("samplePrefix.xml", "test.xml", folder.getRoot().getAbsolutePath());
43 | Assert.assertEquals(1, files.length);
44 | }
45 |
46 | @Test
47 | public void testNonExistingSearchPathSpecified() throws IOException {
48 | folder.newFile("aatest.xml");
49 | File[] files = sut.getFiles("samplePrefix.xml", "a.xml", folder.getRoot().getAbsolutePath());
50 | Assert.assertEquals(0, files.length);
51 | }
52 |
53 | @Test
54 | public void testFindMultiple() throws IOException {
55 | folder.newFile("aatest.xml");
56 | folder.newFile("aaBsssjtest.xml");
57 |
58 | File testFolder = folder.newFolder("test");
59 | new File(testFolder, "0test.xml").createNewFile();
60 | new File(testFolder, "0tes.xml").createNewFile();
61 | File[] files = sut.getFiles("test.xml", "test.xml", folder.getRoot().getAbsolutePath());
62 | Assert.assertEquals(3, files.length);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/sensors/CoverageSensorTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.sensors;
2 |
3 | import java.io.File;
4 | import java.nio.file.Files;
5 | import java.util.Arrays;
6 | import java.util.List;
7 |
8 | import org.apache.commons.io.FileUtils;
9 | import org.junit.Assert;
10 | import org.junit.Test;
11 | import org.junit.rules.TemporaryFolder;
12 | import org.sonar.api.batch.fs.internal.DefaultInputFile;
13 | import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
14 | import org.sonar.api.batch.sensor.internal.SensorContextTester;
15 | import org.sonar.plugins.tsql.Constants;
16 | import org.sonar.plugins.tsql.coverage.SqlCoverCoverageProvider;
17 | import org.sonar.plugins.tsql.languages.TSQLLanguage;
18 |
19 | public class CoverageSensorTest {
20 |
21 | @Test
22 | public void test() throws Throwable {
23 | TemporaryFolder folder = new TemporaryFolder();
24 | folder.create();
25 |
26 | SensorContextTester ctxTester = SensorContextTester.create(folder.getRoot());
27 | String tempName = "GetStatusMessage.sql";
28 | String covReport = "test.xml";
29 | File f = folder.newFile(tempName);
30 | File coverage = folder.newFile(covReport);
31 |
32 | FileUtils.copyInputStreamToFile(this.getClass().getResourceAsStream("/coverage/Coverage.opencoverxml"),
33 | coverage);
34 |
35 | FileUtils.copyInputStreamToFile(this.getClass().getResourceAsStream("/coverage/TestCode.sql"), f);
36 | DefaultInputFile file1 = new TestInputFileBuilder(folder.getRoot().getAbsolutePath(), tempName)
37 | .initMetadata(new String(Files.readAllBytes(f.toPath()))).setLanguage(TSQLLanguage.KEY).build();
38 | ctxTester.fileSystem().add(file1);
39 | ctxTester.settings().setProperty(Constants.COVERAGE_FILE, coverage.getAbsolutePath());
40 | ctxTester.settings().setProperty(Constants.PLUGIN_SKIP_COVERAGE, false);
41 | CoverageSensor sut = new CoverageSensor(new SqlCoverCoverageProvider(ctxTester.settings(), ctxTester.fileSystem()));
42 | sut.execute(ctxTester);
43 | Assert.assertEquals((int) 2, (int) ctxTester.lineHits(file1.key(), 7));
44 |
45 | }
46 | @Test
47 | public void test2() throws Throwable {
48 | List names = Arrays.asList("dbo.test", "test", "other.test");
49 |
50 | String name = "test";
51 |
52 | if (names.contains(name)) {
53 |
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/sensors/antlr4/CComplexityVisitorTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.sensors.antlr4;
2 |
3 | import java.io.IOException;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.sonar.plugins.tsql.antlr.AntlrContext;
8 | import org.sonar.plugins.tsql.antlr.visitors.CComplexityVisitor;
9 | import org.sonar.plugins.tsql.antlr.visitors.CustomTreeVisitor;
10 | import org.sonar.plugins.tsql.helpers.AntlrUtils;
11 |
12 | public class CComplexityVisitorTest {
13 |
14 | @Test
15 | public void testIf() throws Throwable {
16 | String s = "IF DATENAME(weekday, GETDATE()) IN (N'Saturday', N'Sunday') SELECT 'Weekend'; ELSE "
17 | + " SELECT 'Weekday';";
18 | int result = calculate(s);
19 | Assert.assertEquals(2, result);
20 | }
21 |
22 | @Test
23 | public void testCase() throws Throwable {
24 | String s = "SELECT CASE WHEN MIN(value) <= 0 THEN 0 WHEN MAX(1/value) >= 100 THEN 1 ELSE 4 END "
25 | + "FROM testTable ; ";
26 | int result = calculate(s);
27 | Assert.assertEquals(3, result);
28 | }
29 |
30 | @Test
31 | public void testSelectWithWhere() throws Throwable {
32 | String s = "SELECT * from [dbo].[test] where a > 0 or b < 0 and x > 5;";
33 |
34 | int result = calculate(s);
35 | Assert.assertEquals(4, result);
36 | }
37 |
38 | @Test
39 | public void testReturn() throws Throwable {
40 | String s = "CREATE PROCEDURE checkstate @param varchar(11) AS IF (SELECT StateProvince FROM Person.vAdditionalContactInfo WHERE ContactID = @param) = 'WA' RETURN 1 ELSE RETURN 2; GO ";
41 | int result = calculate(s);
42 | Assert.assertEquals(3, result);
43 | }
44 |
45 | @Test
46 | public void testTryCatch() throws Throwable {
47 | String s = "BEGIN TRY SELECT 1/0; END TRY BEGIN CATCH END CATCH; ";
48 | int result = calculate(s);
49 | Assert.assertEquals(2, result);
50 | }
51 |
52 | @Test
53 | public void testWhile() throws Throwable {
54 | String s = "WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM Employee_Cursor; END; ";
55 | int result = calculate(s);
56 | Assert.assertEquals(2, result);
57 | }
58 |
59 | @Test
60 | public void testCase2() throws IOException {
61 | String s = "SELECT case when a > 0 then 'more' when a <0 then 'less' else '0' end from dbo.test";
62 | int result = calculate(s);
63 | Assert.assertEquals(3, result);
64 | }
65 |
66 | private int calculate(String s) throws IOException {
67 | AntlrContext result = AntlrUtils.getRequest(s);
68 | CComplexityVisitor vv = new CComplexityVisitor();
69 | CustomTreeVisitor visitor = new CustomTreeVisitor(vv);
70 | visitor.apply(result.getRoot());
71 | return vv.getMeasure();
72 |
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/java/org/sonar/plugins/tsql/sensors/antlr4/ComplexityVisitorTest.java:
--------------------------------------------------------------------------------
1 | package org.sonar.plugins.tsql.sensors.antlr4;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 | import org.sonar.plugins.tsql.antlr.AntlrContext;
6 | import org.sonar.plugins.tsql.antlr.visitors.ComplexityVisitor;
7 | import org.sonar.plugins.tsql.antlr.visitors.CustomTreeVisitor;
8 | import org.sonar.plugins.tsql.helpers.AntlrUtils;
9 |
10 | public class ComplexityVisitorTest {
11 |
12 | @Test
13 | public void testComplex() throws Throwable {
14 | String s = "SELECT SalesOrderID, SUM(LineTotal) AS SubTotal "
15 | + "FROM Sales.SalesOrderDetail left join dbo.x on t1.id = t2.id where a > 5"
16 | + "GROUP BY SalesOrderID " + "HAVING SUM(LineTotal) > 100000.00 " + "ORDER BY SalesOrderID, test ";
17 | int result = calculate(s);
18 | Assert.assertEquals(11, result);
19 | }
20 |
21 | @Test
22 | public void testSelect() throws Throwable {
23 | String s = "SELECT SalesOrderID, test, * from dbo.test";
24 | int result = calculate(s);
25 | Assert.assertEquals(4, result);
26 | }
27 |
28 | @Test
29 | public void testWhere() throws Throwable {
30 | String s = "SELECT SalesOrderID, test, * from dbo.test where id > 1 and id2 < 9";
31 | int result = calculate(s);
32 | Assert.assertEquals(6, result);
33 | }
34 |
35 | @Test
36 | public void testUnion() throws Throwable {
37 | String s = "SELECT a, b from dbo.test union select c,d from dbo.test2";
38 | int result = calculate(s);
39 | Assert.assertEquals(6, result);
40 | }
41 |
42 | @Test
43 | public void testFunction() throws Throwable {
44 | String s = "SELECT count(a) from dbo.test";
45 | int result = calculate(s);
46 | Assert.assertEquals(3, result);
47 | }
48 |
49 | @Test
50 | public void testCase() throws Throwable {
51 | String s = "SELECT case when a > 0 then 'more' when a <0 then 'less' else '0' end from dbo.test";
52 | int result = calculate(s);
53 | Assert.assertEquals(4, result);
54 | }
55 |
56 | private int calculate(String s) throws Throwable {
57 |
58 | AntlrContext result = AntlrUtils.getRequest(s);
59 | ComplexityVisitor vv = new ComplexityVisitor();
60 | CustomTreeVisitor visitor = new CustomTreeVisitor(vv);
61 | visitor.visit(result.getRoot());
62 | return vv.getMeasure();
63 |
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/cgSample.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/coverage/Coverage.opencoverxml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gretard/sonar-tsql-plugin/aadb5598bbb183c12df997ee9f3e053f962ce0f7/sonar-tsql-plugin/src/test/resources/coverage/Coverage.opencoverxml
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/coverage/TestCode.sql:
--------------------------------------------------------------------------------
1 |
2 | CREATE FUNCTION Accelerator.GetStatusMessage()
3 | RETURNS NVARCHAR(MAX)
4 | AS
5 | BEGIN
6 | DECLARE @NumParticles INT;
7 | SELECT @NumParticles = COUNT(1) FROM Accelerator.Particle;
8 | RETURN 'The Accelerator is prepared with ' + CAST(@NumParticles AS NVARCHAR(MAX)) + ' particles.';
9 | END;
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/coverage/[Accelerator].[AlertParticleDiscovered]:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE Accelerator.AlertParticleDiscovered
3 | @ParticleDiscovered NVARCHAR(MAX)
4 | AS
5 | BEGIN
6 | IF @ParticleDiscovered = 'Higgs Boson'
7 | BEGIN
8 | EXEC Accelerator.SendHiggsBosonDiscoveryEmail 'particle-discovery@new-era-particles.tsqlt.org';
9 | END;
10 | END;
11 |
12 |
13 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/coverage/[Accelerator].[GetStatusMessage]:
--------------------------------------------------------------------------------
1 |
2 | CREATE FUNCTION Accelerator.GetStatusMessage()
3 | RETURNS NVARCHAR(MAX)
4 | AS
5 | BEGIN
6 | DECLARE @NumParticles INT;
7 | SELECT @NumParticles = COUNT(1) FROM Accelerator.Particle;
8 | RETURN 'The Accelerator is prepared with ' + CAST(@NumParticles AS NVARCHAR(MAX)) + ' particles.';
9 | END;
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/coverage/[Accelerator].[IsExperimentReady]:
--------------------------------------------------------------------------------
1 |
2 | CREATE FUNCTION Accelerator.IsExperimentReady()
3 | RETURNS BIT
4 | AS
5 | BEGIN
6 | DECLARE @NumParticles INT;
7 |
8 | SELECT @NumParticles = COUNT(1) FROM Accelerator.Particle;
9 |
10 | IF @NumParticles > 2
11 | RETURN 1;
12 |
13 | RETURN 0;
14 | END;
15 |
16 |
17 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/coverage/[Accelerator].[SendHiggsBosonDiscoveryEmail]:
--------------------------------------------------------------------------------
1 |
2 | CREATE PROCEDURE Accelerator.SendHiggsBosonDiscoveryEmail
3 | @EmailAddress NVARCHAR(MAX)
4 | AS
5 | BEGIN
6 | RAISERROR('Not Implemented - yet',16,10);
7 | END;
8 |
9 |
10 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/testFiles/TestTable.sql:
--------------------------------------------------------------------------------
1 | GO
2 | --test
3 | SELECT FirstName, MiddleName
4 | FROM Person.Person WHERE LastName =
5 | 'Adams';
6 | BEGIN TRANSACTION;
7 |
8 | GO
9 |
10 | IF @@TRANCOUNT = 0
11 |
12 | BEGIN
13 |
14 | SELECT FirstName, MiddleName
15 |
16 | FROM Person.Person WHERE LastName = 'Adams';
17 |
18 | ROLLBACK TRANSACTION;
19 |
20 | PRINT N'Rolling back the transaction two times would cause an error.';
21 |
22 | END;
23 |
24 | ROLLBACK TRANSACTION;
25 |
26 | PRINT N'Rolled back the transaction.';
27 |
28 | GO
29 |
30 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/testFiles/cursorFlow.sql:
--------------------------------------------------------------------------------
1 | SET NOCOUNT ON;
2 |
3 | DECLARE @vendor_id int, @vendor_name nvarchar(50),
4 | @message varchar(80), @product nvarchar(50);
5 |
6 | PRINT '-------- Vendor Products Report --------';
7 |
8 | DECLARE vendor_cursor CURSOR FOR
9 | SELECT VendorID, Name
10 | FROM Purchasing.Vendor
11 | WHERE PreferredVendorStatus = 1
12 | ORDER BY VendorID;
13 |
14 | OPEN vendor_cursor
15 |
16 | FETCH NEXT FROM vendor_cursor
17 | INTO @vendor_id, @vendor_name
18 |
19 | WHILE @@FETCH_STATUS = 0
20 | BEGIN
21 | PRINT ' '
22 | SELECT @message = '----- Products From Vendor: ' +
23 | @vendor_name
24 |
25 | PRINT @message
26 |
27 | -- Declare an inner cursor based
28 | -- on vendor_id from the outer cursor.
29 |
30 | DECLARE product_cursor CURSOR FOR
31 | SELECT v.Name
32 | FROM Purchasing.ProductVendor pv, Production.Product v
33 | WHERE pv.ProductID = v.ProductID AND
34 | pv.VendorID = @vendor_id -- Variable value from the outer cursor
35 |
36 | OPEN product_cursor
37 | FETCH NEXT FROM product_cursor INTO @product
38 |
39 | IF @@FETCH_STATUS <> 0
40 | PRINT ' <>'
41 |
42 | WHILE @@FETCH_STATUS = 0
43 | BEGIN
44 |
45 | SELECT @message = ' ' + @product
46 | PRINT @message
47 | FETCH NEXT FROM product_cursor INTO @product
48 | END
49 | CLOSE vendor_cursor;
50 | DEALLOCATE vendor_cursor;
51 | CLOSE product_cursor
52 | DEALLOCATE product_cursor
53 | -- Get the next vendor.
54 | FETCH NEXT FROM vendor_cursor
55 | INTO @vendor_id, @vendor_name
56 | END
57 |
58 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/testFiles/cursorFlow2.sql:
--------------------------------------------------------------------------------
1 | SET NOCOUNT ON;
2 |
3 | DECLARE @vendor_id int, @vendor_name nvarchar(50),
4 | @message varchar(80), @product nvarchar(50);
5 |
6 | PRINT '-------- Vendor Products Report --------';
7 |
8 | DECLARE vendor_cursor CURSOR FOR
9 | SELECT VendorID, Name
10 | FROM Purchasing.Vendor
11 | WHERE PreferredVendorStatus = 1
12 | ORDER BY VendorID;
13 |
14 | OPEN vendor_cursor
15 |
16 | FETCH NEXT FROM vendor_cursor
17 | INTO @vendor_id, @vendor_name
18 |
19 | WHILE @@FETCH_STATUS = 0
20 | BEGIN
21 | PRINT ' '
22 | SELECT @message = '----- Products From Vendor: ' +
23 | @vendor_name
24 |
25 | PRINT @message
26 |
27 | -- Declare an inner cursor based
28 | -- on vendor_id from the outer cursor.
29 |
30 | DECLARE product_cursor CURSOR FOR
31 | SELECT v.Name
32 | FROM Purchasing.ProductVendor pv, Production.Product v
33 | WHERE pv.ProductID = v.ProductID AND
34 | pv.VendorID = @vendor_id -- Variable value from the outer cursor
35 |
36 | OPEN product_cursor
37 | FETCH NEXT FROM product_cursor INTO @product
38 |
39 | IF @@FETCH_STATUS <> 0
40 | PRINT ' <>'
41 |
42 | WHILE @@FETCH_STATUS = 0
43 | BEGIN
44 |
45 | SELECT @message = ' ' + @product
46 | PRINT @message
47 | FETCH NEXT FROM product_cursor INTO @product
48 | END
49 |
50 | CLOSE product_cursor
51 | DEALLOCATE product_cursor
52 | -- Get the next vendor.
53 | FETCH NEXT FROM vendor_cursor
54 | INTO @vendor_id, @vendor_name
55 | END
56 | CLOSE vendor_cursor;
57 | DEALLOCATE vendor_cursor;
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/testFiles/scriptExample.sql:
--------------------------------------------------------------------------------
1 | SET NOCOUNT ON;
2 |
3 | DECLARE @vendor_id int, @vendor_name nvarchar(50),
4 | @message varchar(80), @product nvarchar(50);
5 |
6 | PRINT '-------- Vendor Products Report --------';
7 |
8 | DECLARE vendor_cursor CURSOR FOR
9 | SELECT VendorID, Name
10 | FROM Purchasing.Vendor
11 | WHERE PreferredVendorStatus = 1
12 | ORDER BY VendorID;
13 |
14 | OPEN vendor_cursor
15 |
16 | FETCH NEXT FROM vendor_cursor
17 | INTO @vendor_id, @vendor_name
18 |
19 | /*WHILE @@FETCH_STATUS = 0
20 | BEGIN
21 | PRINT ' '
22 | SELECT @message = '----- Products From Vendor: ' +
23 | @vendor_name
24 |
25 | PRINT @message
26 |
27 | -- Declare an inner cursor based
28 | -- on vendor_id from the outer cursor.
29 |
30 | DECLARE product_cursor CURSOR FOR
31 | SELECT v.Name
32 | FROM Purchasing.ProductVendor pv, Production.Product v
33 | WHERE pv.ProductID = v.ProductID AND
34 | pv.VendorID = @vendor_id -- Variable value from the outer cursor
35 |
36 | OPEN product_cursor
37 | FETCH NEXT FROM product_cursor INTO @product
38 |
39 | IF @@FETCH_STATUS <> 0
40 | PRINT ' <>'
41 |
42 | WHILE @@FETCH_STATUS = 0
43 | BEGIN
44 |
45 | SELECT @message = ' ' + @product
46 | PRINT @message
47 | FETCH NEXT FROM product_cursor INTO @product
48 | END
49 |
50 | CLOSE product_cursor
51 | DEALLOCATE product_cursor
52 | -- Get the next vendor.
53 | FETCH NEXT FROM vendor_cursor
54 | INTO @vendor_id, @vendor_name
55 | END */
56 | --CLOSE vendor_cursor;
57 | DEALLOCATE vendor_cursor;
58 |
59 | WAITFOR TIME '22:20';
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/testFiles/scriptExample2.sql:
--------------------------------------------------------------------------------
1 | SET NOCOUNT ON;
2 |
3 | DECLARE @vendor_id int, @vendor_name nvarchar(50),
4 | @message varchar(80), @product nvarchar(50);
5 |
6 | PRINT '-------- Vendor Products Report --------';
7 |
8 | DECLARE vendor_cursor CURSOR FOR
9 | SELECT VendorID, Name
10 | FROM Purchasing.Vendor
11 | WHERE PreferredVendorStatus = 1
12 | ORDER BY VendorID;
13 |
14 | OPEN vendor_cursor
15 |
16 | FETCH NEXT FROM vendor_cursor
17 | INTO @vendor_id, @vendor_name
18 |
19 | WHILE @@FETCH_STATUS = 0
20 | BEGIN
21 | PRINT ' '
22 |
23 | DECLARE product_cursor CURSOR FOR
24 | SELECT v.Name
25 | FROM Purchasing.ProductVendor pv, Production.Product v
26 | WHERE pv.ProductID = v.ProductID AND
27 | pv.VendorID = @vendor_id -- Variable value from the outer cursor
28 |
29 |
30 | OPEN product_cursor
31 | FETCH NEXT FROM product_cursor INTO @product
32 |
33 | IF @@FETCH_STATUS <> 0
34 | PRINT ' <>'
35 |
36 | WHILE @@FETCH_STATUS = 0
37 | BEGIN
38 |
39 | SELECT @message = ' ' + @product
40 | PRINT @message
41 | FETCH NEXT FROM product_cursor INTO @product
42 | END
43 |
44 | CLOSE product_cursor
45 | DEALLOCATE product_cursor
46 |
47 |
48 | END
49 |
50 | select * from test
51 | CLOSE vendor_cursor;
52 |
53 | DEALLOCATE vendor_cursor;
54 |
55 | WAITFOR '10:00:00'
56 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/testFiles/scriptExample3.sql:
--------------------------------------------------------------------------------
1 | SELECT * from test
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/testFiles/sp_Get.sql:
--------------------------------------------------------------------------------
1 | create TABLE [dbo].[TestTable]
2 | (
3 | [Id] INT NOT NULL PRIMARY KEY,
4 | [Name] NVARCHAR(MAX) NULL
5 | )
6 | --lkasjdkljasd
7 | // askjdhjksad
8 |
--------------------------------------------------------------------------------
/sonar-tsql-plugin/src/test/resources/vsSample.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Microsoft.Rules.Data.SR0001
5 | The shape of the result set produced by a SELECT * statement will change if the underlying table or view structure changes.
6 | c:\Database1\Procedure1.sql
7 | 6
8 | 9
9 | Warning
10 |
11 |
--------------------------------------------------------------------------------