]> source.dussan.org Git - sonarqube.git/commitdiff
Extract implementation from plugin API and create new module sonar-plugin-api-impl
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 9 Jul 2019 20:30:56 +0000 (15:30 -0500)
committerSonarTech <sonartech@sonarsource.com>
Fri, 12 Jul 2019 18:21:15 +0000 (20:21 +0200)
556 files changed:
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/coverage/ItCoverageSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/coverage/OverallCoverageSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/coverage/UtCoverageSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/extensions/XooPostJobTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/CpdTokenizerSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SignificantCodeSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/AnalysisErrorSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/scm/XooBlameCommandTest.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactory.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactoryTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/measurecomputer/MeasureComputerContextImplTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/component/ConfigurationRepositoryTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/IntegrateCrossProjectDuplicationsTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImplTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/ComponentIssuesLoaderTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/DefaultAssigneeTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/ProjectTrackerBaseLazyInputTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/SiblingsIssueMergerTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/filter/IssueFilterTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/ProjectCleanerTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/PurgeDatastoresStepTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/RatingSettingsTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadQualityGateStepTest.java
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
server/sonar-ce/src/test/java/org/sonar/ce/configuration/CeConfigurationImplTest.java
server/sonar-ce/src/test/java/org/sonar/ce/configuration/CeWorkerCountSettingWarningTest.java
server/sonar-ce/src/test/java/org/sonar/ce/queue/CeQueueCleanerTest.java
server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskInterrupterProviderTest.java
server/sonar-db-core/src/test/java/org/sonar/db/CoreTestDb.java
server/sonar-db-core/src/test/java/org/sonar/db/DefaultDatabaseTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/engine/MigrationEngineImplTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DeletePersonMeasuresTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v73/FixMissingQualityProfilesOnOrganizationsTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v73/PopulateSubscriptionOnOrganizationsTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/AddApplicationCreatorAndPortfolioCreatorToSonarAdministratorTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/CleanOrphanRowsInCeTablesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v76/DeleteModuleAndFolderMeasuresTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v78/UpdateSecurityHotspotsStatusesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v79/ReindexIssuesAndRulesTest.java
server/sonar-server-common/src/main/java/org/sonar/server/component/index/ComponentIndexDefinition.java
server/sonar-server-common/src/main/java/org/sonar/server/config/ConfigurationProvider.java
server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java
server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java
server/sonar-server-common/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java
server/sonar-server-common/src/main/java/org/sonar/server/rule/index/RuleIndexDefinition.java
server/sonar-server-common/src/main/java/org/sonar/server/setting/ChildSettings.java
server/sonar-server-common/src/main/java/org/sonar/server/user/index/UserIndexDefinition.java
server/sonar-server-common/src/main/java/org/sonar/server/view/index/ViewIndexDefinition.java
server/sonar-server-common/src/test/java/org/sonar/server/config/ConfigurationProviderTest.java
server/sonar-server-common/src/test/java/org/sonar/server/es/EsClientProviderTest.java
server/sonar-server-common/src/test/java/org/sonar/server/es/IndexDefinitionContextTest.java
server/sonar-server-common/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java
server/sonar-server-common/src/test/java/org/sonar/server/es/metadata/MetadataIndexDefinitionBridge.java
server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/FakeIndexDefinition.java
server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewAuthorizedIndexTest.java
server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewIndexTest.java
server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewRegularIndexTest.java
server/sonar-server-common/src/test/java/org/sonar/server/issue/index/IssueIndexDefinitionTest.java
server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java
server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java
server/sonar-server-common/src/test/java/org/sonar/server/log/ServerLoggingTest.java
server/sonar-server-common/src/test/java/org/sonar/server/platform/DefaultServerUpgradeStatusTest.java
server/sonar-server-common/src/test/java/org/sonar/server/platform/ServerImplTest.java
server/sonar-server-common/src/test/java/org/sonar/server/platform/StartupMetadataProviderTest.java
server/sonar-server-common/src/test/java/org/sonar/server/platform/UrlSettingsTest.java
server/sonar-server-common/src/test/java/org/sonar/server/platform/WebServerImplTest.java
server/sonar-server-common/src/test/java/org/sonar/server/platform/serverid/ServerIdChecksumTest.java
server/sonar-server-common/src/test/java/org/sonar/server/rule/index/RuleIndexDefinitionTest.java
server/sonar-server-common/src/test/java/org/sonar/server/setting/ChildSettingsTest.java
server/sonar-server-common/src/test/java/org/sonar/server/user/index/UserIndexDefinitionTest.java
server/sonar-server-common/src/test/java/org/sonar/server/util/OkHttpClientProviderTest.java
server/sonar-server-common/src/test/java/org/sonar/server/view/index/ViewIndexDefinitionTest.java
server/sonar-server-common/src/test/java/org/sonar/server/webhook/WebhookCallerImplTest.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java
server/sonar-server/src/test/java/org/sonar/server/app/ProcessCommandWrapperImplTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/CredentialsExternalAuthenticationTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/JwtHttpHandlerTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/JwtSerializerTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplOrgMembershipSyncTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/ws/ValidateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java
server/sonar-server/src/test/java/org/sonar/server/badge/ws/QualityGateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/badge/ws/SvgGeneratorTest.java
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderTest.java
server/sonar-server/src/test/java/org/sonar/server/ce/http/CeHttpClientTest.java
server/sonar-server/src/test/java/org/sonar/server/es/IndexCreatorTest.java
server/sonar-server/src/test/java/org/sonar/server/es/IndexerStartupTaskTest.java
server/sonar-server/src/test/java/org/sonar/server/es/MigrationEsClientImplTest.java
server/sonar-server/src/test/java/org/sonar/server/es/RecoveryIndexerTest.java
server/sonar-server/src/test/java/org/sonar/server/health/NodeHealthModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/health/NodeHealthProviderImplTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTestOnSonarCloud.java
server/sonar-server/src/test/java/org/sonar/server/measure/live/LiveMeasureComputerImplTest.java
server/sonar-server/src/test/java/org/sonar/server/notification/NotificationDaemonTest.java
server/sonar-server/src/test/java/org/sonar/server/notification/NotificationMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/notification/ws/DispatchersImplTest.java
server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java
server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/organization/ws/OrganizationsWsModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndexDefinition.java
server/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/db/EmbeddedDatabaseFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/db/EmbeddedDatabaseTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SettingsSectionTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/StandaloneSystemSectionTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/WebSystemInfoModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/GlobalSystemSectionTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/NodeSystemSectionTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/serverid/ServerIdFactoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/serverid/ServerIdManagerTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/web/WebPagesCacheTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/ws/ChangeLogLevelActionModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/plugins/PluginFileSystemTest.java
server/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java
server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ProjectsInWarningDaemonTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListenerTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java
server/sonar-server/src/test/java/org/sonar/server/setting/ws/CheckSecretKeyActionTest.java
server/sonar-server/src/test/java/org/sonar/server/setting/ws/EncryptActionTest.java
server/sonar-server/src/test/java/org/sonar/server/setting/ws/GenerateSecretKeyActionTest.java
server/sonar-server/src/test/java/org/sonar/server/setting/ws/ValuesActionTest.java
server/sonar-server/src/test/java/org/sonar/server/settings/ProjectConfigurationLoaderImplTest.java
server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryClientTest.java
server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java
server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalActionTest.java
server/sonar-server/src/test/java/org/sonar/server/ui/ws/SettingsActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/SecurityRealmFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/user/SystemPasscodeImplTest.java
server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java
server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java
server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/CreateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionHomepageTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/CurrentActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/HomepageTypesImplTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/UpdateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/UpdateLoginActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/ws/WebServiceFilterTest.java
sonar-application/src/main/java/org/sonar/application/App.java
sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java
sonar-core/src/test/java/org/sonar/core/extension/CoreExtensionsInstallerTest.java
sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/AbstractProjectOrModule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputProject.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextPointer.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextRange.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/CharHandler.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/FileHashComputer.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/IntArrayList.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineCounter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineHashComputer.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineOffsetCounter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AbsolutePathPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AbstractFilePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AndPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/DefaultFilePredicates.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FalsePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/LanguagePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/NotPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OperatorPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OptimizedFilePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OptimizedFilePredicateAdapter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OrPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/PathPatternPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/RelativePathPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/StatusPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/TruePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/TypePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/URIPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/postjob/internal/DefaultPostJobDescriptor.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/postjob/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultActiveRule.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRule.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRuleParam.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/ActiveRulesBuilder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRules.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRuleParam.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRules.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewActiveRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewRuleParam.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/RulesBuilder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCode.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/code/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/coverage/internal/DefaultCoverage.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/coverage/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/cpd/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisError.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/error/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/DefaultStorable.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultNoSonarFilter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/measure/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/rule/internal/DefaultAdHocRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/rule/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTable.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/symbol/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/MapSettings.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/ConfigurationBridge.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MapSettings.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MultivalueProperty.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/package-info.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/MetadataLoader.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/PluginContextImpl.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/SonarRuntimeImpl.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/package-info.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/AbstractProjectOrModule.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultFileSystem.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultIndexedFile.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputComponent.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputDir.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputFile.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputModule.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputProject.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextPointer.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextRange.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/FileMetadata.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/Metadata.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/PathPattern.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/SensorStrategy.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/TestInputFileBuilder.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/CharHandler.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/FileHashComputer.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/IntArrayList.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineCounter.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineHashComputer.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineOffsetCounter.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/package-info.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/package-info.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbsolutePathPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbstractFilePredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AndPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicates.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FalsePredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FilenamePredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/LanguagePredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/NotPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OperatorPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicateAdapter.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OrPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/PathPatternPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/RelativePathPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/StatusPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TruePredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TypePredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/URIPredicate.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/package-info.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/AbstractDefaultIssue.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssue.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssueLocation.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultNoSonarFilter.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/package-info.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/ActiveRulesBuilder.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultActiveRules.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultRules.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/RulesBuilder.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAdHocRule.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAnalysisError.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCoverage.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCpdTokens.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultExternalIssue.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultHighlighting.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultMeasure.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultPostJobDescriptor.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSensorDescriptor.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSignificantCode.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultStorable.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSymbolTable.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/InMemorySensorStorage.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SensorContextTester.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SyntaxHighlightingRule.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/package-info.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewRepository.java
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/RuleDefinitionContext.java [deleted file]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/RulesDefinitionContext.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/MetadataLoader.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/PluginContextImpl.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/charhandler/IntArrayListTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultFileSystemTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputDirTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputFileTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputModuleTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputProjectTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/FileMetadataTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/MetadataTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/PathPatternTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/TestInputFileBuilderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/AndPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/DefaultFilePredicatesTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/OrPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/RelativePathPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/DefaultRulesTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/NewActiveRuleTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCodeTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisErrorTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptorTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorageTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocationTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/rule/internal/DefaultAdHocRuleTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/config/internal/MapSettingsTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/config/internal/MultivaluePropertyTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MapSettingsTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MultivaluePropertyTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/MetadataLoaderTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/SonarRuntimeImplTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultFileSystemTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputDirTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputFileTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputModuleTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputProjectTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/FileMetadataTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/MetadataTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/PathPatternTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/TestInputFileBuilderTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/charhandler/IntArrayListTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/AndPredicateTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicatesTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicateTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FilenamePredicateTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/OrPredicateTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/RelativePathPredicateTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/DefaultRulesTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/RulesBuilderTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAdHocRuleTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAnalysisErrorTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultCpdTokensTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultExternalIssueTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultHighlightingTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueLocationTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultMeasureTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSensorDescriptorTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSignificantCodeTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSymbolTableTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/InMemorySensorStorageTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/SensorContextTesterTest.java [deleted file]
sonar-plugin-api-impl/src/test/java/org/sonar/api/internal/MetadataLoaderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/resources/org/sonar/api/batch/fs/internal/fs/glyphicons-halflings-regular.woff [new file with mode: 0644]
sonar-plugin-api-impl/src/test/resources/org/sonar/api/impl/fs/glyphicons-halflings-regular.woff [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/rules/Rule.java
sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/CheckFactoryTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/NewActiveRuleTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/config/EmailSettingsTest.java
sonar-plugin-api/src/test/java/org/sonar/api/issue/NoSonarFilterTest.java
sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/FileExclusionsTest.java
sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoaderTest.java
sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionI18nLoaderTest.java
sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionTest.java
sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisTempFolderProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/config/DefaultConfiguration.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/CpdExecutor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/CpdSettings.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/JavaCpdBlockIndexerSensor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/index/SonarCpdBlockIndex.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/DefaultCoverageBlock.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/DefaultTestCase.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/DefaultTestable.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/TestPlanBuilder.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/test/TestableBuilder.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/InputModuleHierarchy.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssueFilters.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssuePublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ignore/EnforceIssuesFilter.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ignore/IgnoreIssuesFilter.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ignore/pattern/IssueExclusionPatternInitializer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsRegexpScanner.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobOptimizer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/PostJobWrapper.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ActiveRulesPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ChangedLinesPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ComponentsPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/SourcePublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositories.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DefaultInputModuleHierarchy.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputModuleHierarchyProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputProjectProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfigurationProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfigurationProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectLock.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorBuilder.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/WorkDirectoriesInitializer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AbstractCoverageAndDuplicationExclusions.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFilters.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicates.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultModuleFileSystem.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputComponentStore.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/MetadataGenerator.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleCoverageAndDuplicationExclusions.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStore.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectCoverageAndDuplicationExclusions.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/ProjectFileIndexer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/StatusDetection.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/DefaultBlameOutput.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorOptimizer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorWrapper.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorsExecutor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/ZeroCoverageSensor.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisTempFolderProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionnaryTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionnaryTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/JavaCpdBlockIndexerSensorTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueImporterTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageReportParserTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionReportParserTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionSensorTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/EnforceIssuesFilterTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/IgnoreIssuesFilterTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/BranchMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/DeprecatedBranchMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageAndDuplicationExclusionsTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleSensorsExecutorTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ProjectCoverageExclusionsTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/platform/DefaultServerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/DefaultPostJobContextTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/PostJobOptimizerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesBuilderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectLockTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ProjectExclusionFiltersTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/DefaultBlameOutputTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorOptimizerTest.java

index 7455f077caa6e007d95ce743a94742f6e4be020a..892081dc202eacad0a60354a01df736046a78284 100644 (file)
@@ -25,8 +25,8 @@ import org.junit.Test;
 import org.sonar.api.Plugin;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.context.PluginContextImpl;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.PluginContextImpl;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
 import org.sonar.xoo.global.GlobalProjectSensor;
 import org.sonar.xoo.rule.OneExternalIssuePerLineSensor;
index 161cac8649f29d246bf4f9f14fd82b4dea2a10b1..dd4ebcaa1d092cad3605389146d93a126571c80e 100644 (file)
@@ -28,9 +28,9 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 71c336163f2e898af8580f23d0e91187ea2442f1..7d453c9ae4018e47a5550ffce89c581023babecd 100644 (file)
@@ -28,9 +28,9 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index dde6eddac2c475ca476e69d4c3617439621c65c4..cf9023c9cf743c13f569287ed0d782b985686cc8 100644 (file)
@@ -28,9 +28,9 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 0754cdc12c0bda41e497d88ded9bcd20610ca33d..cb891efd9b19edcc685b652f1a5e4b0892c73c58 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.batch.postjob.PostJobContext;
 import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index aaad31d3da411206fecd62b2c1ae127a6e2c68ee..1eb4fd88650898236f1ba1a7d418e8ea6006c834 100644 (file)
@@ -28,9 +28,9 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
index bc6e6b0050038b7f65a4a9e5f329f3c49de9e761..833a05570e51af0f6984a5768fa70c91db999bd7 100644 (file)
@@ -30,9 +30,9 @@ import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 
index 6acb0ed39e1322253808c74320eab153bbf1abcb..03adee97ed379980e0c99503dac9bcdadc6361cd 100644 (file)
@@ -29,11 +29,11 @@ import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.fs.DefaultTextRange;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.DefaultTextRange;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 1e91363bbed78f2f02be7a6214c17da9b1876c61..bef08ad74f42bfda2e28cde6fcb7d6aecbe627f9 100644 (file)
@@ -27,11 +27,11 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.fs.DefaultTextRange;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.DefaultTextRange;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 import org.sonar.xoo.Xoo;
 
 import static org.assertj.core.api.Assertions.assertThat;
index fc4e865dc018cd1d934e09993b417efe38ceef01..01a6c84f05b3494b94a60b8e62f06e56f4e6efa1 100644 (file)
@@ -27,10 +27,10 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 060925067e47523027dd96b0131888d59ad8fdab..f08e3bd202acf2a826ce772554e9aaee1ce447e3 100644 (file)
@@ -30,10 +30,10 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.sensor.error.AnalysisError;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 24bec8caf7db080ba1949b221a5aa998996d170a..b44eb9610b5cf53726ddf1c249e26d66b188377b 100644 (file)
@@ -27,11 +27,11 @@ import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
-import org.sonar.api.impl.sensor.SensorContextTester;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
 import org.sonar.xoo.Xoo;
 
index e37c8f5df6a668846058bb9fe21c67d0cb8082fa..e0620cf12508e4c9c9985712ee2c612039c950c1 100644 (file)
@@ -23,11 +23,11 @@ import org.sonar.api.SonarEdition;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.SonarQubeSide;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.rule.RulesDefinition;
 import org.sonar.api.utils.Version;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -37,7 +37,7 @@ public class XooRulesDefinitionTest {
   @Before
   public void setUp() {
     XooRulesDefinition def = new XooRulesDefinition(SonarRuntimeImpl.forSonarQube(Version.create(7, 3), SonarQubeSide.SCANNER, SonarEdition.COMMUNITY));
-    context = new RuleDefinitionContext();
+    context = new RulesDefinitionContext();
     def.define(context);
   }
 
index 13a780e7dc7ac836862372a8b116ac66d3cd954e..fbfc8c0c89b6e54816b781fb55a3717cce6eb72f 100644 (file)
@@ -31,9 +31,9 @@ import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.scm.BlameCommand.BlameInput;
 import org.sonar.api.batch.scm.BlameCommand.BlameOutput;
 import org.sonar.api.batch.scm.BlameLine;
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.xoo.Xoo;
 
index 1c7af5ed99c12033685ae51743d6c8f6b27e7d46..75f7c85218714740388335b19730fd622e5686f2 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.ce.task.projectanalysis.analysis;
 import org.sonar.api.ce.ComputeEngineSide;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.ConfigurationBridge;
+import org.sonar.api.config.internal.ConfigurationBridge;
 import org.sonar.db.DbClient;
 import org.sonar.db.component.BranchType;
 import org.sonar.server.setting.ChildSettings;
index 1587d3f49bf7553c9825758b62ddb57ee0a3cf7b..8b91d9fe5b55d866695fca1779a471978feca468 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.ce.task.projectanalysis.analysis;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.ce.task.projectanalysis.component.DefaultBranchImpl;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
index ad305a455ce4f8b1d6d5cd9bf3d604749c5d94df..783adc1ab6c358ed0b1e52da482943426bec1b3f 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.ce.measure.Component;
 import org.sonar.api.ce.measure.MeasureComputer;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.Duration;
index 948f94f4fde8dbe043c00776a142504029d267f6..240637cc3e6c59601e897fcf8bac16d84f39a46e 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
 import org.sonar.ce.task.projectanalysis.analysis.Branch;
index dfd6311e802d1d78b4bcda1df4343bd6ea96b544..f5277d8b49fc81743bc597d51fe68fb60184a9f5 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Collection;
 import java.util.Collections;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
index 00d9a76ac190bc9238d940a73e43255eaf0c0beb..63d6cd19a90472a9866567e9fdf12b10b5b4cea7 100644 (file)
@@ -34,7 +34,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.ce.task.CeTask;
 import org.sonar.ce.task.projectanalysis.filemove.ScoreMatrix.ScoreFile;
 
index cd7249ce51fabe59c0266fc00ec7872c871e3532..5224fe99cba57f13fac44505a6e8e5252c631a29 100644 (file)
@@ -36,7 +36,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.utils.System2;
 import org.sonar.core.issue.DefaultIssue;
index 1bcc1485405e1a5d88b9a5555666f2a57427adad..934a2546730d74536324b9a28d06374fba264ac0 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderImpl;
 import org.sonar.ce.task.projectanalysis.analysis.Organization;
 import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository;
index 9be4ccbc5b023f1f1492b629651a94bf230529c0..4c4ba86943e99ec340c77642499bd192974e293d 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
index ecec80844796554a615b1ea143569062211715a8..44dc2af2e1fced572ff0a332d0758bd6b8d1e7f4 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Date;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
 import org.sonar.ce.task.projectanalysis.component.Component;
index fbafc6ba2576330b079772acb92ed3bfa02d97f0..16e7419b6288aae503b911c2e456b90f9d3501cf 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.System2;
index 0672bf65c120f1b13b993a178c786b59d2da8548..01178f2275ed9aacb9ce8e0551cc3cff497ff156 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository;
index d1cef3b521e131f7d6d3638739a1e0a01bd998f9..1315ab2f7d637de5bcf9cb7bcbf09d22d3b63b7f 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.config.PurgeConstants;
 import org.sonar.core.config.PurgeProperties;
 import org.sonar.db.DbSession;
index 877fa6965a96ff064bb41c2d3f72b52abfe3d1d8..dbf8227eaee88ef540999e558ac31b83ba3bf05e 100644 (file)
@@ -31,7 +31,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository;
index 6e83dd97d6167c42ee23a1e0f28f2e4d2e893be7..583315747569e1d25598a0d13b50913e3206edce 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.MessageException;
 import org.sonar.core.config.CorePropertyDefinitions;
index a5389373f8e2ce2397e745f858bf4a192f58595e..c2b3b13c679044092831770abf7aeb37fd6eca64 100644 (file)
@@ -33,7 +33,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.LogAndArguments;
index eaee9b9da1b62ab24473fd43d071457b87741cf1..809c2505fd6038dd8f5287aa4efe9ecdae56b1c6 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
 import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository;
 import org.sonar.ce.task.projectanalysis.metric.Metric;
index 51eabf72207db263db7cf7b7c4469266e199893f..2358876fb0e92ef4999ae497f6e59f4f7fddc162 100644 (file)
@@ -27,8 +27,8 @@ import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarQubeVersion;
 import org.sonar.api.config.EmailSettings;
-import org.sonar.api.impl.context.MetadataLoader;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.MetadataLoader;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.profiles.AnnotationProfileParser;
 import org.sonar.api.profiles.XMLProfileParser;
 import org.sonar.api.profiles.XMLProfileSerializer;
index eb6c5923d5991977f3f1166e50553727dbf72ca5..ac9b41655fbd8d975043999ba376351ed0ad9b87 100644 (file)
@@ -23,8 +23,8 @@ import java.util.Random;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.ConfigurationBridge;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.ConfigurationBridge;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 
 import static java.lang.Math.abs;
index a271c5747ddcb028b2753c0ab91b3a2a17d9d3e1..d308f13ae07db78aa86e41fbbc42e18055c0e2ef 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.ce.configuration;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 
index fd96fe75b70bc6162f72cddbeba7919db41a9fc6..771b13c21a25823c231fa7bfabb11329441cb8bd 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Optional;
 import org.apache.commons.io.IOUtils;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.ServerUpgradeStatus;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
index 3bb899e9ff2027df911159fff7a835dc1df60355..284c8efc3f0124b47a18e8a9e42453b8ae792094 100644 (file)
@@ -24,7 +24,7 @@ import java.util.Random;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.task.CeTaskInterrupter;
 
index 035c4049ed46e3e5919887dba2edf79b6f791fe4..e673d167ac4457096316584be7ba5d7f66a1b429 100644 (file)
@@ -38,7 +38,7 @@ import org.dbunit.IDatabaseTester;
 import org.dbunit.dataset.datatype.IDataTypeFactory;
 import org.junit.AssumptionViolatedException;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.db.dialect.H2;
index 6c27183b9540ec465cd98742e0033a9e0f92a003..45a55796ff553583fcc89c7365745dfeb93f48b2 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.db.dialect.PostgreSql;
 import org.sonar.process.logging.LogbackHelper;
 
index fe0d5668a7699b7736132378fff58d8bc9de9cd2..4d83aa022e7eaeca177de9d6b0adc995c206669d 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Date;
 import java.util.Optional;
 import org.junit.Test;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Scopes;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
index cab3aa7752e67c71adc380d858e062e8b18db198..9f02622b7a8bd6f0b0be0871c40d031604fc05dc 100644 (file)
@@ -23,8 +23,8 @@ import java.sql.SQLException;
 import java.util.List;
 import java.util.Optional;
 import org.junit.Test;
-import org.sonar.api.impl.config.ConfigurationBridge;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.ConfigurationBridge;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.process.ProcessProperties;
 import org.sonar.server.platform.db.migration.SupportsBlueGreen;
index 35bf49c836309673106b7287bc7b30ca890caad6..e0d21418e1628abc6e1b3ecba6967cdc24327a5c 100644 (file)
@@ -24,7 +24,6 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.commons.lang.math.RandomUtils;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
 import org.sonar.db.CoreDbTester;
 import org.sonar.server.platform.db.migration.step.DataChange;
 
index 787dec23b9318b7615d4f4720b7da2a72b7586c6..fb2bb458e95878ad192fbd1544c0d9597303bddb 100644 (file)
@@ -25,7 +25,7 @@ import java.util.stream.Collectors;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactoryFast;
index de32e5f073024fa1757546127c2759230763c961..f86ee0f6811e4c980bb3a2bc4bd5a20f47d9792a 100644 (file)
@@ -26,7 +26,7 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.Uuids;
index 82077969b155e14893c0f203271015f397af4474..f50108a334df87602552615cda712240bce00279 100644 (file)
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
 import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidProvider;
index 06193a6f394c68c8be7df9945ef68e8444b61e38..51361b81e2bc8e7e1aa39e57dcb346f04d801a37 100644 (file)
@@ -27,7 +27,7 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
 
index c29ac6af95e352e1e41f4333cd4e7239445074a9..5c69599cd7a3e66f01141005ba97eb853c8ed8e8 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.platform.db.migration.version.v76;
 import java.sql.SQLException;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.db.CoreDbTester;
 
 import static java.lang.String.valueOf;
index 05f63284b71c9ede82d6fe66cbf24596b3dc57e0..c6b7ba55a5ed1b1d478b18b8ad733ee327dfb3e8 100644 (file)
@@ -26,7 +26,7 @@ import org.apache.commons.lang.math.RandomUtils;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
index 1175dae3ce671c86ff4c3a77de4558fc25defc61..be656e9750a9c4680a4a88002c9d3f4f398906e0 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.platform.db.migration.version.v79;
 import java.sql.SQLException;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.db.CoreDbTester;
 import org.sonar.server.platform.db.migration.es.MigrationEsClient;
 import org.sonar.server.platform.db.migration.step.DataChange;
index 4a9cc66d6b9b783b37503dee3d1d485036ba87ef..dde34c989a09f3f5568c4a0bac2891cad34e6b8e 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.component.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 8ed3a8044c4ce4b8f3c6f55b66d7b30b51558dc9..bd3ff03f8f88e517f8ff45c0a2db146c899a6073 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.config.Settings;
 
 import static java.util.function.Function.identity;
-import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
+import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
 
 public class ConfigurationProvider extends ProviderAdapter {
 
index c34bdf1863ae4ec98f29383c0bfc987c5bf9b4dd..aafb2941f8e8a78a25d20a0ad18556a2bd302bf5 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.issue.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 2f5b24d0d342d8bdbb64a8907f3aa89cc53aecd3..ed1c40ea8b878db8de753a038f0362ba4b90e1dc 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.measure.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 9e4e4382532c39239fc38bca82d16ea93630a590..97a8b68d1cc18177cb2b5b0f186317c88e36c16f 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.ExtensionProvider;
 import org.sonar.api.Plugin;
 import org.sonar.api.SonarRuntime;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.context.PluginContextImpl;
+import org.sonar.api.internal.PluginContextImpl;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginInfo;
index 81fba7331d3357979e0598170afde123e688c3ed..f1cf0f9ab5999d661a6c68f904a07ac2319a3e53 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.rule.index;
 import com.google.common.collect.ImmutableSet;
 import java.util.Set;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 63b91d0f8bb8e266c9fd6b6d391e03bfa3d8a689..60ff20dca26c2c4167a4ff901e2168d6740808ea 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Map;
 import java.util.Optional;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.ConfigurationBridge;
+import org.sonar.api.config.internal.ConfigurationBridge;
 
 import static java.util.Objects.requireNonNull;
 
index 4e88707992a2971cb1d6f26421849d01498f82a0..a887b55ffdc7286db08577f2818acfe47349a11e 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.user.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index f4ddef479ef9d12c01b9d92758d1baba04b5da15..2abc9030b7b662a97561b1373c82433cc844a410 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.view.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 83691ad734979fd196bf52bd288be44be0da0748..3d09555029ec4cf8886defdc59fb6091ae64dacc 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.config.PropertyDefinition.builder;
index d0195af76a0e56fca1306333a40bec78db6d0d78..d78d03734a8865b33fc6ae818bca10507486c37b 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 
index 149f67ad33fb1a1ef2b41ffc3e2facd75fb75da6..ed7adadab3e1d7e19b0a79b0141590967f647a86 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.newindex.SettingsConfiguration;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
index 705b8054bb24854960e1fc4fb8a8e2119e8aa014..c746a57f812e09f3052a92ab798a66272375ddd4 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Set;
 import java.util.function.Consumer;
 import org.junit.Test;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.IndexType.IndexMainType;
 import org.sonar.server.es.newindex.SettingsConfiguration;
 import org.sonar.server.es.newindex.TestNewIndex;
index 542a89545b769cc842b354cb7debe34ff62f1f01..a86914e28f98fe5a299e61796e9f9c2699819e2f 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.server.es.metadata;
 
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.IndexDefinition;
 
 class MetadataIndexDefinitionBridge implements IndexDefinition {
index e6a8fb116317990b75fbc317ca5db4ca5b508f08..d6dfd760540492b8a406bd0e298e593fb0347ac0 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.es.newindex;
 
 import org.elasticsearch.cluster.metadata.IndexMetaData;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.FakeDoc;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
index 90170c90d6d798cafcbde435087b69d7efe6b9f2..4628a01025fea1a827fa17b0f606c16c95878491 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Map;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexType;
 
index 8f5f29e4b5209259b78152e731de0c1a1435b9e8..1e4266be70d591208f182810b18584300339c02f 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexType;
 import org.sonar.server.es.IndexType.IndexMainType;
index b63225dceca0b81f9caac60ff77f5dfb8522e1b3..928943090052ead7985a08b8254ba8080903f3b7 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexType;
 
index 5d253e97247b92646457adfd06bc3779f3864b7c..43bd47022fb828a21155267eb9cc34acd8c48106 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.issue.index;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 07bc93ec941717502ecc90502ff74de608b64c00..ec1fc186f3963e6c373d25a019d15dc48e332d8a 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.config.EmailSettings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.platform.Server;
 import org.sonar.server.l18n.I18nRule;
index 1aa43d4f3d98bb69018606d13918b38ba7876435..df611026d05e220febc7c45af69f05daa9c1f5d3 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.config.EmailSettings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.platform.Server;
 import org.sonar.server.l18n.I18nRule;
index e08a3991f7beda1c814fe4f0732b9500b099156c..f96745ffc27e120ec4bdcffcd52a1e0c4eb228ce 100644 (file)
@@ -31,7 +31,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.db.Database;
index b3fed77da5e01d1960831f432784445bd316360c..050fc56cbac94d6c0aac5e905869e5054575872c 100644 (file)
@@ -22,8 +22,8 @@ package org.sonar.server.platform;
 import java.util.Optional;
 import org.junit.Before;
 import org.junit.Test;
-import org.sonar.api.impl.config.ConfigurationBridge;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.ConfigurationBridge;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.platform.db.migration.step.MigrationSteps;
 import org.sonar.server.platform.db.migration.version.DatabaseVersion;
 
index c0fc2330255af06aef3cd680f5ac7036e268454d..1c9797aad40d85a2b6c85bc4a21410e3fe35b69b 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.Version;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 27fd0c40f5dd17b92a50a359dd27469b94fdf143..558b000baa844c3f254fac257e89ba202106e73d 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.CoreProperties;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
 import org.sonar.db.DbTester;
index e3758bb181faa80500b6720c792c8f9c51750ebf..cb4f0c3dbb1b3e8cdbc7946ff0700c24364d84c6 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.config.CorePropertyDefinitions;
 
 import static org.assertj.core.api.Assertions.assertThat;
index da41c4238be8f0428f36501931de206b2f93cab4..ae97dd927d3e3e639beaa48b275576563403f271 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.platform;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 8192345a929c220a31424a290569eff590343d42..fd7aac44d4d5cc3ff4be2c7359d72d6d015b3cd1 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.platform.serverid;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 782480eade47bc91adb06e815f83c640586f8411..81bd2172c7477085036fbe5e6b1879fdd42e3666 100644 (file)
@@ -25,7 +25,7 @@ import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
index e3fa70e6f9e909e4f7c42ceea3cce5dfa70563c8..19c783336aec24af2986792e6ed3f8c74e646ebe 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.assertj.core.api.Assertions.assertThat;
index cac317cb0740cce41facb951b2d956917d9780ab..4e7e8fedc093d5faea5afc32737b4daf495b5308 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.user.index;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index b495b63b4e7abc3588fc40a62cb39d4724776a89..e78b267f0ddf6ab6e430c8bba37c6a9d488d288c 100644 (file)
@@ -33,8 +33,8 @@ import org.junit.Test;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
 
 import static org.assertj.core.api.Assertions.assertThat;
index fece8070b3ce92a7ed85464d42f6a768fa314144..e18c49b422f3dba5b960e46b64f86ff66682c023 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.view.index;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 4ad418c9d4a953c5a21bbc0647f0353a74f7d283..d23dfa06e690c9e3c307bf316911666750e6dc92 100644 (file)
@@ -32,8 +32,8 @@ import org.junit.rules.Timeout;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
index cbbf90342101a2f19f7a563d5036909a8c6cd820..184fd922bc39d28f07323915c7f143b2c88acc12 100644 (file)
@@ -25,8 +25,8 @@ import javax.annotation.Nullable;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarQubeVersion;
-import org.sonar.api.impl.context.MetadataLoader;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.MetadataLoader;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
 import org.sonar.server.util.TempFolderCleaner;
index b503863846b3b887b1eef11d4cd6eba3b567869c..80da97d352f8352f0328a8772115ffefbf546de0 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.rule;
 
 import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 import org.sonar.server.plugins.ServerPluginRepository;
 
 /**
@@ -51,7 +51,7 @@ public class RuleDefinitionsLoader {
   }
 
   public RulesDefinition.Context load() {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     for (RulesDefinition pluginDefinition : pluginDefs) {
       context.setCurrentPluginKey(serverPluginRepository.getPluginKey(pluginDefinition));
       pluginDefinition.define(context);
index 2ad32ba933373bab062b669e532c4fceb7a6d2c8..de5f24347fc483782a73ce1b2fa27a03f69701f5 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.process.sharedmemoryfile.DefaultProcessCommands;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 290e5309433de9353e6660f7f43c81484f231caf..ee90eb0d0940b919d8e3ad86f04fb841f6cf6f13 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.security.Authenticator;
 import org.sonar.api.security.ExternalGroupsProvider;
 import org.sonar.api.security.ExternalUsersProvider;
index 05fe52566e329a08afd96886d2923c94e6980277..4e4809a0d83942371634e35d54a5da11b55aabdb 100644 (file)
@@ -31,7 +31,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.stream.MoreCollectors;
index f7b68650c27fce2e43605e3303966f3481a3f14e..ed1f5c220844fc7e3bce54265f1e81cc20fae999 100644 (file)
@@ -33,7 +33,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
index e4ae8ff6bcf0bbf8ab6050acc2c205f1027c5f21..08aae1e567e24347f355ace18f7dd7ac31f10dd0 100644 (file)
@@ -32,7 +32,7 @@ import javax.crypto.spec.SecretKeySpec;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
index 3a633f733bc987c95bd391a53bdfb5280b320f6d..744b96cd8c7e8936d27d392c63a19b094525ad85 100644 (file)
@@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableSet;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
index d81029a2c54640265a2a644ac913230398492407..ca56cf07ce77fce8c19b25a05822db55a77ec127 100644 (file)
@@ -24,7 +24,7 @@ import java.util.stream.Collectors;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.server.authentication.UserIdentity;
 import org.sonar.api.utils.System2;
index 14dc0e5fa118e458c8816f1c0852873015edad5c..cac1b7ceaf7b08517bf1b47fa317d9cc7750d106 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.authentication.BaseIdentityProvider;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
index cc6376e9a3a5e0786e512cd790f1120b310a0219..649818cbc643cfd513e6af1c9874af280bf8dc45 100644 (file)
@@ -27,7 +27,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.junit.Before;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.authentication.BasicAuthentication;
 import org.sonar.server.authentication.JwtHttpHandler;
 import org.sonar.server.authentication.event.AuthenticationException;
index fbfc5ccabf79ca8d6c42acb91d8cea63391faf3a..59ddc6217ab9181e06a79baf04b2c97b771d2874 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.server.ws.WebService;
index 924462809fd4488b2c3e72d56637fa1a79a7a84d..d189746349364fccac815d4701af1896b6cc77f4 100644 (file)
@@ -27,7 +27,7 @@ import java.util.Locale;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
index 5706c2699fa9aee0d5bcd5d4f319deb99f9279cc..d34710a619e8dc4adad32116f78c7c83dd387b70 100644 (file)
@@ -24,7 +24,7 @@ import org.apache.commons.io.IOUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.Metric;
 import org.sonar.db.DbTester;
 import org.sonar.server.tester.UserSessionRule;
index 480ac6fc207dfd78ca21a26dd685f3f0cc8c5a32..c357b96495c72cfe66ce43e2e899e31225690b86 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.batch;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
 import org.sonar.api.web.UserRole;
index 227bf05fd8ae0e4cb5b8062bffd4289b7e31b008..c53cf871bf4c54ab1a71a8401ae1e349bbfd5b33 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.process.sharedmemoryfile.DefaultProcessCommands;
 import org.sonar.process.ProcessEntryPoint;
index 319683819e606000a27c962114342e1ad88a7acc..b2b26d951a7595620ee023273a41ef083daabcd7 100644 (file)
@@ -33,7 +33,7 @@ import org.elasticsearch.common.settings.Settings;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.server.es.IndexType.IndexMainType;
index 515056beb856a7c3b3bee84584ad7c44422022ed..de10b8e190502708d82b53fd30038339d5038525 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mockito;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.metadata.MetadataIndex;
 import org.sonar.server.es.metadata.MetadataIndexImpl;
 import org.sonar.server.es.newindex.FakeIndexDefinition;
index 8394828fffe924a2591b5ff5609e2df60401d25d..4f6633793b6cfb3cf82a3efa0e05032d733f39cc 100644 (file)
@@ -27,7 +27,7 @@ import org.elasticsearch.cluster.metadata.MappingMetaData;
 import org.elasticsearch.common.collect.ImmutableOpenMap;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.server.platform.db.migration.es.MigrationEsClient;
index 9c898e9611e0770902c54daa0d3d1f669156261e..8f9bf8b324f025b3d3f676353fbf2f489a0eeaf0 100644 (file)
@@ -35,7 +35,7 @@ import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
index c0a61c8f573c98044cd3fda380f61d36203c3a3c..4e278877baddf670238c61054dbe436554039756 100644 (file)
@@ -26,7 +26,7 @@ import java.util.Random;
 import java.util.stream.Collectors;
 import org.junit.Test;
 import org.picocontainer.ComponentAdapter;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.System2;
 import org.sonar.core.platform.ComponentContainer;
index 015d5f62db732fd2ef5c8e46f52987ca8fef0eea..72366851eb6700c773d42867b7c909d57686a688 100644 (file)
@@ -26,7 +26,7 @@ import java.util.stream.IntStream;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.process.NetworkUtils;
 import org.sonar.process.cluster.health.NodeDetails;
index 6f97d04f0e3f32b02a70adf8d05b15ca1ebdce44..9a4bacc317dad51d753392ae741ec5599f620a59 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Date;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.rule.RuleKey;
index 1d5abf53edce643c9b53acdf54180c158c9c9c63..1d5d65750a9892802ecd4813bd519e3d2a4ed46d 100644 (file)
@@ -26,7 +26,7 @@ import java.util.stream.IntStream;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.ws.WebService;
index d1287a495f392f911c3d8032315207e6c3c8fd8f..07ded448839da1cdbf79ba706c37b489b8db07dd 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rules.RuleType;
index a12c5715697232c00a56c57757d8a54b70ab95ef..b029c512d7e166cc5ba3b44a77afb90d7e6029d0 100644 (file)
@@ -26,7 +26,7 @@ import java.util.Arrays;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.Durations;
index 1dc8030a2941164a940966fa9bb045ddcfc3cf77..df8fff10315e381988777fa66d038e4debed0de9 100644 (file)
@@ -35,7 +35,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.resources.Qualifiers;
index 7d7fb37fc96fa96d3be6fcc7a5faf6824612b1ca..8a24e6b092c50b5837ce0e9605da642abfc780fd 100644 (file)
@@ -26,7 +26,7 @@ import org.mockito.InOrder;
 import org.mockito.Mockito;
 import org.mockito.verification.Timeout;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.notifications.Notification;
 
 import static java.util.Collections.singleton;
index 7e343ea2f28581116d12c17e0deb77c7a13acb53..9476a84c9832832ec8acee71d04cffc3db8568a7 100644 (file)
@@ -24,7 +24,7 @@ import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.sonar.api.config.PropertyDefinitions;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.notifications.NotificationChannel;
 import org.sonar.db.DbClient;
index 89f6bc086f40b5ad4891812b0334d8f1eb2e31f0..a6354115e838d649e5cdf799d1e79195f66ebbd5 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.notification.ws;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.notifications.NotificationChannel;
 import org.sonar.server.issue.notification.FPOrWontFixNotificationHandler;
 import org.sonar.server.issue.notification.MyNewIssuesNotificationHandler;
index 58474092b700a41164e0405248643684876cbdad..2bcfb03b97305ff05ee58d3391dd63419e89dfa3 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.server.organization;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Consumer;
@@ -27,13 +26,11 @@ import org.apache.commons.lang.RandomStringUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.utils.System2;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.config.CorePropertyDefinitions;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.util.SequenceUuidFactory;
 import org.sonar.core.util.UuidFactory;
@@ -44,7 +41,6 @@ import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.db.organization.DefaultTemplates;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.organization.OrganizationDto.Subscription;
-import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto;
 import org.sonar.db.permission.template.PermissionTemplateDto;
 import org.sonar.db.permission.template.PermissionTemplateGroupDto;
 import org.sonar.db.qualitygate.QualityGateDto;
index 760a904b9befb3bdcc8b53f4c06fa5093e0de86b..3d7c766ede85c329e4d6a694da0385b281ab8ade 100644 (file)
@@ -26,7 +26,7 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.WebService;
index 9946f312fd4e4666c487dcc5871945d5f3464c1e..ce3eaed91602612a88fdbd381343f616a575b6b4 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.organization.ws;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 71ad3c3bb9386fa18ef981620d3da65bcdbf8690..2dfe93c4c29aad4bd59927e7b64ee263ce212a62 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.server.permission.index;
 
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index ce8e98ccb7e700b46147c4a16dbbf7e98ab20a92..3de7281760b69e6dd7f3061146bce46335ee08ee 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Optional;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
index 04cab75b3846f4520157e3a1814e979f2d86e1e1..812b3d9254b8bd4681bcd7858a5e2465ec2c90b4 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.platform;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
 
index 3d149ac81b4209119498549ef613fbe58bc603b7..7e30958d5397f7004702f5ed54ab2cd050dd365f 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.platform.db;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
 
 import static org.mockito.Mockito.mock;
index 3f3520c48935482428348d5ae8e3ae47f834551d..5672b7b60cf86b42aa30a59ab94f304fcea7a308 100644 (file)
@@ -31,7 +31,7 @@ import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.process.NetworkUtilsImpl;
index d1010a5ad2a4c303f856ffe6eec55f385673d587..5860ed73671c9c237ce0792ef5f0d547c4ffbf51 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.PropertyType;
 import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.config.PropertyDefinitions;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
 
 import static org.apache.commons.lang.StringUtils.repeat;
index 1c4495f1a9517a5c5e62d52f6269d251ba1b506d..bc233dab4e9418818e87d172f02a9f1fc9976034 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.platform.monitoring;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.security.SecurityRealm;
 import org.sonar.api.utils.log.LoggerLevel;
index 2f87bef1aadca5e7341aed0ca8dc03fb933934e6..3b06b895c331ee06acb4883c6c948659434a306f 100644 (file)
@@ -27,7 +27,7 @@ import javax.annotation.Nullable;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.picocontainer.ComponentAdapter;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.server.platform.WebServer;
 
index adffc0b91a234ef0155d6abf013b2c16c658d07e..f12c7461f1e063d69b1cb4fce0cb725bda88a855 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.platform.monitoring.cluster;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.security.SecurityRealm;
 import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
index 9e3d15d6c71d6e535f91fea066db2597b86a19ce..9fdb245d475241e5a87d11b6d759d478896c6aa9 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.platform.monitoring.cluster;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
 import org.sonar.server.platform.OfficialDistribution;
index a256be06728eb5acb4af2f9124892098a15ef7cb..3756ca14b5841eef36bf17764bb0f9a282ea64e2 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ServerId;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.core.util.Uuids;
index 22a4550d8d5e16177b03d129038332d9a2d199f3..0875ad0fcb242904ff80f24d77ab3da829899bd4 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.SonarQubeSide;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
 import org.sonar.core.platform.ServerId;
index f9bf7d29a92e510537389b83a0ec4b16c72e965d..5551c269c15484026af0bc88fe442de22fd90d1e 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.stubbing.Answer;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.server.platform.OfficialDistribution;
 import org.sonar.server.platform.Platform;
 
index d07cb6a34c8816418d79a9fbfee121ed6ce0b5b4..5f52cee93c1d30cdccc81772ddae95378a8d84d5 100644 (file)
@@ -27,7 +27,7 @@ import javax.annotation.Nullable;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.picocontainer.ComponentAdapter;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.server.platform.WebServer;
 
index cfd4360fcfdc170aaf9ae10367818b4bbe1f192e..bc353f997781dac11726f29c7255af2737ada7f9 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.PluginInfo;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 6bd1c7dba916c069b71fe05e6967839b744f2db7..b1e50cba77c11753033bbc2439869d33a1c7109a 100644 (file)
@@ -24,7 +24,7 @@ import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
 import org.junit.Before;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.SonarException;
 import org.sonar.api.utils.UriReader;
 import org.sonar.process.ProcessProperties;
index 4b558c8ce925c7fa7d1fd1211d38f7907be92ed8..383177f51c8ed6da18a2b4ed5fd6dc62cf848942 100644 (file)
@@ -20,8 +20,8 @@
 package org.sonar.server.project.ws;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.ConfigurationBridge;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.ConfigurationBridge;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.process.ProcessProperties;
 
index 76d1c9facf625f4aaac356cddcde50bbb3c8d5fe..ba56ae7b267a55c0c89ae0e164d042a873d045e9 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.utils.System2;
index d87e2b3fc72c8516d07f1a90d39eda18566cab58..d796ff9e6fdf809f394964e07602da749a87ac76 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Random;
 import org.assertj.core.groups.Tuple;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
index 2f55c987a57b18b910c33afa7f55965efe27b398..ca338616a5dc8affa7452099287d6517dc3fc380 100644 (file)
@@ -36,7 +36,7 @@ import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.rule.RulesDefinition;
 import org.sonar.api.utils.ValidationMessages;
 import org.sonar.core.i18n.RuleI18nManager;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 import org.sonar.server.debt.DebtModelPluginRepository;
 import org.sonar.server.debt.DebtModelXMLExporter;
 import org.sonar.server.debt.DebtRulesXMLImporter;
@@ -100,7 +100,7 @@ public class DeprecatedRulesDefinitionLoaderTest {
 
   @Test
   public void wrap_deprecated_rule_repositories() {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     CheckstyleRules checkstyleRules = new CheckstyleRules();
     when(pluginRepository.getPluginKey(checkstyleRules)).thenReturn("unittest");
     new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, pluginRepository, new RuleRepository[] {checkstyleRules}).complete(context);
@@ -133,7 +133,7 @@ public class DeprecatedRulesDefinitionLoaderTest {
 
   @Test
   public void emulate_the_day_deprecated_api_can_be_dropped() {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
 
     // no more RuleRepository !
     new DeprecatedRulesDefinitionLoader(i18n, debtModelRepository, importer, pluginRepository);
@@ -143,7 +143,7 @@ public class DeprecatedRulesDefinitionLoaderTest {
 
   @Test
   public void use_l10n_bundles() {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     when(i18n.getName("checkstyle", "ConstantName")).thenReturn("Constant Name");
     when(i18n.getDescription("checkstyle", "ConstantName")).thenReturn("Checks that constant names conform to the specified format");
     when(i18n.getParamDescription("checkstyle", "ConstantName", "format")).thenReturn("Regular expression");
@@ -163,7 +163,7 @@ public class DeprecatedRulesDefinitionLoaderTest {
 
   @Test
   public void define_rule_debt() {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
 
     List<DebtModelXMLExporter.RuleDebt> ruleDebts = newArrayList(
       new DebtModelXMLExporter.RuleDebt()
@@ -193,7 +193,7 @@ public class DeprecatedRulesDefinitionLoaderTest {
 
   @Test
   public void fail_on_invalid_rule_debt() {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
 
     List<DebtModelXMLExporter.RuleDebt> ruleDebts = newArrayList(
       new DebtModelXMLExporter.RuleDebt()
index d80649148196187b9f47db54a31a702b30b647f2..09e05a689e67f04d499d956c71e6d84eaa7943a5 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.config.Encryption;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.tester.UserSessionRule;
index 230264e218cd698de867ec172d1e023485933fa7..59acdbde22f1701ec0af6510a6a3ce326f6ce912 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.config.Encryption;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
index 56930de11542e2c78f06de5eac631c3f7f7f3eb3..b673bcdfaa6d310a661411419f59542fcd00f174 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.config.Encryption;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.tester.UserSessionRule;
index 07b05d46f3e4ff72979ec92caa848cade2b61d01..bd778c40aed476d4183c4d5b2b3426c5c46dea17 100644 (file)
@@ -32,7 +32,7 @@ import org.sonar.api.config.Configuration;
 import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.config.PropertyDefinitions;
 import org.sonar.api.config.PropertyFieldDefinition;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
index f3266fade4ecb131aedef651b925af2a9bb4911e..60944a2a608079d082908a1756e291815b1200ad 100644 (file)
@@ -26,7 +26,7 @@ import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
index 9dc9c21665109ca57ee97cd8d60dba2755b68830..60fdc81e5d6364b181596db8b7a49cea8040797b 100644 (file)
@@ -26,7 +26,7 @@ import okhttp3.Request;
 import okio.Buffer;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
index 197b196328fb1225c9a6cb16500e91e25abec963..188c77f98af98d415b290d0fcf4405b8e7210fa0 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
index c55f40f90b69b1b877ac122106dffba5fc0877da..1a20d2e87feae81588a34946e9e5bdd72e38dd3c 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.ui.ws;
 import java.util.Optional;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypeTree;
index cb92f591fdc7aab57466400f65528121ae403741..03d177395e286fd0664af3a79d775f418ed161f9 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.ui.ws;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.web.page.Page;
 import org.sonar.api.web.page.PageDefinition;
 import org.sonar.core.platform.PluginInfo;
index 9abfeb01669c27f7b4603c7cc4003343346f70d3..d680692abd6aacc2b367eee64f028a7632c1b510 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.user;
 
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.security.LoginPasswordAuthenticator;
 import org.sonar.api.security.SecurityRealm;
 import org.sonar.api.utils.SonarException;
index 8b86153904bff0de7079e124184661a7f056c6b9..352070eacf32afb021a51d0b6c2e78ef13c46a99 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.user;
 import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.server.ws.TestRequest;
index 2b111c3a9e0e60af25cf5206dcf5d94cbd6a4733..2a66852ab752a0130cc8b938960feb301fb8a2b6 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.platform.NewUserHandler;
 import org.sonar.api.utils.System2;
index 7bf516e79c5848c5a733da5ff396d972b26881db..1c7c15f0eccea1cc3d23ac6412bf8b86bd8ab366 100644 (file)
@@ -23,7 +23,7 @@ import com.google.common.collect.Multimap;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
index f10ac9b212d3a78381004ea09dc900082cf7b4b6..e718e8eef1cdcef55b42ffae29a6480f2185b044 100644 (file)
@@ -25,7 +25,7 @@ import org.elasticsearch.search.SearchHit;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
index 0c5915c47f7fd1f885e5e299dcc277e32aff5c18..56315f7dc6feacfe33215e8c6c0c8d1524174cdc 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
index c8a60f681d88f7872a5d7b75a531aed0ade2848b..5b9377ac7bd78104ea73805ec167befadea97eb3 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
index cd3bb4523da0d8adcfa8b6ed0317153c7425ad83..38de2bb71af86d16e8182feda78326e746620747 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.user.ws;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypeTree;
index b1d23d8eee5afb458251e57fd544a827e830e878..81f5649177a5bf8e9527de450fc2c959f8ffe1d7 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Collections;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypeTree;
@@ -33,7 +33,6 @@ import org.sonar.api.utils.System2;
 import org.sonar.core.platform.PluginRepository;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.issue.ws.AvatarResolverImpl;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
index 498bf6adedb92779e1025161fba2c02f02b1f1ab..1da5327451a329643ebe14b464afcf05e9913b81 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.user.ws;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.db.DbTester;
 import org.sonar.server.organization.TestOrganizationFlags;
 
index 40bcb63f881767feeb59ea6a2e95f1640d985808..8901a4c7dd518af87e740bb4dd04a54e17361a8a 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
index b5696869de237fa95cc2686ece8360ae6959d735..12445f7a341d2082f36eb3a00717ad91c1890372 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.user.ws;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.System2;
index 50ce373b5920d5813528dfd1dcfaf1a1457e45d6..1fbd80a8f78db77fb05cc742101d391e7f5f6fd2 100644 (file)
@@ -20,8 +20,8 @@
 package org.sonar.server.user.ws;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.ConfigurationBridge;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.ConfigurationBridge;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.process.ProcessProperties;
 
index c3e7f7e1596027a642a4e576eeca20784a233f1d..1e58673735d008679d5179c41fafb91fdbe47553 100644 (file)
@@ -32,7 +32,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
index b547f2cd76cf61afdd456f0ddc79c6075af97b67..c37aff811d4a245f511b8265df21d34656dae562 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.application;
 
 import java.io.IOException;
 import org.sonar.api.SonarEdition;
-import org.sonar.api.impl.context.MetadataLoader;
+import org.sonar.api.internal.MetadataLoader;
 import org.sonar.application.command.CommandFactory;
 import org.sonar.application.command.CommandFactoryImpl;
 import org.sonar.application.command.JavaVersion;
index bd93edf4cca209ee39c98b434780da04c61c01f0..58bb7ca5b6451bc7a0350c6b98129541217ac867 100644 (file)
@@ -29,7 +29,7 @@ import java.util.function.Predicate;
 import org.sonar.api.ExtensionProvider;
 import org.sonar.api.SonarRuntime;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
index c8f5baa5bcc06100948f553465c8663a6d3526d7..663d56b58676b80cbde1e49e02533d0ccb231896 100644 (file)
@@ -46,7 +46,7 @@ import org.sonar.api.SonarRuntime;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 8944bfbf181729ba4e5b6512258fdd99787715cd..9ca8301ad29b43d49ff932b2366a6ff19fcbf317 100644 (file)
@@ -52,7 +52,7 @@ import org.simpleframework.http.Response;
 import org.simpleframework.http.core.Container;
 import org.simpleframework.transport.connect.SocketConnection;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.SonarException;
 
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/AbstractProjectOrModule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/AbstractProjectOrModule.java
new file mode 100644 (file)
index 0000000..2f45fb0
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.concurrent.Immutable;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.SystemUtils;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+@Immutable
+public abstract class AbstractProjectOrModule extends DefaultInputComponent {
+  private static final Logger LOGGER = Loggers.get(AbstractProjectOrModule.class);
+  private final Path baseDir;
+  private final Path workDir;
+  private final String name;
+  private final String originalName;
+  private final String description;
+  private final String keyWithBranch;
+  private final String branch;
+  private final Map<String, String> properties;
+
+  private final String key;
+  private final ProjectDefinition definition;
+  private final Charset encoding;
+
+  public AbstractProjectOrModule(ProjectDefinition definition, int scannerComponentId) {
+    super(scannerComponentId);
+    this.baseDir = initBaseDir(definition);
+    this.workDir = initWorkingDir(definition);
+    this.name = definition.getName();
+    this.originalName = definition.getOriginalName();
+    this.description = definition.getDescription();
+    this.keyWithBranch = definition.getKeyWithBranch();
+    this.branch = definition.getBranch();
+    this.properties = Collections.unmodifiableMap(new HashMap<>(definition.properties()));
+
+    this.definition = definition;
+    this.key = definition.getKey();
+    this.encoding = initEncoding(definition);
+  }
+
+  private static Charset initEncoding(ProjectDefinition module) {
+    String encodingStr = module.properties().get(CoreProperties.ENCODING_PROPERTY);
+    Charset result;
+    if (StringUtils.isNotEmpty(encodingStr)) {
+      result = Charset.forName(StringUtils.trim(encodingStr));
+    } else {
+      result = Charset.defaultCharset();
+    }
+    return result;
+  }
+
+  private static Path initBaseDir(ProjectDefinition module) {
+    Path result;
+    try {
+      result = module.getBaseDir().toPath().toRealPath(LinkOption.NOFOLLOW_LINKS);
+    } catch (IOException e) {
+      throw new IllegalStateException("Unable to resolve module baseDir", e);
+    }
+    return result;
+  }
+
+  private static Path initWorkingDir(ProjectDefinition module) {
+    File workingDirAsFile = module.getWorkDir();
+    Path workingDir = workingDirAsFile.getAbsoluteFile().toPath().normalize();
+    if (SystemUtils.IS_OS_WINDOWS) {
+      try {
+        Files.createDirectories(workingDir);
+        Files.setAttribute(workingDir, "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
+      } catch (IOException e) {
+        LOGGER.warn("Failed to set working directory hidden: {}", e.getMessage());
+      }
+    }
+    return workingDir;
+  }
+
+  /**
+   * Module key without branch
+   */
+  @Override
+  public String key() {
+    return key;
+  }
+
+  @Override
+  public boolean isFile() {
+    return false;
+  }
+
+  public ProjectDefinition definition() {
+    return definition;
+  }
+
+  public Path getBaseDir() {
+    return baseDir;
+  }
+
+  public Path getWorkDir() {
+    return workDir;
+  }
+
+  public String getKeyWithBranch() {
+    return keyWithBranch;
+  }
+
+  @CheckForNull
+  public String getBranch() {
+    return branch;
+  }
+
+  public Map<String, String> properties() {
+    return properties;
+  }
+
+  @CheckForNull
+  public String getOriginalName() {
+    return originalName;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public Charset getEncoding() {
+    return encoding;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
new file mode 100644 (file)
index 0000000..94dfc99
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.stream.StreamSupport;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.predicates.DefaultFilePredicates;
+import org.sonar.api.batch.fs.internal.predicates.FileExtensionPredicate;
+import org.sonar.api.batch.fs.internal.predicates.OptimizedFilePredicateAdapter;
+import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * @since 4.2
+ */
+public class DefaultFileSystem implements FileSystem {
+
+  private final Cache cache;
+  private final FilePredicates predicates;
+  private final Path baseDir;
+  private Path workDir;
+  private Charset encoding;
+
+  /**
+   * Only for testing
+   */
+  public DefaultFileSystem(Path baseDir) {
+    this(baseDir, new MapCache(), new DefaultFilePredicates(baseDir));
+  }
+
+  /**
+   * Only for testing
+   */
+  public DefaultFileSystem(File baseDir) {
+    this(baseDir.toPath(), new MapCache(), new DefaultFilePredicates(baseDir.toPath()));
+  }
+
+  protected DefaultFileSystem(Path baseDir, Cache cache, FilePredicates filePredicates) {
+    this.baseDir = baseDir;
+    this.cache = cache;
+    this.predicates = filePredicates;
+  }
+
+  public Path baseDirPath() {
+    return baseDir;
+  }
+
+  @Override
+  public File baseDir() {
+    return baseDir.toFile();
+  }
+
+  public DefaultFileSystem setEncoding(Charset e) {
+    this.encoding = e;
+    return this;
+  }
+
+  @Override
+  public Charset encoding() {
+    return encoding;
+  }
+
+  public DefaultFileSystem setWorkDir(Path d) {
+    this.workDir = d;
+    return this;
+  }
+
+  @Override
+  public File workDir() {
+    return workDir.toFile();
+  }
+
+  @Override
+  public InputFile inputFile(FilePredicate predicate) {
+    Iterable<InputFile> files = inputFiles(predicate);
+    Iterator<InputFile> iterator = files.iterator();
+    if (!iterator.hasNext()) {
+      return null;
+    }
+    InputFile first = iterator.next();
+    if (!iterator.hasNext()) {
+      return first;
+    }
+
+    StringBuilder sb = new StringBuilder();
+    sb.append("expected one element but was: <" + first);
+    for (int i = 0; i < 4 && iterator.hasNext(); i++) {
+      sb.append(", " + iterator.next());
+    }
+    if (iterator.hasNext()) {
+      sb.append(", ...");
+    }
+    sb.append('>');
+
+    throw new IllegalArgumentException(sb.toString());
+
+  }
+
+  public Iterable<InputFile> inputFiles() {
+    return inputFiles(predicates.all());
+  }
+
+  @Override
+  public Iterable<InputFile> inputFiles(FilePredicate predicate) {
+    return OptimizedFilePredicateAdapter.create(predicate).get(cache);
+  }
+
+  @Override
+  public boolean hasFiles(FilePredicate predicate) {
+    return inputFiles(predicate).iterator().hasNext();
+  }
+
+  @Override
+  public Iterable<File> files(FilePredicate predicate) {
+    return () -> StreamSupport.stream(inputFiles(predicate).spliterator(), false)
+      .map(InputFile::file)
+      .iterator();
+  }
+
+  @Override
+  public InputDir inputDir(File dir) {
+    String relativePath = PathUtils.sanitize(new PathResolver().relativePath(baseDir.toFile(), dir));
+    if (relativePath == null) {
+      return null;
+    }
+    // Issues on InputDir are moved to the project, so we just return a fake InputDir for backward compatibility
+    return new DefaultInputDir("unused", relativePath).setModuleBaseDir(baseDir);
+  }
+
+  public DefaultFileSystem add(InputFile inputFile) {
+    cache.add(inputFile);
+    return this;
+  }
+
+  @Override
+  public SortedSet<String> languages() {
+    return cache.languages();
+  }
+
+  @Override
+  public FilePredicates predicates() {
+    return predicates;
+  }
+
+  public abstract static class Cache implements Index {
+
+    protected abstract void doAdd(InputFile inputFile);
+
+    final void add(InputFile inputFile) {
+      doAdd(inputFile);
+    }
+
+    protected abstract SortedSet<String> languages();
+  }
+
+  /**
+   * Used only for testing
+   */
+  private static class MapCache extends Cache {
+    private final Map<String, InputFile> fileMap = new HashMap<>();
+    private final Map<String, Set<InputFile>> filesByNameCache = new HashMap<>();
+    private final Map<String, Set<InputFile>> filesByExtensionCache = new HashMap<>();
+    private SortedSet<String> languages = new TreeSet<>();
+
+    @Override
+    public Iterable<InputFile> inputFiles() {
+      return new ArrayList<>(fileMap.values());
+    }
+
+    @Override
+    public InputFile inputFile(String relativePath) {
+      return fileMap.get(relativePath);
+    }
+
+    @Override
+    public Iterable<InputFile> getFilesByName(String filename) {
+      return filesByNameCache.get(filename);
+    }
+
+    @Override
+    public Iterable<InputFile> getFilesByExtension(String extension) {
+      return filesByExtensionCache.get(extension);
+    }
+
+    @Override
+    protected void doAdd(InputFile inputFile) {
+      if (inputFile.language() != null) {
+        languages.add(inputFile.language());
+      }
+      fileMap.put(inputFile.relativePath(), inputFile);
+      filesByNameCache.computeIfAbsent(inputFile.filename(), x -> new HashSet<>()).add(inputFile);
+      filesByExtensionCache.computeIfAbsent(FileExtensionPredicate.getExtension(inputFile), x -> new HashSet<>()).add(inputFile);
+    }
+
+    @Override
+    protected SortedSet<String> languages() {
+      return languages;
+    }
+  }
+
+  @Override
+  public File resolvePath(String path) {
+    File file = new File(path);
+    if (!file.isAbsolute()) {
+      try {
+        file = new File(baseDir(), path).getCanonicalFile();
+      } catch (IOException e) {
+        throw new IllegalArgumentException("Unable to resolve path '" + path + "'", e);
+      }
+    }
+    return file;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultIndexedFile.java
new file mode 100644 (file)
index 0000000..229280f
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * @since 6.3
+ */
+@Immutable
+public class DefaultIndexedFile extends DefaultInputComponent implements IndexedFile {
+  private static AtomicInteger intGenerator = new AtomicInteger(0);
+
+  private final String projectRelativePath;
+  private final String moduleRelativePath;
+  private final String projectKey;
+  private final String language;
+  private final Type type;
+  private final Path absolutePath;
+  private final SensorStrategy sensorStrategy;
+
+  /**
+   * Testing purposes only!
+   */
+  public DefaultIndexedFile(String projectKey, Path baseDir, String relativePath, @Nullable String language) {
+    this(baseDir.resolve(relativePath), projectKey, relativePath, relativePath, Type.MAIN, language, intGenerator.getAndIncrement(),
+      new SensorStrategy());
+  }
+
+  public DefaultIndexedFile(Path absolutePath, String projectKey, String projectRelativePath, String moduleRelativePath, Type type, @Nullable String language, int batchId,
+    SensorStrategy sensorStrategy) {
+    super(batchId);
+    this.projectKey = projectKey;
+    this.projectRelativePath = PathUtils.sanitize(projectRelativePath);
+    this.moduleRelativePath = PathUtils.sanitize(moduleRelativePath);
+    this.type = type;
+    this.language = language;
+    this.sensorStrategy = sensorStrategy;
+    this.absolutePath = absolutePath;
+  }
+
+  @Override
+  public String relativePath() {
+    return sensorStrategy.isGlobal() ? projectRelativePath : moduleRelativePath;
+  }
+
+  public String getModuleRelativePath() {
+    return moduleRelativePath;
+  }
+
+  public String getProjectRelativePath() {
+    return projectRelativePath;
+  }
+
+  @Override
+  public String absolutePath() {
+    return PathUtils.sanitize(path().toString());
+  }
+
+  @Override
+  public File file() {
+    return path().toFile();
+  }
+
+  @Override
+  public Path path() {
+    return absolutePath;
+  }
+
+  @Override
+  public InputStream inputStream() throws IOException {
+    return Files.newInputStream(path());
+  }
+
+  @CheckForNull
+  @Override
+  public String language() {
+    return language;
+  }
+
+  @Override
+  public Type type() {
+    return type;
+  }
+
+  /**
+   * Component key (without branch).
+   */
+  @Override
+  public String key() {
+    return new StringBuilder().append(projectKey).append(":").append(projectRelativePath).toString();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (!(o instanceof DefaultIndexedFile)) {
+      return false;
+    }
+
+    DefaultIndexedFile that = (DefaultIndexedFile) o;
+    return projectRelativePath.equals(that.projectRelativePath);
+  }
+
+  @Override
+  public int hashCode() {
+    return projectRelativePath.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return projectRelativePath;
+  }
+
+  @Override
+  public boolean isFile() {
+    return true;
+  }
+
+  @Override
+  public String filename() {
+    return path().getFileName().toString();
+  }
+
+  @Override
+  public URI uri() {
+    return path().toUri();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java
new file mode 100644 (file)
index 0000000..19a5cce
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.measure.Metric;
+
+/**
+ * @since 5.2
+ */
+public abstract class DefaultInputComponent implements InputComponent {
+  private int id;
+  private Set<String> storedMetricKeys = new HashSet<>();
+
+  public DefaultInputComponent(int scannerId) {
+    this.id = scannerId;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || this.getClass() != o.getClass()) {
+      return false;
+    }
+
+    DefaultInputComponent that = (DefaultInputComponent) o;
+    return key().equals(that.key());
+  }
+
+  public int scannerId() {
+    return id;
+  }
+
+  @Override
+  public int hashCode() {
+    return key().hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return "[key=" + key() + "]";
+  }
+
+  public void setHasMeasureFor(Metric metric) {
+    storedMetricKeys.add(metric.key());
+  }
+
+  public boolean hasMeasureFor(Metric metric) {
+    return storedMetricKeys.contains(metric.key());
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java
new file mode 100644 (file)
index 0000000..14a39ee
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.File;
+import java.net.URI;
+import java.nio.file.Path;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * @since 4.5
+ */
+public class DefaultInputDir extends DefaultInputComponent implements InputDir {
+
+  private final String relativePath;
+  private final String moduleKey;
+  private Path moduleBaseDir;
+
+  public DefaultInputDir(String moduleKey, String relativePath) {
+    super(-1);
+    this.moduleKey = moduleKey;
+    this.relativePath = PathUtils.sanitize(relativePath);
+  }
+
+  @Override
+  public String relativePath() {
+    return relativePath;
+  }
+
+  @Override
+  public String absolutePath() {
+    return PathUtils.sanitize(path().toString());
+  }
+
+  @Override
+  public File file() {
+    return path().toFile();
+  }
+
+  @Override
+  public Path path() {
+    if (moduleBaseDir == null) {
+      throw new IllegalStateException("Can not return the java.nio.file.Path because module baseDir is not set (see method setModuleBaseDir(java.io.File))");
+    }
+    return moduleBaseDir.resolve(relativePath);
+  }
+
+  public String moduleKey() {
+    return moduleKey;
+  }
+
+  @Override
+  public String key() {
+    StringBuilder sb = new StringBuilder().append(moduleKey).append(":");
+    if (StringUtils.isEmpty(relativePath)) {
+      sb.append("/");
+    } else {
+      sb.append(relativePath);
+    }
+    return sb.toString();
+  }
+
+  /**
+   * For testing purpose. Will be automatically set when dir is added to {@link DefaultFileSystem}
+   */
+  public DefaultInputDir setModuleBaseDir(Path moduleBaseDir) {
+    this.moduleBaseDir = moduleBaseDir.normalize();
+    return this;
+  }
+
+  @Override
+  public boolean isFile() {
+    return false;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || this.getClass() != o.getClass()) {
+      return false;
+    }
+
+    DefaultInputDir that = (DefaultInputDir) o;
+    return moduleKey.equals(that.moduleKey) && relativePath.equals(that.relativePath);
+  }
+
+  @Override
+  public int hashCode() {
+    return moduleKey.hashCode() + relativePath.hashCode() * 13;
+  }
+
+  @Override
+  public String toString() {
+    return "[moduleKey=" + moduleKey + ", relative=" + relativePath + ", basedir=" + moduleBaseDir + "]";
+  }
+
+  @Override
+  public URI uri() {
+    return path().toUri();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
new file mode 100644 (file)
index 0000000..4a48bf9
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.io.ByteOrderMark;
+import org.apache.commons.io.input.BOMInputStream;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.TextRange;
+
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+/**
+ * @since 4.2
+ * To create {@link InputFile} in tests, use TestInputFileBuilder.
+ */
+public class DefaultInputFile extends DefaultInputComponent implements InputFile {
+
+  private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+  private final DefaultIndexedFile indexedFile;
+  private final String contents;
+  private final Consumer<DefaultInputFile> metadataGenerator;
+
+  private boolean published;
+  private boolean excludedForCoverage;
+  private boolean excludedForDuplication;
+  private boolean ignoreAllIssues;
+  // Lazy init to save memory
+  private BitSet noSonarLines;
+  private Status status;
+  private Charset charset;
+  private Metadata metadata;
+  private Collection<int[]> ignoreIssuesOnlineRanges;
+  private BitSet executableLines;
+
+  public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator) {
+    this(indexedFile, metadataGenerator, null);
+  }
+
+  // For testing
+  public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator, @Nullable String contents) {
+    super(indexedFile.scannerId());
+    this.indexedFile = indexedFile;
+    this.metadataGenerator = metadataGenerator;
+    this.metadata = null;
+    this.published = false;
+    this.excludedForCoverage = false;
+    this.contents = contents;
+  }
+
+  public void checkMetadata() {
+    if (metadata == null) {
+      metadataGenerator.accept(this);
+    }
+  }
+
+  @Override
+  public InputStream inputStream() throws IOException {
+    return contents != null ? new ByteArrayInputStream(contents.getBytes(charset()))
+      : new BOMInputStream(Files.newInputStream(path()),
+      ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
+  }
+
+  @Override
+  public String contents() throws IOException {
+    if (contents != null) {
+      return contents;
+    } else {
+      ByteArrayOutputStream result = new ByteArrayOutputStream();
+      try (InputStream inputStream = inputStream()) {
+        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+        int length;
+        while ((length = inputStream.read(buffer)) != -1) {
+          result.write(buffer, 0, length);
+        }
+      }
+      return result.toString(charset().name());
+    }
+  }
+
+  public DefaultInputFile setPublished(boolean published) {
+    this.published = published;
+    return this;
+  }
+
+  public boolean isPublished() {
+    return published;
+  }
+
+  public DefaultInputFile setExcludedForCoverage(boolean excludedForCoverage) {
+    this.excludedForCoverage = excludedForCoverage;
+    return this;
+  }
+
+  public boolean isExcludedForCoverage() {
+    return excludedForCoverage;
+  }
+
+  public DefaultInputFile setExcludedForDuplication(boolean excludedForDuplication) {
+    this.excludedForDuplication = excludedForDuplication;
+    return this;
+  }
+
+  public boolean isExcludedForDuplication() {
+    return excludedForDuplication;
+  }
+
+  /**
+   * @deprecated since 6.6
+   */
+  @Deprecated
+  @Override
+  public String relativePath() {
+    return indexedFile.relativePath();
+  }
+
+  public String getModuleRelativePath() {
+    return indexedFile.getModuleRelativePath();
+  }
+
+  public String getProjectRelativePath() {
+    return indexedFile.getProjectRelativePath();
+  }
+
+  @Override
+  public String absolutePath() {
+    return indexedFile.absolutePath();
+  }
+
+  @Override
+  public File file() {
+    return indexedFile.file();
+  }
+
+  @Override
+  public Path path() {
+    return indexedFile.path();
+  }
+
+  @CheckForNull
+  @Override
+  public String language() {
+    return indexedFile.language();
+  }
+
+  @Override
+  public Type type() {
+    return indexedFile.type();
+  }
+
+  /**
+   * Component key (without branch).
+   */
+  @Override
+  public String key() {
+    return indexedFile.key();
+  }
+
+  @Override
+  public int hashCode() {
+    return indexedFile.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return indexedFile.toString();
+  }
+
+  /**
+   * {@link #setStatus(Status)}
+   */
+  @Override
+  public Status status() {
+    checkMetadata();
+    return status;
+  }
+
+  @Override
+  public int lines() {
+    checkMetadata();
+    return metadata.lines();
+  }
+
+  @Override
+  public boolean isEmpty() {
+    checkMetadata();
+    return metadata.isEmpty();
+  }
+
+  @Override
+  public Charset charset() {
+    checkMetadata();
+    return charset;
+  }
+
+  public int lastValidOffset() {
+    checkMetadata();
+    return metadata.lastValidOffset();
+  }
+
+  /**
+   * Digest hash of the file.
+   */
+  public String hash() {
+    checkMetadata();
+    return metadata.hash();
+  }
+
+  public int nonBlankLines() {
+    checkMetadata();
+    return metadata.nonBlankLines();
+  }
+
+  public int[] originalLineStartOffsets() {
+    checkMetadata();
+    checkState(metadata.originalLineStartOffsets() != null, "InputFile is not properly initialized.");
+    checkState(metadata.originalLineStartOffsets().length == metadata.lines(),
+      "InputFile is not properly initialized. 'originalLineStartOffsets' property length should be equal to 'lines'");
+    return metadata.originalLineStartOffsets();
+  }
+
+  public int[] originalLineEndOffsets() {
+    checkMetadata();
+    checkState(metadata.originalLineEndOffsets() != null, "InputFile is not properly initialized.");
+    checkState(metadata.originalLineEndOffsets().length == metadata.lines(),
+      "InputFile is not properly initialized. 'originalLineEndOffsets' property length should be equal to 'lines'");
+    return metadata.originalLineEndOffsets();
+  }
+
+  @Override
+  public TextPointer newPointer(int line, int lineOffset) {
+    checkMetadata();
+    DefaultTextPointer textPointer = new DefaultTextPointer(line, lineOffset);
+    checkValid(textPointer, "pointer");
+    return textPointer;
+  }
+
+  @Override
+  public TextRange newRange(TextPointer start, TextPointer end) {
+    checkMetadata();
+    checkValid(start, "start pointer");
+    checkValid(end, "end pointer");
+    return newRangeValidPointers(start, end, false);
+  }
+
+  @Override
+  public TextRange newRange(int startLine, int startLineOffset, int endLine, int endLineOffset) {
+    checkMetadata();
+    TextPointer start = newPointer(startLine, startLineOffset);
+    TextPointer end = newPointer(endLine, endLineOffset);
+    return newRangeValidPointers(start, end, false);
+  }
+
+  @Override
+  public TextRange selectLine(int line) {
+    checkMetadata();
+    TextPointer startPointer = newPointer(line, 0);
+    TextPointer endPointer = newPointer(line, lineLength(line));
+    return newRangeValidPointers(startPointer, endPointer, true);
+  }
+
+  public void validate(TextRange range) {
+    checkMetadata();
+    checkValid(range.start(), "start pointer");
+    checkValid(range.end(), "end pointer");
+  }
+
+  /**
+   * Create Range from global offsets. Used for backward compatibility with older API.
+   */
+  public TextRange newRange(int startOffset, int endOffset) {
+    checkMetadata();
+    return newRangeValidPointers(newPointer(startOffset), newPointer(endOffset), false);
+  }
+
+  public TextPointer newPointer(int globalOffset) {
+    checkMetadata();
+    checkArgument(globalOffset >= 0, "%s is not a valid offset for a file", globalOffset);
+    checkArgument(globalOffset <= lastValidOffset(), "%s is not a valid offset for file %s. Max offset is %s", globalOffset, this, lastValidOffset());
+    int line = findLine(globalOffset);
+    int startLineOffset = originalLineStartOffsets()[line - 1];
+    // In case the global offset is between \r and \n, move the pointer to a valid location
+    return new DefaultTextPointer(line, Math.min(globalOffset, originalLineEndOffsets()[line - 1]) - startLineOffset);
+  }
+
+  public DefaultInputFile setStatus(Status status) {
+    this.status = status;
+    return this;
+  }
+
+  public DefaultInputFile setCharset(Charset charset) {
+    this.charset = charset;
+    return this;
+  }
+
+  private void checkValid(TextPointer pointer, String owner) {
+    checkArgument(pointer.line() >= 1, "%s is not a valid line for a file", pointer.line());
+    checkArgument(pointer.line() <= this.metadata.lines(), "%s is not a valid line for %s. File %s has %s line(s)", pointer.line(), owner, this, metadata.lines());
+    checkArgument(pointer.lineOffset() >= 0, "%s is not a valid line offset for a file", pointer.lineOffset());
+    int lineLength = lineLength(pointer.line());
+    checkArgument(pointer.lineOffset() <= lineLength,
+      "%s is not a valid line offset for %s. File %s has %s character(s) at line %s", pointer.lineOffset(), owner, this, lineLength, pointer.line());
+  }
+
+  private int lineLength(int line) {
+    return originalLineEndOffsets()[line - 1] - originalLineStartOffsets()[line - 1];
+  }
+
+  private static TextRange newRangeValidPointers(TextPointer start, TextPointer end, boolean acceptEmptyRange) {
+    checkArgument(acceptEmptyRange ? (start.compareTo(end) <= 0) : (start.compareTo(end) < 0),
+      "Start pointer %s should be before end pointer %s", start, end);
+    return new DefaultTextRange(start, end);
+  }
+
+  private int findLine(int globalOffset) {
+    return Math.abs(Arrays.binarySearch(originalLineStartOffsets(), globalOffset) + 1);
+  }
+
+  public DefaultInputFile setMetadata(Metadata metadata) {
+    this.metadata = metadata;
+    return this;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj == null) {
+      return false;
+    }
+
+    if (this.getClass() != obj.getClass()) {
+      return false;
+    }
+
+    DefaultInputFile that = (DefaultInputFile) obj;
+    return this.getProjectRelativePath().equals(that.getProjectRelativePath());
+  }
+
+  @Override
+  public boolean isFile() {
+    return true;
+  }
+
+  @Override
+  public String filename() {
+    return indexedFile.filename();
+  }
+
+  @Override
+  public URI uri() {
+    return indexedFile.uri();
+  }
+
+  public void noSonarAt(Set<Integer> noSonarLines) {
+    if (this.noSonarLines == null) {
+      this.noSonarLines = new BitSet(lines());
+    }
+    noSonarLines.forEach(l -> this.noSonarLines.set(l - 1));
+  }
+
+  public boolean hasNoSonarAt(int line) {
+    if (this.noSonarLines == null) {
+      return false;
+    }
+    return this.noSonarLines.get(line - 1);
+  }
+
+  public boolean isIgnoreAllIssues() {
+    return ignoreAllIssues;
+  }
+
+  public void setIgnoreAllIssues(boolean ignoreAllIssues) {
+    this.ignoreAllIssues = ignoreAllIssues;
+  }
+
+  public void addIgnoreIssuesOnLineRanges(Collection<int[]> lineRanges) {
+    if (this.ignoreIssuesOnlineRanges == null) {
+      this.ignoreIssuesOnlineRanges = new ArrayList<>();
+    }
+    this.ignoreIssuesOnlineRanges.addAll(lineRanges);
+  }
+
+  public boolean isIgnoreAllIssuesOnLine(@Nullable Integer line) {
+    if (line == null || ignoreIssuesOnlineRanges == null) {
+      return false;
+    }
+    return ignoreIssuesOnlineRanges.stream().anyMatch(r -> r[0] <= line && line <= r[1]);
+  }
+
+  public void setExecutableLines(Set<Integer> executableLines) {
+    checkState(this.executableLines == null, "Executable lines have already been saved for file: {}", this.toString());
+    this.executableLines = new BitSet(lines());
+    executableLines.forEach(l -> this.executableLines.set(l - 1));
+  }
+
+  public Optional<Set<Integer>> getExecutableLines() {
+    if (this.executableLines == null) {
+      return Optional.empty();
+    }
+    return Optional.of(this.executableLines.stream().map(i -> i + 1).boxed().collect(Collectors.toSet()));
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java
new file mode 100644 (file)
index 0000000..73fa8dd
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.CheckForNull;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputModule;
+import org.sonar.api.scan.filesystem.PathResolver;
+
+import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
+
+@Immutable
+public class DefaultInputModule extends AbstractProjectOrModule implements InputModule {
+
+  private final List<Path> sourceDirsOrFiles;
+  private final List<Path> testDirsOrFiles;
+
+  /**
+   * For testing only!
+   */
+  public DefaultInputModule(ProjectDefinition definition) {
+    this(definition, 0);
+  }
+
+  public DefaultInputModule(ProjectDefinition definition, int scannerComponentId) {
+    super(definition, scannerComponentId);
+
+    this.sourceDirsOrFiles = initSources(definition, ProjectDefinition.SOURCES_PROPERTY);
+    this.testDirsOrFiles = initSources(definition, ProjectDefinition.TESTS_PROPERTY);
+  }
+
+  @CheckForNull
+  private List<Path> initSources(ProjectDefinition module, String propertyKey) {
+    if (!module.properties().containsKey(propertyKey)) {
+      return null;
+    }
+    List<Path> result = new ArrayList<>();
+    PathResolver pathResolver = new PathResolver();
+    String srcPropValue = module.properties().get(propertyKey);
+    if (srcPropValue != null) {
+      for (String sourcePath : parseAsCsv(propertyKey, srcPropValue)) {
+        File dirOrFile = pathResolver.relativeFile(getBaseDir().toFile(), sourcePath);
+        if (dirOrFile.exists()) {
+          result.add(dirOrFile.toPath());
+        }
+      }
+    }
+    return result;
+  }
+
+  public Optional<List<Path>> getSourceDirsOrFiles() {
+    return Optional.ofNullable(sourceDirsOrFiles);
+  }
+
+  public Optional<List<Path>> getTestDirsOrFiles() {
+    return Optional.ofNullable(testDirsOrFiles);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputProject.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputProject.java
new file mode 100644 (file)
index 0000000..b6f07c8
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.scanner.fs.InputProject;
+
+@Immutable
+public class DefaultInputProject extends AbstractProjectOrModule implements InputProject {
+
+  /**
+   * For testing only!
+   */
+  public DefaultInputProject(ProjectDefinition definition) {
+    super(definition, 0);
+  }
+
+  public DefaultInputProject(ProjectDefinition definition, int scannerComponentId) {
+    super(definition, scannerComponentId);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextPointer.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextPointer.java
new file mode 100644 (file)
index 0000000..c10efd0
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import org.sonar.api.batch.fs.TextPointer;
+
+/**
+ * @since 5.2
+ */
+public class DefaultTextPointer implements TextPointer {
+
+  private final int line;
+  private final int lineOffset;
+
+  public DefaultTextPointer(int line, int lineOffset) {
+    this.line = line;
+    this.lineOffset = lineOffset;
+  }
+
+  @Override
+  public int line() {
+    return line;
+  }
+
+  @Override
+  public int lineOffset() {
+    return lineOffset;
+  }
+
+  @Override
+  public String toString() {
+    return "[line=" + line + ", lineOffset=" + lineOffset + "]";
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof DefaultTextPointer)) {
+      return false;
+    }
+    DefaultTextPointer other = (DefaultTextPointer) obj;
+    return other.line == this.line && other.lineOffset == this.lineOffset;
+  }
+
+  @Override
+  public int hashCode() {
+    return 37 * this.line + lineOffset;
+  }
+
+  @Override
+  public int compareTo(TextPointer o) {
+    if (this.line == o.line()) {
+      return Integer.compare(this.lineOffset, o.lineOffset());
+    }
+    return Integer.compare(this.line, o.line());
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextRange.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextRange.java
new file mode 100644 (file)
index 0000000..efef79c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.TextRange;
+
+/**
+ * @since 5.2
+ */
+public class DefaultTextRange implements TextRange {
+
+  private final TextPointer start;
+  private final TextPointer end;
+
+  public DefaultTextRange(TextPointer start, TextPointer end) {
+    this.start = start;
+    this.end = end;
+  }
+
+  @Override
+  public TextPointer start() {
+    return start;
+  }
+
+  @Override
+  public TextPointer end() {
+    return end;
+  }
+
+  @Override
+  public boolean overlap(TextRange another) {
+    // [A,B] and [C,D]
+    // B > C && D > A
+    return this.end.compareTo(another.start()) > 0 && another.end().compareTo(this.start) > 0;
+  }
+
+  @Override
+  public String toString() {
+    return "Range[from " + start + " to " + end + "]";
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof DefaultTextRange)) {
+      return false;
+    }
+    DefaultTextRange other = (DefaultTextRange) obj;
+    return start.equals(other.start) && end.equals(other.end);
+  }
+
+  @Override
+  public int hashCode() {
+    return start.hashCode() * 17 + end.hashCode();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java
new file mode 100644 (file)
index 0000000..bda14d8
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.charhandler.CharHandler;
+import org.sonar.api.batch.fs.internal.charhandler.FileHashComputer;
+import org.sonar.api.batch.fs.internal.charhandler.LineCounter;
+import org.sonar.api.batch.fs.internal.charhandler.LineHashComputer;
+import org.sonar.api.batch.fs.internal.charhandler.LineOffsetCounter;
+
+/**
+ * Computes hash of files. Ends of Lines are ignored, so files with
+ * same content but different EOL encoding have the same hash.
+ */
+@Immutable
+public class FileMetadata {
+  private static final char LINE_FEED = '\n';
+  private static final char CARRIAGE_RETURN = '\r';
+
+  /**
+   * Compute hash of a file ignoring line ends differences.
+   * Maximum performance is needed.
+   */
+  public Metadata readMetadata(InputStream stream, Charset encoding, String filePath, @Nullable CharHandler otherHandler) {
+    LineCounter lineCounter = new LineCounter(filePath, encoding);
+    FileHashComputer fileHashComputer = new FileHashComputer(filePath);
+    LineOffsetCounter lineOffsetCounter = new LineOffsetCounter();
+
+    if (otherHandler != null) {
+      CharHandler[] handlers = {lineCounter, fileHashComputer, lineOffsetCounter, otherHandler};
+      readFile(stream, encoding, filePath, handlers);
+    } else {
+      CharHandler[] handlers = {lineCounter, fileHashComputer, lineOffsetCounter};
+      readFile(stream, encoding, filePath, handlers);
+    }
+    return new Metadata(lineCounter.lines(), lineCounter.nonBlankLines(), fileHashComputer.getHash(), lineOffsetCounter.getOriginalLineStartOffsets(),
+      lineOffsetCounter.getOriginalLineEndOffsets(),
+      lineOffsetCounter.getLastValidOffset());
+  }
+
+  public Metadata readMetadata(InputStream stream, Charset encoding, String filePath) {
+    return readMetadata(stream, encoding, filePath, null);
+  }
+
+  /**
+   * For testing purpose
+   */
+  public Metadata readMetadata(Reader reader) {
+    LineCounter lineCounter = new LineCounter("fromString", StandardCharsets.UTF_16);
+    FileHashComputer fileHashComputer = new FileHashComputer("fromString");
+    LineOffsetCounter lineOffsetCounter = new LineOffsetCounter();
+    CharHandler[] handlers = {lineCounter, fileHashComputer, lineOffsetCounter};
+
+    try {
+      read(reader, handlers);
+    } catch (IOException e) {
+      throw new IllegalStateException("Should never occur", e);
+    }
+    return new Metadata(lineCounter.lines(), lineCounter.nonBlankLines(), fileHashComputer.getHash(), lineOffsetCounter.getOriginalLineStartOffsets(),
+      lineOffsetCounter.getOriginalLineEndOffsets(),
+      lineOffsetCounter.getLastValidOffset());
+  }
+
+  public static void readFile(InputStream stream, Charset encoding, String filePath, CharHandler[] handlers) {
+    try (Reader reader = new BufferedReader(new InputStreamReader(stream, encoding))) {
+      read(reader, handlers);
+    } catch (IOException e) {
+      throw new IllegalStateException(String.format("Fail to read file '%s' with encoding '%s'", filePath, encoding), e);
+    }
+  }
+
+  private static void read(Reader reader, CharHandler[] handlers) throws IOException {
+    char c;
+    int i = reader.read();
+    boolean afterCR = false;
+    while (i != -1) {
+      c = (char) i;
+      if (afterCR) {
+        for (CharHandler handler : handlers) {
+          if (c == CARRIAGE_RETURN) {
+            handler.newLine();
+            handler.handleAll(c);
+          } else if (c == LINE_FEED) {
+            handler.handleAll(c);
+            handler.newLine();
+          } else {
+            handler.newLine();
+            handler.handleIgnoreEoL(c);
+            handler.handleAll(c);
+          }
+        }
+        afterCR = c == CARRIAGE_RETURN;
+      } else if (c == LINE_FEED) {
+        for (CharHandler handler : handlers) {
+          handler.handleAll(c);
+          handler.newLine();
+        }
+      } else if (c == CARRIAGE_RETURN) {
+        afterCR = true;
+        for (CharHandler handler : handlers) {
+          handler.handleAll(c);
+        }
+      } else {
+        for (CharHandler handler : handlers) {
+          handler.handleIgnoreEoL(c);
+          handler.handleAll(c);
+        }
+      }
+      i = reader.read();
+    }
+    for (CharHandler handler : handlers) {
+      if (afterCR) {
+        handler.newLine();
+      }
+      handler.eof();
+    }
+  }
+
+  @FunctionalInterface
+  public interface LineHashConsumer {
+    void consume(int lineIdx, @Nullable byte[] hash);
+  }
+
+  /**
+   * Compute a MD5 hash of each line of the file after removing of all blank chars
+   */
+  public static void computeLineHashesForIssueTracking(InputFile f, LineHashConsumer consumer) {
+    try {
+      readFile(f.inputStream(), f.charset(), f.absolutePath(), new CharHandler[] {new LineHashComputer(consumer, f.file())});
+    } catch (IOException e) {
+      throw new IllegalStateException("Failed to compute line hashes for " + f.absolutePath(), e);
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java
new file mode 100644 (file)
index 0000000..50c0d75
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.util.Arrays;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+public class Metadata {
+  private final int lines;
+  private final int nonBlankLines;
+  private final String hash;
+  private final int[] originalLineStartOffsets;
+  private final int[] originalLineEndOffsets;
+  private final int lastValidOffset;
+
+  public Metadata(int lines, int nonBlankLines, String hash, int[] originalLineStartOffsets, int[] originalLineEndOffsets, int lastValidOffset) {
+    this.lines = lines;
+    this.nonBlankLines = nonBlankLines;
+    this.hash = hash;
+    this.originalLineStartOffsets = Arrays.copyOf(originalLineStartOffsets, originalLineStartOffsets.length);
+    this.originalLineEndOffsets = Arrays.copyOf(originalLineEndOffsets, originalLineEndOffsets.length);
+    this.lastValidOffset = lastValidOffset;
+  }
+
+  public int lines() {
+    return lines;
+  }
+
+  public int nonBlankLines() {
+    return nonBlankLines;
+  }
+
+  public String hash() {
+    return hash;
+  }
+
+  public int[] originalLineStartOffsets() {
+    return originalLineStartOffsets;
+  }
+
+  public int[] originalLineEndOffsets() {
+    return originalLineEndOffsets;
+  }
+
+  public int lastValidOffset() {
+    return lastValidOffset;
+  }
+
+  public boolean isEmpty() {
+    return lastValidOffset == 0;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
new file mode 100644 (file)
index 0000000..41287d4
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.nio.file.Path;
+import javax.annotation.concurrent.ThreadSafe;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.utils.PathUtils;
+import org.sonar.api.utils.WildcardPattern;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+@ThreadSafe
+public abstract class PathPattern {
+
+  private static final Logger LOG = Loggers.get(PathPattern.class);
+
+  /**
+   * @deprecated since 6.6
+   */
+  @Deprecated
+  private static final String ABSOLUTE_PATH_PATTERN_PREFIX = "file:";
+  final WildcardPattern pattern;
+
+  PathPattern(String pattern) {
+    this.pattern = WildcardPattern.create(pattern);
+  }
+
+  public abstract boolean match(Path absolutePath, Path relativePath);
+
+  public abstract boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension);
+
+  public static PathPattern create(String s) {
+    String trimmed = StringUtils.trim(s);
+    if (StringUtils.startsWithIgnoreCase(trimmed, ABSOLUTE_PATH_PATTERN_PREFIX)) {
+      LOG.warn("Using absolute path pattern is deprecated. Please use relative path instead of '" + trimmed + "'");
+      return new AbsolutePathPattern(StringUtils.substring(trimmed, ABSOLUTE_PATH_PATTERN_PREFIX.length()));
+    }
+    return new RelativePathPattern(trimmed);
+  }
+
+  public static PathPattern[] create(String[] s) {
+    PathPattern[] result = new PathPattern[s.length];
+    for (int i = 0; i < s.length; i++) {
+      result[i] = create(s[i]);
+    }
+    return result;
+  }
+
+  /**
+   * @deprecated since 6.6
+   */
+  @Deprecated
+  private static class AbsolutePathPattern extends PathPattern {
+    private AbsolutePathPattern(String pattern) {
+      super(pattern);
+    }
+
+    @Override
+    public boolean match(Path absolutePath, Path relativePath) {
+      return match(absolutePath, relativePath, true);
+    }
+
+    @Override
+    public boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension) {
+      String path = PathUtils.sanitize(absolutePath.toString());
+      if (!caseSensitiveFileExtension) {
+        String extension = sanitizeExtension(FilenameUtils.getExtension(path));
+        if (StringUtils.isNotBlank(extension)) {
+          path = StringUtils.removeEndIgnoreCase(path, extension);
+          path = path + extension;
+        }
+      }
+      return pattern.match(path);
+    }
+
+    @Override
+    public String toString() {
+      return ABSOLUTE_PATH_PATTERN_PREFIX + pattern.toString();
+    }
+  }
+
+  /**
+   * Path relative to module basedir
+   */
+  private static class RelativePathPattern extends PathPattern {
+    private RelativePathPattern(String pattern) {
+      super(pattern);
+    }
+
+    @Override
+    public boolean match(Path absolutePath, Path relativePath) {
+      return match(absolutePath, relativePath, true);
+    }
+
+    @Override
+    public boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension) {
+      String path = PathUtils.sanitize(relativePath.toString());
+      if (!caseSensitiveFileExtension) {
+        String extension = sanitizeExtension(FilenameUtils.getExtension(path));
+        if (StringUtils.isNotBlank(extension)) {
+          path = StringUtils.removeEndIgnoreCase(path, extension);
+          path = path + extension;
+        }
+      }
+      return path != null && pattern.match(path);
+    }
+
+    @Override
+    public String toString() {
+      return pattern.toString();
+    }
+  }
+
+  static String sanitizeExtension(String suffix) {
+    return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java
new file mode 100644 (file)
index 0000000..adde738
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * A shared, mutable object in the project container.
+ * It's used during the execution of sensors to decide whether
+ * sensors should be executed once for the entire project, or per-module.
+ * It is also injected into each InputFile to change the behavior of {@link InputFile#relativePath()}
+ */
+public class SensorStrategy {
+
+  private boolean global = true;
+
+  public boolean isGlobal() {
+    return global;
+  }
+
+  public void setGlobal(boolean global) {
+    this.global = global;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/TestInputFileBuilder.java
new file mode 100644 (file)
index 0000000..00f9319
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * Intended to be used in unit tests that need to create {@link InputFile}s.
+ * An InputFile is unambiguously identified by a <b>module key</b> and a <b>relative path</b>, so these parameters are mandatory.
+ * <p>
+ * A module base directory is only needed to construct absolute paths.
+ * <p>
+ * Examples of usage of the constructors:
+ *
+ * <pre>
+ * InputFile file1 = TestInputFileBuilder.create("module1", "myfile.java").build();
+ * InputFile file2 = TestInputFileBuilder.create("", fs.baseDir(), myfile).build();
+ * </pre>
+ * <p>
+ * file1 will have the "module1" as both module key and module base directory.
+ * file2 has an empty string as module key, and a relative path which is the path from the filesystem base directory to myfile.
+ *
+ * @since 6.3
+ */
+public class TestInputFileBuilder {
+  private static int batchId = 1;
+
+  private final int id;
+  private final String relativePath;
+  private final String projectKey;
+  @CheckForNull
+  private Path projectBaseDir;
+  private Path moduleBaseDir;
+  private String language;
+  private InputFile.Type type = InputFile.Type.MAIN;
+  private InputFile.Status status;
+  private int lines = -1;
+  private Charset charset;
+  private String hash;
+  private int nonBlankLines;
+  private int[] originalLineStartOffsets = new int[0];
+  private int[] originalLineEndOffsets = new int[0];
+  private int lastValidOffset = -1;
+  private boolean publish = true;
+  private String contents;
+
+  /**
+   * Create a InputFile identified by the given project key and relative path.
+   */
+  public TestInputFileBuilder(String projectKey, String relativePath) {
+    this(projectKey, relativePath, batchId++);
+  }
+
+  /**
+   * Create a InputFile with a given module key and module base directory.
+   * The relative path is generated comparing the file path to the module base directory.
+   * filePath must point to a file that is within the module base directory.
+   */
+  public TestInputFileBuilder(String projectKey, File moduleBaseDir, File filePath) {
+    String relativePath = moduleBaseDir.toPath().relativize(filePath.toPath()).toString();
+    this.projectKey = projectKey;
+    setModuleBaseDir(moduleBaseDir.toPath());
+    this.relativePath = PathUtils.sanitize(relativePath);
+    this.id = batchId++;
+  }
+
+  public TestInputFileBuilder(String projectKey, String relativePath, int id) {
+    this.projectKey = projectKey;
+    setModuleBaseDir(Paths.get(projectKey));
+    this.relativePath = PathUtils.sanitize(relativePath);
+    this.id = id;
+  }
+
+  public static TestInputFileBuilder create(String moduleKey, File moduleBaseDir, File filePath) {
+    return new TestInputFileBuilder(moduleKey, moduleBaseDir, filePath);
+  }
+
+  public static TestInputFileBuilder create(String moduleKey, String relativePath) {
+    return new TestInputFileBuilder(moduleKey, relativePath);
+  }
+
+  public static int nextBatchId() {
+    return batchId++;
+  }
+
+  public TestInputFileBuilder setProjectBaseDir(Path projectBaseDir) {
+    this.projectBaseDir = normalize(projectBaseDir);
+    return this;
+  }
+
+  public TestInputFileBuilder setModuleBaseDir(Path moduleBaseDir) {
+    this.moduleBaseDir = normalize(moduleBaseDir);
+    return this;
+  }
+
+  private static Path normalize(Path path) {
+    try {
+      return path.normalize().toRealPath(LinkOption.NOFOLLOW_LINKS);
+    } catch (IOException e) {
+      return path.normalize();
+    }
+  }
+
+  public TestInputFileBuilder setLanguage(@Nullable String language) {
+    this.language = language;
+    return this;
+  }
+
+  public TestInputFileBuilder setType(InputFile.Type type) {
+    this.type = type;
+    return this;
+  }
+
+  public TestInputFileBuilder setStatus(InputFile.Status status) {
+    this.status = status;
+    return this;
+  }
+
+  public TestInputFileBuilder setLines(int lines) {
+    this.lines = lines;
+    return this;
+  }
+
+  public TestInputFileBuilder setCharset(Charset charset) {
+    this.charset = charset;
+    return this;
+  }
+
+  public TestInputFileBuilder setHash(String hash) {
+    this.hash = hash;
+    return this;
+  }
+
+  /**
+   * Set contents of the file and calculates metadata from it.
+   * The contents will be returned by {@link InputFile#contents()} and {@link InputFile#inputStream()} and can be
+   * inconsistent with the actual physical file pointed by {@link InputFile#path()}, {@link InputFile#absolutePath()}, etc.
+   */
+  public TestInputFileBuilder setContents(String content) {
+    this.contents = content;
+    initMetadata(content);
+    return this;
+  }
+
+  public TestInputFileBuilder setNonBlankLines(int nonBlankLines) {
+    this.nonBlankLines = nonBlankLines;
+    return this;
+  }
+
+  public TestInputFileBuilder setLastValidOffset(int lastValidOffset) {
+    this.lastValidOffset = lastValidOffset;
+    return this;
+  }
+
+  public TestInputFileBuilder setOriginalLineStartOffsets(int[] originalLineStartOffsets) {
+    this.originalLineStartOffsets = originalLineStartOffsets;
+    return this;
+  }
+
+  public TestInputFileBuilder setOriginalLineEndOffsets(int[] originalLineEndOffsets) {
+    this.originalLineEndOffsets = originalLineEndOffsets;
+    return this;
+  }
+
+  public TestInputFileBuilder setPublish(boolean publish) {
+    this.publish = publish;
+    return this;
+  }
+
+  public TestInputFileBuilder setMetadata(Metadata metadata) {
+    this.setLines(metadata.lines());
+    this.setLastValidOffset(metadata.lastValidOffset());
+    this.setNonBlankLines(metadata.nonBlankLines());
+    this.setHash(metadata.hash());
+    this.setOriginalLineStartOffsets(metadata.originalLineStartOffsets());
+    this.setOriginalLineEndOffsets(metadata.originalLineEndOffsets());
+    return this;
+  }
+
+  public TestInputFileBuilder initMetadata(String content) {
+    return setMetadata(new FileMetadata().readMetadata(new StringReader(content)));
+  }
+
+  public DefaultInputFile build() {
+    Path absolutePath = moduleBaseDir.resolve(relativePath);
+    if (projectBaseDir == null) {
+      projectBaseDir = moduleBaseDir;
+    }
+    String projectRelativePath = projectBaseDir.relativize(absolutePath).toString();
+    DefaultIndexedFile indexedFile = new DefaultIndexedFile(absolutePath, projectKey, projectRelativePath, relativePath, type, language, id, new SensorStrategy());
+    DefaultInputFile inputFile = new DefaultInputFile(indexedFile,
+      f -> f.setMetadata(new Metadata(lines, nonBlankLines, hash, originalLineStartOffsets, originalLineEndOffsets, lastValidOffset)),
+      contents);
+    inputFile.setStatus(status);
+    inputFile.setCharset(charset);
+    inputFile.setPublished(publish);
+    return inputFile;
+  }
+
+  public static DefaultInputModule newDefaultInputModule(String moduleKey, File baseDir) {
+    ProjectDefinition definition = ProjectDefinition.create()
+      .setKey(moduleKey)
+      .setBaseDir(baseDir)
+      .setWorkDir(new File(baseDir, ".sonar"));
+    return newDefaultInputModule(definition);
+  }
+
+  public static DefaultInputModule newDefaultInputModule(ProjectDefinition projectDefinition) {
+    return new DefaultInputModule(projectDefinition, TestInputFileBuilder.nextBatchId());
+  }
+
+  public static DefaultInputModule newDefaultInputModule(AbstractProjectOrModule parent, String key) throws IOException {
+    Path basedir = parent.getBaseDir().resolve(key);
+    Files.createDirectory(basedir);
+    return newDefaultInputModule(key, basedir.toFile());
+  }
+
+  public static DefaultInputProject newDefaultInputProject(String projectKey, File baseDir) {
+    ProjectDefinition definition = ProjectDefinition.create()
+      .setKey(projectKey)
+      .setBaseDir(baseDir)
+      .setWorkDir(new File(baseDir, ".sonar"));
+    return newDefaultInputProject(definition);
+  }
+
+  public static DefaultInputProject newDefaultInputProject(ProjectDefinition projectDefinition) {
+    return new DefaultInputProject(projectDefinition, TestInputFileBuilder.nextBatchId());
+  }
+
+  public static DefaultInputProject newDefaultInputProject(String key, Path baseDir) throws IOException {
+    Files.createDirectory(baseDir);
+    return newDefaultInputProject(key, baseDir.toFile());
+  }
+
+  public static DefaultInputDir newDefaultInputDir(AbstractProjectOrModule module, String relativePath) throws IOException {
+    Path basedir = module.getBaseDir().resolve(relativePath);
+    Files.createDirectory(basedir);
+    return new DefaultInputDir(module.key(), relativePath)
+      .setModuleBaseDir(module.getBaseDir());
+  }
+
+  public static DefaultInputFile newDefaultInputFile(Path projectBaseDir, AbstractProjectOrModule module, String relativePath) {
+    return new TestInputFileBuilder(module.key(), relativePath)
+      .setStatus(InputFile.Status.SAME)
+      .setProjectBaseDir(projectBaseDir)
+      .setModuleBaseDir(module.getBaseDir())
+      .build();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/CharHandler.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/CharHandler.java
new file mode 100644 (file)
index 0000000..8932b7d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.charhandler;
+
+public abstract class CharHandler {
+
+  public void handleAll(char c) {
+  }
+
+  public void handleIgnoreEoL(char c) {
+  }
+
+  public void newLine() {
+  }
+
+  public void eof() {
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/FileHashComputer.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/FileHashComputer.java
new file mode 100644 (file)
index 0000000..9fe15ff
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.charhandler;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.codec.digest.DigestUtils;
+
+public class FileHashComputer extends CharHandler {
+  private static final char LINE_FEED = '\n';
+
+  
+  private MessageDigest globalMd5Digest = DigestUtils.getMd5Digest();
+  private StringBuilder sb = new StringBuilder();
+  private final CharsetEncoder encoder;
+  private final String filePath;
+
+  public FileHashComputer(String filePath) {
+    encoder = StandardCharsets.UTF_8.newEncoder()
+      .onMalformedInput(CodingErrorAction.REPLACE)
+      .onUnmappableCharacter(CodingErrorAction.REPLACE);
+    this.filePath = filePath;
+  }
+
+  @Override
+  public void handleIgnoreEoL(char c) {
+    sb.append(c);
+  }
+
+  @Override
+  public void newLine() {
+    sb.append(LINE_FEED);
+    processBuffer();
+    sb.setLength(0);
+  }
+
+  @Override
+  public void eof() {
+    if (sb.length() > 0) {
+      processBuffer();
+    }
+  }
+
+  private void processBuffer() {
+    try {
+      if (sb.length() > 0) {
+        ByteBuffer encoded = encoder.encode(CharBuffer.wrap(sb));
+        globalMd5Digest.update(encoded.array(), 0, encoded.limit());
+      }
+    } catch (CharacterCodingException e) {
+      throw new IllegalStateException("Error encoding line hash in file: " + filePath, e);
+    }
+  }
+
+  public String getHash() {
+    return Hex.encodeHexString(globalMd5Digest.digest());
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/IntArrayList.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/IntArrayList.java
new file mode 100644 (file)
index 0000000..0795098
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.charhandler;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Specialization of {@link java.util.ArrayList} to create a list of int (only append elements) and then produce an int[].
+ */
+class IntArrayList {
+
+  /**
+   * Default initial capacity.
+   */
+  private static final int DEFAULT_CAPACITY = 10;
+
+  /**
+   * Shared empty array instance used for default sized empty instances. We
+   * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
+   * first element is added.
+   */
+  private static final int[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
+
+  /**
+   * The array buffer into which the elements of the ArrayList are stored.
+   * The capacity of the IntArrayList is the length of this array buffer. Any
+   * empty IntArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
+   * will be expanded to DEFAULT_CAPACITY when the first element is added.
+   */
+  private int[] elementData;
+
+  /**
+   * The size of the IntArrayList (the number of elements it contains).
+   */
+  private int size;
+
+  /**
+   * Constructs an empty list with an initial capacity of ten.
+   */
+  public IntArrayList() {
+    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
+  }
+
+  /**
+   * Trims the capacity of this <tt>IntArrayList</tt> instance to be the
+   * list's current size and return the internal array. An application can use this operation to minimize
+   * the storage of an <tt>IntArrayList</tt> instance.
+   */
+  public int[] trimAndGet() {
+    if (size < elementData.length) {
+      elementData = Arrays.copyOf(elementData, size);
+    }
+    return elementData;
+  }
+
+  private void ensureCapacityInternal(int minCapacity) {
+    int capacity = minCapacity;
+    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
+      capacity = Math.max(DEFAULT_CAPACITY, minCapacity);
+    }
+
+    ensureExplicitCapacity(capacity);
+  }
+
+  private void ensureExplicitCapacity(int minCapacity) {
+    if (minCapacity - elementData.length > 0) {
+      grow(minCapacity);
+    }
+  }
+
+  /**
+   * Increases the capacity to ensure that it can hold at least the
+   * number of elements specified by the minimum capacity argument.
+   *
+   * @param minCapacity the desired minimum capacity
+   */
+  private void grow(int minCapacity) {
+    int oldCapacity = elementData.length;
+    int newCapacity = oldCapacity + (oldCapacity >> 1);
+    if (newCapacity - minCapacity < 0) {
+      newCapacity = minCapacity;
+    }
+    elementData = Arrays.copyOf(elementData, newCapacity);
+  }
+
+  /**
+   * Appends the specified element to the end of this list.
+   *
+   * @param e element to be appended to this list
+   * @return <tt>true</tt> (as specified by {@link Collection#add})
+   */
+  public boolean add(int e) {
+    ensureCapacityInternal(size + 1);
+    elementData[size] = e;
+    size++;
+    return true;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineCounter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineCounter.java
new file mode 100644 (file)
index 0000000..588d716
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.charhandler;
+
+import java.nio.charset.Charset;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+public class LineCounter extends CharHandler {
+  private static final Logger LOG = Loggers.get(LineCounter.class);
+    
+  private int lines = 1;
+  private int nonBlankLines = 0;
+  private boolean blankLine = true;
+  boolean alreadyLoggedInvalidCharacter = false;
+  private final String filePath;
+  private final Charset encoding;
+
+  public LineCounter(String filePath, Charset encoding) {
+    this.filePath = filePath;
+    this.encoding = encoding;
+  }
+
+  @Override
+  public void handleAll(char c) {
+    if (!alreadyLoggedInvalidCharacter && c == '\ufffd') {
+      LOG.warn("Invalid character encountered in file {} at line {} for encoding {}. Please fix file content or configure the encoding to be used using property '{}'.", filePath,
+        lines, encoding, CoreProperties.ENCODING_PROPERTY);
+      alreadyLoggedInvalidCharacter = true;
+    }
+  }
+
+  @Override
+  public void newLine() {
+    lines++;
+    if (!blankLine) {
+      nonBlankLines++;
+    }
+    blankLine = true;
+  }
+
+  @Override
+  public void handleIgnoreEoL(char c) {
+    if (!Character.isWhitespace(c)) {
+      blankLine = false;
+    }
+  }
+
+  @Override
+  public void eof() {
+    if (!blankLine) {
+      nonBlankLines++;
+    }
+  }
+
+  public int lines() {
+    return lines;
+  }
+
+  public int nonBlankLines() {
+    return nonBlankLines;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineHashComputer.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineHashComputer.java
new file mode 100644 (file)
index 0000000..fa8c4f1
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.charhandler;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+
+public class LineHashComputer extends CharHandler {
+  private final MessageDigest lineMd5Digest = DigestUtils.getMd5Digest();
+  private final CharsetEncoder encoder;
+  private final StringBuilder sb = new StringBuilder();
+  private final FileMetadata.LineHashConsumer consumer;
+  private final File file;
+  private int line = 1;
+
+  public LineHashComputer(FileMetadata.LineHashConsumer consumer, File f) {
+    this.consumer = consumer;
+    this.file = f;
+    this.encoder = StandardCharsets.UTF_8.newEncoder()
+      .onMalformedInput(CodingErrorAction.REPLACE)
+      .onUnmappableCharacter(CodingErrorAction.REPLACE);
+  }
+
+  @Override
+  public void handleIgnoreEoL(char c) {
+    if (!Character.isWhitespace(c)) {
+      sb.append(c);
+    }
+  }
+
+  @Override
+  public void newLine() {
+    processBuffer();
+    sb.setLength(0);
+    line++;
+  }
+
+  @Override
+  public void eof() {
+    if (this.line > 0) {
+      processBuffer();
+    }
+  }
+
+  private void processBuffer() {
+    try {
+      if (sb.length() > 0) {
+        ByteBuffer encoded = encoder.encode(CharBuffer.wrap(sb));
+        lineMd5Digest.update(encoded.array(), 0, encoded.limit());
+        consumer.consume(line, lineMd5Digest.digest());
+      }
+    } catch (CharacterCodingException e) {
+      throw new IllegalStateException("Error encoding line hash in file: " + file.getAbsolutePath(), e);
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineOffsetCounter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/LineOffsetCounter.java
new file mode 100644 (file)
index 0000000..22292be
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.charhandler;
+
+public class LineOffsetCounter extends CharHandler {
+  private long currentOriginalLineStartOffset = 0;
+  private long currentOriginalLineEndOffset = 0;
+  private final IntArrayList originalLineStartOffsets = new IntArrayList();
+  private final IntArrayList originalLineEndOffsets = new IntArrayList();
+  private long lastValidOffset = 0;
+
+  public LineOffsetCounter() {
+    originalLineStartOffsets.add(0);
+  }
+
+  @Override
+  public void handleAll(char c) {
+    currentOriginalLineStartOffset++;
+  }
+
+  @Override
+  public void handleIgnoreEoL(char c) {
+    currentOriginalLineEndOffset++;
+  }
+
+  @Override
+  public void newLine() {
+    if (currentOriginalLineStartOffset > Integer.MAX_VALUE) {
+      throw new IllegalStateException("File is too big: " + currentOriginalLineStartOffset);
+    }
+    originalLineStartOffsets.add((int) currentOriginalLineStartOffset);
+    originalLineEndOffsets.add((int) currentOriginalLineEndOffset);
+    currentOriginalLineEndOffset = currentOriginalLineStartOffset;
+  }
+
+  @Override
+  public void eof() {
+    originalLineEndOffsets.add((int) currentOriginalLineEndOffset);
+    lastValidOffset = currentOriginalLineStartOffset;
+  }
+
+  public int[] getOriginalLineStartOffsets() {
+    return originalLineStartOffsets.trimAndGet();
+  }
+
+  public int[] getOriginalLineEndOffsets() {
+    return originalLineEndOffsets.trimAndGet();
+  }
+
+  public int getLastValidOffset() {
+    if (lastValidOffset > Integer.MAX_VALUE) {
+      throw new IllegalStateException("File is too big: " + lastValidOffset);
+    }
+    return (int) lastValidOffset;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/charhandler/package-info.java
new file mode 100644 (file)
index 0000000..953ee25
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.fs.internal.charhandler;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
new file mode 100644 (file)
index 0000000..4af8d77
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.fs.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AbsolutePathPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AbsolutePathPredicate.java
new file mode 100644 (file)
index 0000000..56414c5
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import org.sonar.api.batch.fs.FileSystem.Index;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * @since 4.2
+ */
+class AbsolutePathPredicate extends AbstractFilePredicate {
+
+  private final String path;
+  private final Path baseDir;
+
+  AbsolutePathPredicate(String path, Path baseDir) {
+    this.baseDir = baseDir;
+    this.path = PathUtils.sanitize(path);
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return path.equals(f.absolutePath());
+  }
+
+  @Override
+  public Iterable<InputFile> get(Index index) {
+    String relative = PathUtils.sanitize(new PathResolver().relativePath(baseDir.toFile(), new File(path)));
+    if (relative == null) {
+      return Collections.emptyList();
+    }
+    InputFile f = index.inputFile(relative);
+    return f != null ? Arrays.asList(f) : Collections.<InputFile>emptyList();
+  }
+
+  @Override
+  public int priority() {
+    return USE_INDEX;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AbstractFilePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AbstractFilePredicate.java
new file mode 100644 (file)
index 0000000..a073ab6
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.stream.StreamSupport;
+import org.sonar.api.batch.fs.FileSystem.Index;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * Partial implementation of {@link OptimizedFilePredicate}.
+ * @since 5.1
+ */
+public abstract class AbstractFilePredicate implements OptimizedFilePredicate {
+
+  protected static final int DEFAULT_PRIORITY = 10;
+  protected static final int USE_INDEX = 20;
+
+  @Override
+  public Iterable<InputFile> filter(Iterable<InputFile> target) {
+    return () -> StreamSupport.stream(target.spliterator(), false)
+      .filter(this::apply)
+      .iterator();
+  }
+
+  @Override
+  public Iterable<InputFile> get(Index index) {
+    return filter(index.inputFiles());
+  }
+
+  @Override
+  public int priority() {
+    return DEFAULT_PRIORITY;
+  }
+
+  @Override
+  public final int compareTo(OptimizedFilePredicate o) {
+    return o.priority() - priority();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AndPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/AndPredicate.java
new file mode 100644 (file)
index 0000000..ab0c129
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem.Index;
+import org.sonar.api.batch.fs.InputFile;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * @since 4.2
+ */
+class AndPredicate extends AbstractFilePredicate implements OperatorPredicate {
+
+  private final List<OptimizedFilePredicate> predicates = new ArrayList<>();
+
+  private AndPredicate() {
+  }
+
+  public static FilePredicate create(Collection<FilePredicate> predicates) {
+    if (predicates.isEmpty()) {
+      return TruePredicate.TRUE;
+    }
+    AndPredicate result = new AndPredicate();
+    for (FilePredicate filePredicate : predicates) {
+      if (filePredicate == TruePredicate.TRUE) {
+        continue;
+      } else if (filePredicate == FalsePredicate.FALSE) {
+        return FalsePredicate.FALSE;
+      } else if (filePredicate instanceof AndPredicate) {
+        result.predicates.addAll(((AndPredicate) filePredicate).predicates);
+      } else {
+        result.predicates.add(OptimizedFilePredicateAdapter.create(filePredicate));
+      }
+    }
+    Collections.sort(result.predicates);
+    return result;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    for (OptimizedFilePredicate predicate : predicates) {
+      if (!predicate.apply(f)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public Iterable<InputFile> filter(Iterable<InputFile> target) {
+    Iterable<InputFile> result = target;
+    for (OptimizedFilePredicate predicate : predicates) {
+      result = predicate.filter(result);
+    }
+    return result;
+  }
+
+  @Override
+  public Iterable<InputFile> get(Index index) {
+    if (predicates.isEmpty()) {
+      return index.inputFiles();
+    }
+    // Optimization, use get on first predicate then filter with next predicates
+    Iterable<InputFile> result = predicates.get(0).get(index);
+    for (int i = 1; i < predicates.size(); i++) {
+      result = predicates.get(i).filter(result);
+    }
+    return result;
+  }
+
+  Collection<OptimizedFilePredicate> predicates() {
+    return predicates;
+  }
+
+  @Override
+  public List<FilePredicate> operands() {
+    return predicates.stream().map(p -> (FilePredicate) p).collect(toList());
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/DefaultFilePredicates.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/DefaultFilePredicates.java
new file mode 100644 (file)
index 0000000..1e45c43
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.io.File;
+import java.net.URI;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Status;
+import org.sonar.api.batch.fs.internal.PathPattern;
+
+/**
+ * Factory of {@link FilePredicate}
+ *
+ * @since 4.2
+ */
+public class DefaultFilePredicates implements FilePredicates {
+
+  private final Path baseDir;
+
+  /**
+   * Client code should use {@link org.sonar.api.batch.fs.FileSystem#predicates()} to get an instance
+   */
+  public DefaultFilePredicates(Path baseDir) {
+    this.baseDir = baseDir;
+  }
+
+  /**
+   * Returns a predicate that always evaluates to true
+   */
+  @Override
+  public FilePredicate all() {
+    return TruePredicate.TRUE;
+  }
+
+  /**
+   * Returns a predicate that always evaluates to false
+   */
+  @Override
+  public FilePredicate none() {
+    return FalsePredicate.FALSE;
+  }
+
+  @Override
+  public FilePredicate hasAbsolutePath(String s) {
+    return new AbsolutePathPredicate(s, baseDir);
+  }
+
+  /**
+   * non-normalized path and Windows-style path are supported
+   */
+  @Override
+  public FilePredicate hasRelativePath(String s) {
+    return new RelativePathPredicate(s);
+  }
+
+  @Override
+  public FilePredicate hasFilename(String s) {
+    return new FilenamePredicate(s);
+  }
+
+  @Override
+  public FilePredicate hasExtension(String s) {
+    return new FileExtensionPredicate(s);
+  }
+
+  @Override
+  public FilePredicate hasURI(URI uri) {
+    return new URIPredicate(uri, baseDir);
+  }
+
+  @Override
+  public FilePredicate matchesPathPattern(String inclusionPattern) {
+    return new PathPatternPredicate(PathPattern.create(inclusionPattern));
+  }
+
+  @Override
+  public FilePredicate matchesPathPatterns(String[] inclusionPatterns) {
+    if (inclusionPatterns.length == 0) {
+      return TruePredicate.TRUE;
+    }
+    FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length];
+    for (int i = 0; i < inclusionPatterns.length; i++) {
+      predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i]));
+    }
+    return or(predicates);
+  }
+
+  @Override
+  public FilePredicate doesNotMatchPathPattern(String exclusionPattern) {
+    return not(matchesPathPattern(exclusionPattern));
+  }
+
+  @Override
+  public FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) {
+    if (exclusionPatterns.length == 0) {
+      return TruePredicate.TRUE;
+    }
+    return not(matchesPathPatterns(exclusionPatterns));
+  }
+
+  @Override
+  public FilePredicate hasPath(String s) {
+    File file = new File(s);
+    if (file.isAbsolute()) {
+      return hasAbsolutePath(s);
+    }
+    return hasRelativePath(s);
+  }
+
+  @Override
+  public FilePredicate is(File ioFile) {
+    if (ioFile.isAbsolute()) {
+      return hasAbsolutePath(ioFile.getAbsolutePath());
+    }
+    return hasRelativePath(ioFile.getPath());
+  }
+
+  @Override
+  public FilePredicate hasLanguage(String language) {
+    return new LanguagePredicate(language);
+  }
+
+  @Override
+  public FilePredicate hasLanguages(Collection<String> languages) {
+    List<FilePredicate> list = new ArrayList<>();
+    for (String language : languages) {
+      list.add(hasLanguage(language));
+    }
+    return or(list);
+  }
+
+  @Override
+  public FilePredicate hasLanguages(String... languages) {
+    List<FilePredicate> list = new ArrayList<>();
+    for (String language : languages) {
+      list.add(hasLanguage(language));
+    }
+    return or(list);
+  }
+
+  @Override
+  public FilePredicate hasType(InputFile.Type type) {
+    return new TypePredicate(type);
+  }
+
+  @Override
+  public FilePredicate not(FilePredicate p) {
+    return new NotPredicate(p);
+  }
+
+  @Override
+  public FilePredicate or(Collection<FilePredicate> or) {
+    return OrPredicate.create(or);
+  }
+
+  @Override
+  public FilePredicate or(FilePredicate... or) {
+    return OrPredicate.create(Arrays.asList(or));
+  }
+
+  @Override
+  public FilePredicate or(FilePredicate first, FilePredicate second) {
+    return OrPredicate.create(Arrays.asList(first, second));
+  }
+
+  @Override
+  public FilePredicate and(Collection<FilePredicate> and) {
+    return AndPredicate.create(and);
+  }
+
+  @Override
+  public FilePredicate and(FilePredicate... and) {
+    return AndPredicate.create(Arrays.asList(and));
+  }
+
+  @Override
+  public FilePredicate and(FilePredicate first, FilePredicate second) {
+    return AndPredicate.create(Arrays.asList(first, second));
+  }
+
+  @Override
+  public FilePredicate hasStatus(Status status) {
+    return new StatusPredicate(status);
+  }
+
+  @Override
+  public FilePredicate hasAnyStatus() {
+    return new StatusPredicate(null);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FalsePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FalsePredicate.java
new file mode 100644 (file)
index 0000000..1f2207d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.Collections;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem.Index;
+import org.sonar.api.batch.fs.InputFile;
+
+class FalsePredicate extends AbstractFilePredicate {
+
+  static final FilePredicate FALSE = new FalsePredicate();
+
+  @Override
+  public boolean apply(InputFile inputFile) {
+    return false;
+  }
+
+  @Override
+  public Iterable<InputFile> filter(Iterable<InputFile> target) {
+    return Collections.emptyList();
+  }
+
+  @Override
+  public Iterable<InputFile> get(Index index) {
+    return Collections.emptyList();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicate.java
new file mode 100644 (file)
index 0000000..8e3e55a
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.Locale;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @since 6.3
+ */
+public class FileExtensionPredicate extends AbstractFilePredicate {
+
+  private final String extension;
+
+  public FileExtensionPredicate(String extension) {
+    this.extension = lowercase(extension);
+  }
+
+  @Override
+  public boolean apply(InputFile inputFile) {
+    return extension.equals(getExtension(inputFile));
+  }
+
+  @Override
+  public Iterable<InputFile> get(FileSystem.Index index) {
+    return index.getFilesByExtension(extension);
+  }
+
+  public static String getExtension(InputFile inputFile) {
+    return getExtension(inputFile.filename());
+  }
+
+  static String getExtension(String name) {
+    int index = name.lastIndexOf('.');
+    if (index < 0) {
+      return "";
+    }
+    return lowercase(name.substring(index + 1));
+  }
+
+  private static String lowercase(String extension) {
+    return extension.toLowerCase(Locale.ENGLISH);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicate.java
new file mode 100644 (file)
index 0000000..68a3e4f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @since 6.3
+ */
+public class FilenamePredicate extends AbstractFilePredicate {
+  private final String filename;
+
+  public FilenamePredicate(String filename) {
+    this.filename = filename;
+  }
+
+  @Override
+  public boolean apply(InputFile inputFile) {
+    return filename.equals(inputFile.filename());
+  }
+
+  @Override
+  public Iterable<InputFile> get(FileSystem.Index index) {
+    return index.getFilesByName(filename);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/LanguagePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/LanguagePredicate.java
new file mode 100644 (file)
index 0000000..e78ef8d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @since 4.2
+ */
+class LanguagePredicate extends AbstractFilePredicate {
+  private final String language;
+
+  LanguagePredicate(String language) {
+    this.language = language;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return language.equals(f.language());
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/NotPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/NotPredicate.java
new file mode 100644 (file)
index 0000000..33b3c67
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.Arrays;
+import java.util.List;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @since 4.2
+ */
+class NotPredicate extends AbstractFilePredicate implements OperatorPredicate {
+
+  private final FilePredicate predicate;
+
+  NotPredicate(FilePredicate predicate) {
+    this.predicate = predicate;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return !predicate.apply(f);
+  }
+
+  @Override
+  public List<FilePredicate> operands() {
+    return Arrays.asList(predicate);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OperatorPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OperatorPredicate.java
new file mode 100644 (file)
index 0000000..06e3042
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.List;
+import org.sonar.api.batch.fs.FilePredicate;
+
+/**
+ * A predicate that associate other predicates
+ */
+public interface OperatorPredicate extends FilePredicate {
+
+  List<FilePredicate> operands();
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OptimizedFilePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OptimizedFilePredicate.java
new file mode 100644 (file)
index 0000000..de1ea6a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * Optimized version of FilePredicate allowing to speed up query by looking at InputFile by index.
+ */
+public interface OptimizedFilePredicate extends FilePredicate, Comparable<OptimizedFilePredicate> {
+
+  /**
+   * Filter provided files to keep only the ones that are valid for this predicate
+   */
+  Iterable<InputFile> filter(Iterable<InputFile> inputFiles);
+
+  /**
+   * Get all files that are valid for this predicate.
+   */
+  Iterable<InputFile> get(FileSystem.Index index);
+
+  /**
+   * For optimization. FilePredicates will be applied in priority order. For example when doing
+   * p.and(p1, p2, p3) then p1, p2 and p3 will be applied according to their priority value. Higher priority value
+   * are applied first.
+   * Assign a high priority when the predicate will likely highly reduce the set of InputFiles to filter. Also
+   * {@link RelativePathPredicate} and AbsolutePathPredicate have a high priority since they are using cache index.
+   */
+  int priority();
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OptimizedFilePredicateAdapter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OptimizedFilePredicateAdapter.java
new file mode 100644 (file)
index 0000000..e2f9336
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+public class OptimizedFilePredicateAdapter extends AbstractFilePredicate {
+
+  private FilePredicate unoptimizedPredicate;
+
+  private OptimizedFilePredicateAdapter(FilePredicate unoptimizedPredicate) {
+    this.unoptimizedPredicate = unoptimizedPredicate;
+  }
+
+  @Override
+  public boolean apply(InputFile inputFile) {
+    return unoptimizedPredicate.apply(inputFile);
+  }
+
+  public static OptimizedFilePredicate create(FilePredicate predicate) {
+    if (predicate instanceof OptimizedFilePredicate) {
+      return (OptimizedFilePredicate) predicate;
+    } else {
+      return new OptimizedFilePredicateAdapter(predicate);
+    }
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OrPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/OrPredicate.java
new file mode 100644 (file)
index 0000000..92a3ec0
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @since 4.2
+ */
+class OrPredicate extends AbstractFilePredicate implements OperatorPredicate {
+
+  private final List<FilePredicate> predicates = new ArrayList<>();
+
+  private OrPredicate() {
+  }
+
+  public static FilePredicate create(Collection<FilePredicate> predicates) {
+    if (predicates.isEmpty()) {
+      return TruePredicate.TRUE;
+    }
+    OrPredicate result = new OrPredicate();
+    for (FilePredicate filePredicate : predicates) {
+      if (filePredicate == TruePredicate.TRUE) {
+        return TruePredicate.TRUE;
+      } else if (filePredicate == FalsePredicate.FALSE) {
+        continue;
+      } else if (filePredicate instanceof OrPredicate) {
+        result.predicates.addAll(((OrPredicate) filePredicate).predicates);
+      } else {
+        result.predicates.add(filePredicate);
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    for (FilePredicate predicate : predicates) {
+      if (predicate.apply(f)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  Collection<FilePredicate> predicates() {
+    return predicates;
+  }
+
+  @Override
+  public List<FilePredicate> operands() {
+    return predicates;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/PathPatternPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/PathPatternPredicate.java
new file mode 100644 (file)
index 0000000..70efa65
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.nio.file.Paths;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.PathPattern;
+
+/**
+ * @since 4.2
+ */
+class PathPatternPredicate extends AbstractFilePredicate {
+
+  private final PathPattern pattern;
+
+  PathPatternPredicate(PathPattern pattern) {
+    this.pattern = pattern;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return pattern.match(f.path(), Paths.get(f.relativePath()));
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/RelativePathPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/RelativePathPredicate.java
new file mode 100644 (file)
index 0000000..c03a209
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.Collections;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.FileSystem.Index;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.utils.PathUtils;
+
+/**
+ * @since 4.2
+ */
+public class RelativePathPredicate extends AbstractFilePredicate {
+
+  @Nullable
+  private final String path;
+
+  RelativePathPredicate(String path) {
+    this.path = PathUtils.sanitize(path);
+  }
+
+  public String path() {
+    return path;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    if (path == null) {
+      return false;
+    }
+
+    return path.equals(f.relativePath());
+  }
+
+  @Override
+  public Iterable<InputFile> get(Index index) {
+    if (path != null) {
+      InputFile f = index.inputFile(this.path);
+      if (f != null) {
+        return Collections.singletonList(f);
+      }
+    }
+    return Collections.emptyList();
+  }
+
+  @Override
+  public int priority() {
+    return USE_INDEX;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/StatusPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/StatusPredicate.java
new file mode 100644 (file)
index 0000000..e9a6b87
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @deprecated since 7.8
+ */
+@Deprecated
+public class StatusPredicate extends AbstractFilePredicate {
+
+  private final InputFile.Status status;
+
+  StatusPredicate(@Nullable InputFile.Status status) {
+    this.status = status;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return status == null || status == f.status();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/TruePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/TruePredicate.java
new file mode 100644 (file)
index 0000000..1dfcdfc
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem.Index;
+import org.sonar.api.batch.fs.InputFile;
+
+class TruePredicate extends AbstractFilePredicate {
+
+  static final FilePredicate TRUE = new TruePredicate();
+
+  @Override
+  public boolean apply(InputFile inputFile) {
+    return true;
+  }
+
+  @Override
+  public Iterable<InputFile> get(Index index) {
+    return index.inputFiles();
+  }
+
+  @Override
+  public Iterable<InputFile> filter(Iterable<InputFile> target) {
+    return target;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/TypePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/TypePredicate.java
new file mode 100644 (file)
index 0000000..081fee5
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.sonar.api.batch.fs.InputFile;
+
+/**
+ * @since 4.2
+ */
+class TypePredicate extends AbstractFilePredicate {
+
+  private final InputFile.Type type;
+
+  TypePredicate(InputFile.Type type) {
+    this.type = type;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return type == f.type();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/URIPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/URIPredicate.java
new file mode 100644 (file)
index 0000000..8dd2a30
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Optional;
+import org.sonar.api.batch.fs.FileSystem.Index;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.scan.filesystem.PathResolver;
+
+/**
+ * @since 6.6
+ */
+class URIPredicate extends AbstractFilePredicate {
+
+  private final URI uri;
+  private final Path baseDir;
+
+  URIPredicate(URI uri, Path baseDir) {
+    this.baseDir = baseDir;
+    this.uri = uri;
+  }
+
+  @Override
+  public boolean apply(InputFile f) {
+    return uri.equals(f.uri());
+  }
+
+  @Override
+  public Iterable<InputFile> get(Index index) {
+    Path path = Paths.get(uri);
+    Optional<String> relative = PathResolver.relativize(baseDir, path);
+    if (!relative.isPresent()) {
+      return Collections.emptyList();
+    }
+    InputFile f = index.inputFile(relative.get());
+    return f != null ? Arrays.asList(f) : Collections.<InputFile>emptyList();
+  }
+
+  @Override
+  public int priority() {
+    return USE_INDEX;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/fs/internal/predicates/package-info.java
new file mode 100644 (file)
index 0000000..d847fbe
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.fs.internal.predicates;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/postjob/internal/DefaultPostJobDescriptor.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/postjob/internal/DefaultPostJobDescriptor.java
new file mode 100644 (file)
index 0000000..c3c2396
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.postjob.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.sonar.api.batch.postjob.PostJobDescriptor;
+
+public class DefaultPostJobDescriptor implements PostJobDescriptor {
+
+  private String name;
+  private String[] properties = new String[0];
+
+  public String name() {
+    return name;
+  }
+
+  public Collection<String> properties() {
+    return Arrays.asList(properties);
+  }
+
+  @Override
+  public DefaultPostJobDescriptor name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  @Override
+  public DefaultPostJobDescriptor requireProperty(String... propertyKey) {
+    return requireProperties(propertyKey);
+  }
+
+  @Override
+  public DefaultPostJobDescriptor requireProperties(String... propertyKeys) {
+    this.properties = propertyKeys;
+    return this;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/postjob/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/postjob/internal/package-info.java
new file mode 100644 (file)
index 0000000..8e69c51
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.postjob.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultActiveRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultActiveRule.java
deleted file mode 100644 (file)
index a46bf1a..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.batch.rule;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.rule.RuleKey;
-
-@Immutable
-public class DefaultActiveRule implements ActiveRule {
-  private final RuleKey ruleKey;
-  private final String severity;
-  private final String internalKey;
-  private final String language;
-  private final String templateRuleKey;
-  private final Map<String, String> params;
-  private final long createdAt;
-  private final long updatedAt;
-  private final String qProfileKey;
-
-  public DefaultActiveRule(NewActiveRule newActiveRule) {
-    this.severity = newActiveRule.severity;
-    this.internalKey = newActiveRule.internalKey;
-    this.templateRuleKey = newActiveRule.templateRuleKey;
-    this.ruleKey = newActiveRule.ruleKey;
-    this.params = Collections.unmodifiableMap(new HashMap<>(newActiveRule.params));
-    this.language = newActiveRule.language;
-    this.createdAt = newActiveRule.createdAt;
-    this.updatedAt = newActiveRule.updatedAt;
-    this.qProfileKey = newActiveRule.qProfileKey;
-  }
-
-  @Override
-  public RuleKey ruleKey() {
-    return ruleKey;
-  }
-
-  @Override
-  public String severity() {
-    return severity;
-  }
-
-  @Override
-  public String language() {
-    return language;
-  }
-
-  @Override
-  public String param(String key) {
-    return params.get(key);
-  }
-
-  @Override
-  public Map<String, String> params() {
-    // already immutable
-    return params;
-  }
-
-  @Override
-  public String internalKey() {
-    return internalKey;
-  }
-
-  @Override
-  public String templateRuleKey() {
-    return templateRuleKey;
-  }
-
-  public long createdAt() {
-    return createdAt;
-  }
-
-  public long updatedAt() {
-    return updatedAt;
-  }
-
-  @Override
-  public String qpKey() {
-    return qProfileKey;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRule.java
deleted file mode 100644 (file)
index b893852..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.batch.rule;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-
-@Immutable
-public class DefaultRule implements Rule {
-
-  private final RuleKey key;
-  private final Integer id;
-  private final String name;
-  private final String severity;
-  private final String type;
-  private final String description;
-  private final String internalKey;
-  private final RuleStatus status;
-  private final Map<String, RuleParam> params;
-
-  public DefaultRule(NewRule newRule) {
-    this.key = newRule.key;
-    this.id = newRule.id;
-    this.name = newRule.name;
-    this.severity = newRule.severity;
-    this.type = newRule.type;
-    this.description = newRule.description;
-    this.internalKey = newRule.internalKey;
-    this.status = newRule.status;
-
-    Map<String, RuleParam> builder = new HashMap<>();
-    for (NewRuleParam newRuleParam : newRule.params.values()) {
-      builder.put(newRuleParam.key, new DefaultRuleParam(newRuleParam));
-    }
-    params = Collections.unmodifiableMap(builder);
-  }
-
-  @Override
-  public RuleKey key() {
-    return key;
-  }
-
-  @CheckForNull
-  public Integer id() {
-    return id;
-  }
-
-  @Override
-  public String name() {
-    return name;
-  }
-
-  @Override
-  public String severity() {
-    return severity;
-  }
-
-  @CheckForNull
-  public String type() {
-    return type;
-  }
-
-  @Override
-  public String description() {
-    return description;
-  }
-
-  @Override
-  public String internalKey() {
-    return internalKey;
-  }
-
-  @Override
-  public RuleStatus status() {
-    return status;
-  }
-
-  @Override
-  public RuleParam param(String paramKey) {
-    return params.get(paramKey);
-  }
-
-  @Override
-  public Collection<RuleParam> params() {
-    return params.values();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRuleParam.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRuleParam.java
deleted file mode 100644 (file)
index eb714dc..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.batch.rule;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-class DefaultRuleParam implements RuleParam {
-
-  private final String key;
-  private final String description;
-
-  DefaultRuleParam(NewRuleParam p) {
-    this.key = p.key;
-    this.description = p.description;
-  }
-
-  @Override
-  public String key() {
-    return key;
-  }
-
-  @Override
-  @Nullable
-  public String description() {
-    return description;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/ActiveRulesBuilder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/ActiveRulesBuilder.java
new file mode 100644 (file)
index 0000000..a77980f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.rule.RuleKey;
+
+/**
+ * Builds instances of {@link org.sonar.api.batch.rule.ActiveRules}.
+ * <b>For unit testing and internal use only</b>.
+ *
+ * @since 4.2
+ */
+public class ActiveRulesBuilder {
+
+  private final Map<RuleKey, NewActiveRule> map = new LinkedHashMap<>();
+
+  public ActiveRulesBuilder addRule(NewActiveRule newActiveRule) {
+    if (map.containsKey(newActiveRule.ruleKey())) {
+      throw new IllegalStateException(String.format("Rule '%s' is already activated", newActiveRule.ruleKey()));
+    }
+    map.put(newActiveRule.ruleKey(), newActiveRule);
+    return this;
+  }
+
+  public ActiveRules build() {
+    return new DefaultActiveRules(map.values());
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRule.java
new file mode 100644 (file)
index 0000000..f1c9061
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.rule.ActiveRule;
+import org.sonar.api.rule.RuleKey;
+
+@Immutable
+public class DefaultActiveRule implements ActiveRule {
+  private final RuleKey ruleKey;
+  private final String severity;
+  private final String internalKey;
+  private final String language;
+  private final String templateRuleKey;
+  private final Map<String, String> params;
+  private final long createdAt;
+  private final long updatedAt;
+  private final String qProfileKey;
+
+  public DefaultActiveRule(NewActiveRule newActiveRule) {
+    this.severity = newActiveRule.severity;
+    this.internalKey = newActiveRule.internalKey;
+    this.templateRuleKey = newActiveRule.templateRuleKey;
+    this.ruleKey = newActiveRule.ruleKey;
+    this.params = Collections.unmodifiableMap(new HashMap<>(newActiveRule.params));
+    this.language = newActiveRule.language;
+    this.createdAt = newActiveRule.createdAt;
+    this.updatedAt = newActiveRule.updatedAt;
+    this.qProfileKey = newActiveRule.qProfileKey;
+  }
+
+  @Override
+  public RuleKey ruleKey() {
+    return ruleKey;
+  }
+
+  @Override
+  public String severity() {
+    return severity;
+  }
+
+  @Override
+  public String language() {
+    return language;
+  }
+
+  @Override
+  public String param(String key) {
+    return params.get(key);
+  }
+
+  @Override
+  public Map<String, String> params() {
+    // already immutable
+    return params;
+  }
+
+  @Override
+  public String internalKey() {
+    return internalKey;
+  }
+
+  @Override
+  public String templateRuleKey() {
+    return templateRuleKey;
+  }
+
+  public long createdAt() {
+    return createdAt;
+  }
+
+  public long updatedAt() {
+    return updatedAt;
+  }
+
+  @Override
+  public String qpKey() {
+    return qProfileKey;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRules.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRules.java
new file mode 100644 (file)
index 0000000..845137a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.rule.ActiveRule;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.rule.RuleKey;
+
+@Immutable
+public class DefaultActiveRules implements ActiveRules {
+  private final Map<String, List<ActiveRule>> activeRulesByRepository = new HashMap<>();
+  private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndKey = new HashMap<>();
+  private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndInternalKey = new HashMap<>();
+  private final Map<String, List<ActiveRule>> activeRulesByLanguage = new HashMap<>();
+
+  public DefaultActiveRules(Collection<NewActiveRule> newActiveRules) {
+    for (NewActiveRule newAR : newActiveRules) {
+      DefaultActiveRule ar = new DefaultActiveRule(newAR);
+      String repo = ar.ruleKey().repository();
+      activeRulesByRepository.computeIfAbsent(repo, x -> new ArrayList<>()).add(ar);
+      if (ar.language() != null) {
+        activeRulesByLanguage.computeIfAbsent(ar.language(), x -> new ArrayList<>()).add(ar);
+      }
+
+      activeRulesByRepositoryAndKey.computeIfAbsent(repo, r -> new HashMap<>()).put(ar.ruleKey().rule(), ar);
+      String internalKey = ar.internalKey();
+      if (internalKey != null) {
+        activeRulesByRepositoryAndInternalKey.computeIfAbsent(repo, r -> new HashMap<>()).put(internalKey, ar);
+      }
+    }
+  }
+
+  @Override
+  public ActiveRule find(RuleKey ruleKey) {
+    return activeRulesByRepositoryAndKey.getOrDefault(ruleKey.repository(), Collections.emptyMap())
+      .get(ruleKey.rule());
+  }
+
+  @Override
+  public Collection<ActiveRule> findAll() {
+    return activeRulesByRepository.entrySet().stream().flatMap(x -> x.getValue().stream()).collect(Collectors.toList());
+  }
+
+  @Override
+  public Collection<ActiveRule> findByRepository(String repository) {
+    return activeRulesByRepository.getOrDefault(repository, Collections.emptyList());
+  }
+
+  @Override
+  public Collection<ActiveRule> findByLanguage(String language) {
+    return activeRulesByLanguage.getOrDefault(language, Collections.emptyList());
+  }
+
+  @Override
+  public ActiveRule findByInternalKey(String repository, String internalKey) {
+    return activeRulesByRepositoryAndInternalKey.containsKey(repository) ? activeRulesByRepositoryAndInternalKey.get(repository).get(internalKey) : null;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java
new file mode 100644 (file)
index 0000000..5708c62
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.rule.Rule;
+import org.sonar.api.batch.rule.RuleParam;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+
+@Immutable
+public class DefaultRule implements Rule {
+
+  private final RuleKey key;
+  private final Integer id;
+  private final String name;
+  private final String severity;
+  private final String type;
+  private final String description;
+  private final String internalKey;
+  private final RuleStatus status;
+  private final Map<String, RuleParam> params;
+
+  public DefaultRule(NewRule newRule) {
+    this.key = newRule.key;
+    this.id = newRule.id;
+    this.name = newRule.name;
+    this.severity = newRule.severity;
+    this.type = newRule.type;
+    this.description = newRule.description;
+    this.internalKey = newRule.internalKey;
+    this.status = newRule.status;
+
+    Map<String, RuleParam> builder = new HashMap<>();
+    for (NewRuleParam newRuleParam : newRule.params.values()) {
+      builder.put(newRuleParam.key, new DefaultRuleParam(newRuleParam));
+    }
+    params = Collections.unmodifiableMap(builder);
+  }
+
+  @Override
+  public RuleKey key() {
+    return key;
+  }
+
+  @CheckForNull
+  public Integer id() {
+    return id;
+  }
+
+  @Override
+  public String name() {
+    return name;
+  }
+
+  @Override
+  public String severity() {
+    return severity;
+  }
+
+  @CheckForNull
+  public String type() {
+    return type;
+  }
+
+  @Override
+  public String description() {
+    return description;
+  }
+
+  @Override
+  public String internalKey() {
+    return internalKey;
+  }
+
+  @Override
+  public RuleStatus status() {
+    return status;
+  }
+
+  @Override
+  public RuleParam param(String paramKey) {
+    return params.get(paramKey);
+  }
+
+  @Override
+  public Collection<RuleParam> params() {
+    return params.values();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRuleParam.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRuleParam.java
new file mode 100644 (file)
index 0000000..793e949
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.rule.RuleParam;
+
+@Immutable
+class DefaultRuleParam implements RuleParam {
+
+  private final String key;
+  private final String description;
+
+  DefaultRuleParam(NewRuleParam p) {
+    this.key = p.key;
+    this.description = p.description;
+  }
+
+  @Override
+  public String key() {
+    return key;
+  }
+
+  @Override
+  @Nullable
+  public String description() {
+    return description;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRules.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/DefaultRules.java
new file mode 100644 (file)
index 0000000..def0012
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.batch.rule.Rule;
+import org.sonar.api.batch.rule.Rules;
+import org.sonar.api.rule.RuleKey;
+
+@Immutable
+class DefaultRules implements Rules {
+  private final Map<String, List<Rule>> rulesByRepository;
+  private final Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKey;
+  private final Map<RuleKey, Rule> rulesByRuleKey;
+
+  DefaultRules(Collection<NewRule> newRules) {
+    Map<String, List<Rule>> rulesByRepositoryBuilder = new HashMap<>();
+    Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKeyBuilder = new HashMap<>();
+    Map<RuleKey, Rule> rulesByRuleKeyBuilder = new HashMap<>();
+
+    for (NewRule newRule : newRules) {
+      DefaultRule r = new DefaultRule(newRule);
+      rulesByRuleKeyBuilder.put(r.key(), r);
+      rulesByRepositoryBuilder.computeIfAbsent(r.key().repository(), x -> new ArrayList<>()).add(r);
+      addToTable(rulesByRepositoryAndInternalKeyBuilder, r);
+    }
+
+    rulesByRuleKey = Collections.unmodifiableMap(rulesByRuleKeyBuilder);
+    rulesByRepository = Collections.unmodifiableMap(rulesByRepositoryBuilder);
+    rulesByRepositoryAndInternalKey = Collections.unmodifiableMap(rulesByRepositoryAndInternalKeyBuilder);
+  }
+
+  private static void addToTable(Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKeyBuilder, DefaultRule r) {
+    if (r.internalKey() == null) {
+      return;
+    }
+
+    rulesByRepositoryAndInternalKeyBuilder
+      .computeIfAbsent(r.key().repository(), x -> new HashMap<>())
+      .computeIfAbsent(r.internalKey(), x -> new ArrayList<>())
+      .add(r);
+  }
+
+  @Override
+  public Rule find(RuleKey ruleKey) {
+    return rulesByRuleKey.get(ruleKey);
+  }
+
+  @Override
+  public Collection<Rule> findAll() {
+    return rulesByRepository.values().stream().flatMap(List::stream).collect(Collectors.toList());
+  }
+
+  @Override
+  public Collection<Rule> findByRepository(String repository) {
+    return rulesByRepository.getOrDefault(repository, Collections.emptyList());
+  }
+
+  @Override
+  public Collection<Rule> findByInternalKey(String repository, String internalKey) {
+    return rulesByRepositoryAndInternalKey
+      .getOrDefault(repository, Collections.emptyMap())
+      .getOrDefault(internalKey, Collections.emptyList());
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewActiveRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewActiveRule.java
new file mode 100644 (file)
index 0000000..10b5c94
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+
+/**
+ * @since 4.2
+ */
+@Immutable
+public class NewActiveRule {
+  final RuleKey ruleKey;
+  final String name;
+  final String severity;
+  final Map<String, String> params;
+  final long createdAt;
+  final long updatedAt;
+  final String internalKey;
+  final String language;
+  final String templateRuleKey;
+  final String qProfileKey;
+
+  NewActiveRule(Builder builder) {
+    this.ruleKey = builder.ruleKey;
+    this.name = builder.name;
+    this.severity = builder.severity;
+    this.params = builder.params;
+    this.createdAt = builder.createdAt;
+    this.updatedAt = builder.updatedAt;
+    this.internalKey = builder.internalKey;
+    this.language = builder.language;
+    this.templateRuleKey = builder.templateRuleKey;
+    this.qProfileKey = builder.qProfileKey;
+  }
+
+  public RuleKey ruleKey() {
+    return this.ruleKey;
+  }
+
+  public static class Builder {
+    private RuleKey ruleKey;
+    private String name;
+    private String severity = Severity.defaultSeverity();
+    private Map<String, String> params = new HashMap<>();
+    private long createdAt;
+    private long updatedAt;
+    private String internalKey;
+    private String language;
+    private String templateRuleKey;
+    private String qProfileKey;
+
+    public Builder setRuleKey(RuleKey ruleKey) {
+      this.ruleKey = ruleKey;
+      return this;
+    }
+
+    public Builder setName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public Builder setSeverity(@Nullable String severity) {
+      this.severity = StringUtils.defaultIfBlank(severity, Severity.defaultSeverity());
+      return this;
+    }
+
+    public Builder setParam(String key, @Nullable String value) {
+      // possible improvement : check that the param key exists in rule definition
+      if (value == null) {
+        params.remove(key);
+      } else {
+        params.put(key, value);
+      }
+      return this;
+    }
+
+    public Builder setCreatedAt(long createdAt) {
+      this.createdAt = createdAt;
+      return this;
+    }
+
+    public Builder setUpdatedAt(long updatedAt) {
+      this.updatedAt = updatedAt;
+      return this;
+    }
+
+    public Builder setInternalKey(@Nullable String internalKey) {
+      this.internalKey = internalKey;
+      return this;
+    }
+
+    public Builder setLanguage(@Nullable String language) {
+      this.language = language;
+      return this;
+    }
+
+    public Builder setTemplateRuleKey(@Nullable String templateRuleKey) {
+      this.templateRuleKey = templateRuleKey;
+      return this;
+    }
+
+    public Builder setQProfileKey(String qProfileKey) {
+      this.qProfileKey = qProfileKey;
+      return this;
+    }
+
+    public NewActiveRule build() {
+      return new NewActiveRule(this);
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java
new file mode 100644 (file)
index 0000000..9805198
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+
+public class NewRule {
+
+  private static final String DEFAULT_SEVERITY = Severity.defaultSeverity();
+
+  final RuleKey key;
+  Integer id;
+  String name;
+  String description;
+  String severity = DEFAULT_SEVERITY;
+  String type;
+  String internalKey;
+  RuleStatus status = RuleStatus.defaultStatus();
+  Map<String, NewRuleParam> params = new HashMap<>();
+
+  public NewRule(RuleKey key) {
+    this.key = key;
+  }
+
+  public NewRule setId(@Nullable Integer id) {
+    this.id = id;
+    return this;
+  }
+
+  public NewRule setDescription(@Nullable String description) {
+    this.description = description;
+    return this;
+  }
+
+  public NewRule setName(@Nullable String s) {
+    this.name = s;
+    return this;
+  }
+
+  public NewRule setSeverity(@Nullable String severity) {
+    this.severity = StringUtils.defaultIfBlank(severity, DEFAULT_SEVERITY);
+    return this;
+  }
+  
+  public NewRule setType(@Nullable String type) {
+    this.type = type;
+    return this;
+  }
+
+  public NewRule setStatus(@Nullable RuleStatus s) {
+    this.status = (RuleStatus) ObjectUtils.defaultIfNull(s, RuleStatus.defaultStatus());
+    return this;
+  }
+
+  public NewRule setInternalKey(@Nullable String s) {
+    this.internalKey = s;
+    return this;
+  }
+
+  public NewRuleParam addParam(String paramKey) {
+    if (params.containsKey(paramKey)) {
+      throw new IllegalStateException(String.format("Parameter '%s' already exists on rule '%s'", paramKey, key));
+    }
+    NewRuleParam param = new NewRuleParam(paramKey);
+    params.put(paramKey, param);
+    return param;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewRuleParam.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/NewRuleParam.java
new file mode 100644 (file)
index 0000000..a274b56
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import javax.annotation.Nullable;
+
+public class NewRuleParam {
+  final String key;
+  String description;
+
+  NewRuleParam(String key) {
+    this.key = key;
+  }
+
+  public NewRuleParam setDescription(@Nullable String s) {
+    description = s;
+    return this;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/RulesBuilder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/RulesBuilder.java
new file mode 100644 (file)
index 0000000..88bf720
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.sonar.api.batch.rule.Rules;
+import org.sonar.api.rule.RuleKey;
+
+/**
+ * For unit testing and internal use only.
+ *
+ * @since 4.2
+ */
+
+public class RulesBuilder {
+
+  private final Map<RuleKey, NewRule> map = new HashMap<>();
+
+  public NewRule add(RuleKey key) {
+    if (map.containsKey(key)) {
+      throw new IllegalStateException(String.format("Rule '%s' already exists", key));
+    }
+    NewRule newRule = new NewRule(key);
+    map.put(key, newRule);
+    return newRule;
+  }
+
+  public Rules build() {
+    return new DefaultRules(map.values());
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/internal/package-info.java
new file mode 100644 (file)
index 0000000..8b52ade
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.rule.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCode.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCode.java
new file mode 100644 (file)
index 0000000..40ea16b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.code.internal;
+
+import java.util.SortedMap;
+import java.util.TreeMap;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.code.NewSignificantCode;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.utils.Preconditions;
+
+public class DefaultSignificantCode extends DefaultStorable implements NewSignificantCode {
+  private SortedMap<Integer, TextRange> significantCodePerLine = new TreeMap<>();
+  private InputFile inputFile;
+
+  public DefaultSignificantCode() {
+    super();
+  }
+
+  public DefaultSignificantCode(@Nullable SensorStorage storage) {
+    super(storage);
+  }
+
+  @Override
+  public DefaultSignificantCode onFile(InputFile inputFile) {
+    this.inputFile = inputFile;
+    return this;
+  }
+
+  @Override
+  public DefaultSignificantCode addRange(TextRange range) {
+    Preconditions.checkState(this.inputFile != null, "addRange() should be called after on()");
+
+    int line = range.start().line();
+
+    Preconditions.checkArgument(line == range.end().line(), "Ranges of significant code must be located in a single line");
+    Preconditions.checkState(!significantCodePerLine.containsKey(line), "Significant code was already reported for line '%s'. Can only report once per line.", line);
+
+    significantCodePerLine.put(line, range);
+    return this;
+  }
+
+  @Override
+  protected void doSave() {
+    Preconditions.checkState(inputFile != null, "Call onFile() first");
+    storage.store(this);
+  }
+
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  public SortedMap<Integer, TextRange> significantCodePerLine() {
+    return significantCodePerLine;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/code/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/code/internal/package-info.java
new file mode 100644 (file)
index 0000000..95f3885
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.code.internal;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/coverage/internal/DefaultCoverage.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/coverage/internal/DefaultCoverage.java
new file mode 100644 (file)
index 0000000..94fc188
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.coverage.internal;
+
+import java.util.Collections;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.coverage.CoverageType;
+import org.sonar.api.batch.sensor.coverage.NewCoverage;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultCoverage extends DefaultStorable implements NewCoverage {
+
+  private InputFile inputFile;
+  private CoverageType type;
+  private int totalCoveredLines = 0;
+  private int totalConditions = 0;
+  private int totalCoveredConditions = 0;
+  private SortedMap<Integer, Integer> hitsByLine = new TreeMap<>();
+  private SortedMap<Integer, Integer> conditionsByLine = new TreeMap<>();
+  private SortedMap<Integer, Integer> coveredConditionsByLine = new TreeMap<>();
+
+  public DefaultCoverage() {
+    super();
+  }
+
+  public DefaultCoverage(@Nullable SensorStorage storage) {
+    super(storage);
+  }
+
+  @Override
+  public DefaultCoverage onFile(InputFile inputFile) {
+    this.inputFile = inputFile;
+    return this;
+  }
+
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  @Override
+  public NewCoverage ofType(CoverageType type) {
+    this.type = requireNonNull(type, "type can't be null");
+    return this;
+  }
+
+  public CoverageType type() {
+    return type;
+  }
+
+  @Override
+  public NewCoverage lineHits(int line, int hits) {
+    validateFile();
+    if (isExcluded()) {
+      return this;
+    }
+    validateLine(line);
+
+    if (!hitsByLine.containsKey(line)) {
+      hitsByLine.put(line, hits);
+      if (hits > 0) {
+        totalCoveredLines += 1;
+      }
+    }
+    return this;
+  }
+
+  private void validateLine(int line) {
+    checkState(line <= inputFile.lines(), "Line %s is out of range in the file %s (lines: %s)", line, inputFile, inputFile.lines());
+    checkState(line > 0, "Line number must be strictly positive: %s", line);
+  }
+
+  private void validateFile() {
+    requireNonNull(inputFile, "Call onFile() first");
+  }
+
+  @Override
+  public NewCoverage conditions(int line, int conditions, int coveredConditions) {
+    validateFile();
+    if (isExcluded()) {
+      return this;
+    }
+    validateLine(line);
+
+    if (conditions > 0 && !conditionsByLine.containsKey(line)) {
+      totalConditions += conditions;
+      totalCoveredConditions += coveredConditions;
+      conditionsByLine.put(line, conditions);
+      coveredConditionsByLine.put(line, coveredConditions);
+    }
+    return this;
+  }
+
+  public int coveredLines() {
+    return totalCoveredLines;
+  }
+
+  public int linesToCover() {
+    return hitsByLine.size();
+  }
+
+  public int conditions() {
+    return totalConditions;
+  }
+
+  public int coveredConditions() {
+    return totalCoveredConditions;
+  }
+
+  public SortedMap<Integer, Integer> hitsByLine() {
+    return Collections.unmodifiableSortedMap(hitsByLine);
+  }
+
+  public SortedMap<Integer, Integer> conditionsByLine() {
+    return Collections.unmodifiableSortedMap(conditionsByLine);
+  }
+
+  public SortedMap<Integer, Integer> coveredConditionsByLine() {
+    return Collections.unmodifiableSortedMap(coveredConditionsByLine);
+  }
+
+  @Override
+  public void doSave() {
+    validateFile();
+    if (!isExcluded()) {
+      storage.store(this);
+    }
+  }
+
+  private boolean isExcluded() {
+    return ((DefaultInputFile) inputFile).isExcludedForCoverage();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/coverage/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/coverage/internal/package-info.java
new file mode 100644 (file)
index 0000000..a0b5e87
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.coverage.internal;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java
new file mode 100644 (file)
index 0000000..a2c592c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.cpd.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+import static java.util.Collections.unmodifiableList;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
+  private static final Logger LOG = Loggers.get(DefaultCpdTokens.class);
+  private final List<TokensLine> result = new ArrayList<>();
+  private DefaultInputFile inputFile;
+  private int startLine = Integer.MIN_VALUE;
+  private int startIndex = 0;
+  private int currentIndex = 0;
+  private StringBuilder sb = new StringBuilder();
+  private TextRange lastRange;
+  private boolean loggedTestCpdWarning = false;
+
+  public DefaultCpdTokens(SensorStorage storage) {
+    super(storage);
+  }
+
+  @Override
+  public DefaultCpdTokens onFile(InputFile inputFile) {
+    this.inputFile = (DefaultInputFile) requireNonNull(inputFile, "file can't be null");
+    return this;
+  }
+
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  @Override
+  public NewCpdTokens addToken(int startLine, int startLineOffset, int endLine, int endLineOffset, String image) {
+    checkInputFileNotNull();
+    TextRange newRange;
+    try {
+      newRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
+    } catch (Exception e) {
+      throw new IllegalArgumentException("Unable to register token in file " + inputFile, e);
+    }
+    return addToken(newRange, image);
+  }
+
+  @Override
+  public DefaultCpdTokens addToken(TextRange range, String image) {
+    requireNonNull(range, "Range should not be null");
+    requireNonNull(image, "Image should not be null");
+    checkInputFileNotNull();
+    if (isExcludedForDuplication()) {
+      return this;
+    }
+    checkState(lastRange == null || lastRange.end().compareTo(range.start()) <= 0,
+      "Tokens of file %s should be provided in order.\nPrevious token: %s\nLast token: %s", inputFile, lastRange, range);
+
+    int line = range.start().line();
+    if (line != startLine) {
+      addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
+      startIndex = currentIndex + 1;
+      startLine = line;
+    }
+    currentIndex++;
+    sb.append(image);
+    lastRange = range;
+
+    return this;
+  }
+
+  private boolean isExcludedForDuplication() {
+    if (inputFile.isExcludedForDuplication()) {
+      return true;
+    }
+    if (inputFile.type() == InputFile.Type.TEST) {
+      if (!loggedTestCpdWarning) {
+        LOG.warn("Duplication reported for '{}' will be ignored because it's a test file.", inputFile);
+        loggedTestCpdWarning = true;
+      }
+      return true;
+    }
+    return false;
+  }
+
+  public List<TokensLine> getTokenLines() {
+    return unmodifiableList(new ArrayList<>(result));
+  }
+
+  private static void addNewTokensLine(List<TokensLine> result, int startUnit, int endUnit, int startLine, StringBuilder sb) {
+    if (sb.length() != 0) {
+      result.add(new TokensLine(startUnit, endUnit, startLine, sb.toString()));
+      sb.setLength(0);
+    }
+  }
+
+  @Override
+  protected void doSave() {
+    checkState(inputFile != null, "Call onFile() first");
+    if (isExcludedForDuplication()) {
+      return;
+    }
+    addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
+    storage.store(this);
+  }
+
+  private void checkInputFileNotNull() {
+    checkState(inputFile != null, "Call onFile() first");
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/cpd/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/cpd/internal/package-info.java
new file mode 100644 (file)
index 0000000..f89010f
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.cpd.internal;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisError.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisError.java
new file mode 100644 (file)
index 0000000..3a9073a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.error.internal;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.sensor.error.AnalysisError;
+import org.sonar.api.batch.sensor.error.NewAnalysisError;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultAnalysisError extends DefaultStorable implements NewAnalysisError, AnalysisError {
+  private InputFile inputFile;
+  private String message;
+  private TextPointer location;
+
+  public DefaultAnalysisError() {
+    super(null);
+  }
+
+  public DefaultAnalysisError(SensorStorage storage) {
+    super(storage);
+  }
+
+  @Override
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  @Override
+  public String message() {
+    return message;
+  }
+
+  @Override
+  public TextPointer location() {
+    return location;
+  }
+
+  @Override
+  public NewAnalysisError onFile(InputFile inputFile) {
+    checkArgument(inputFile != null, "Cannot use a inputFile that is null");
+    checkState(this.inputFile == null, "onFile() already called");
+    this.inputFile = inputFile;
+    return this;
+  }
+
+  @Override
+  public NewAnalysisError message(String message) {
+    this.message = message;
+    return this;
+  }
+
+  @Override
+  public NewAnalysisError at(TextPointer location) {
+    checkState(this.location == null, "at() already called");
+    this.location = location;
+    return this;
+  }
+
+  @Override
+  protected void doSave() {
+    requireNonNull(this.inputFile, "inputFile is mandatory on AnalysisError");
+    storage.store(this);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/error/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/error/internal/package-info.java
new file mode 100644 (file)
index 0000000..07b2de5
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.error.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java
new file mode 100644 (file)
index 0000000..9bf679a
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.highlighting.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultHighlighting extends DefaultStorable implements NewHighlighting {
+
+  private final List<SyntaxHighlightingRule> syntaxHighlightingRules;
+  private DefaultInputFile inputFile;
+
+  public DefaultHighlighting(SensorStorage storage) {
+    super(storage);
+    syntaxHighlightingRules = new ArrayList<>();
+  }
+
+  public List<SyntaxHighlightingRule> getSyntaxHighlightingRuleSet() {
+    return syntaxHighlightingRules;
+  }
+
+  private void checkOverlappingBoundaries() {
+    if (syntaxHighlightingRules.size() > 1) {
+      Iterator<SyntaxHighlightingRule> it = syntaxHighlightingRules.iterator();
+      SyntaxHighlightingRule previous = it.next();
+      while (it.hasNext()) {
+        SyntaxHighlightingRule current = it.next();
+        if (previous.range().end().compareTo(current.range().start()) > 0 && (previous.range().end().compareTo(current.range().end()) < 0)) {
+          String errorMsg = String.format("Cannot register highlighting rule for characters at %s as it " +
+            "overlaps at least one existing rule", current.range());
+          throw new IllegalStateException(errorMsg);
+        }
+        previous = current;
+      }
+    }
+  }
+
+  @Override
+  public DefaultHighlighting onFile(InputFile inputFile) {
+    requireNonNull(inputFile, "file can't be null");
+    this.inputFile = (DefaultInputFile) inputFile;
+    return this;
+  }
+
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  @Override
+  public DefaultHighlighting highlight(int startOffset, int endOffset, TypeOfText typeOfText) {
+    checkInputFileNotNull();
+    TextRange newRange;
+    try {
+      newRange = inputFile.newRange(startOffset, endOffset);
+    } catch (Exception e) {
+      throw new IllegalArgumentException("Unable to highlight file " + inputFile, e);
+    }
+    return highlight(newRange, typeOfText);
+  }
+
+  @Override
+  public DefaultHighlighting highlight(int startLine, int startLineOffset, int endLine, int endLineOffset, TypeOfText typeOfText) {
+    checkInputFileNotNull();
+    TextRange newRange;
+    try {
+      newRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
+    } catch (Exception e) {
+      throw new IllegalArgumentException("Unable to highlight file " + inputFile, e);
+    }
+    return highlight(newRange, typeOfText);
+  }
+
+  @Override
+  public DefaultHighlighting highlight(TextRange range, TypeOfText typeOfText) {
+    SyntaxHighlightingRule syntaxHighlightingRule = SyntaxHighlightingRule.create(range, typeOfText);
+    this.syntaxHighlightingRules.add(syntaxHighlightingRule);
+    return this;
+  }
+
+  @Override
+  protected void doSave() {
+    checkInputFileNotNull();
+    // Sort rules to avoid variation during consecutive runs
+    Collections.sort(syntaxHighlightingRules, (left, right) -> {
+      int result = left.range().start().compareTo(right.range().start());
+      if (result == 0) {
+        result = right.range().end().compareTo(left.range().end());
+      }
+      return result;
+    });
+    checkOverlappingBoundaries();
+    storage.store(this);
+  }
+
+  private void checkInputFileNotNull() {
+    checkState(inputFile != null, "Call onFile() first");
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java
new file mode 100644 (file)
index 0000000..22934dc
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.highlighting.internal;
+
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+
+public class SyntaxHighlightingRule {
+
+  private final TextRange range;
+  private final TypeOfText textType;
+
+  private SyntaxHighlightingRule(TextRange range, TypeOfText textType) {
+    this.range = range;
+    this.textType = textType;
+  }
+
+  public static SyntaxHighlightingRule create(TextRange range, TypeOfText textType) {
+    return new SyntaxHighlightingRule(range, textType);
+  }
+
+  public TextRange range() {
+    return range;
+  }
+
+  public TypeOfText getTextType() {
+    return textType;
+  }
+
+  @Override
+  public String toString() {
+    return ReflectionToStringBuilder.toString(this, ToStringStyle.SIMPLE_STYLE);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/package-info.java
new file mode 100644 (file)
index 0000000..ca3da22
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.highlighting.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptor.java
new file mode 100644 (file)
index 0000000..ef29870
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Predicate;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.config.Configuration;
+
+import static java.util.Arrays.asList;
+
+public class DefaultSensorDescriptor implements SensorDescriptor {
+
+  private String name;
+  private String[] languages = new String[0];
+  private InputFile.Type type = null;
+  private String[] ruleRepositories = new String[0];
+  private boolean global = false;
+  private Predicate<Configuration> configurationPredicate;
+
+  public String name() {
+    return name;
+  }
+
+  public Collection<String> languages() {
+    return Arrays.asList(languages);
+  }
+
+  @Nullable
+  public InputFile.Type type() {
+    return type;
+  }
+
+  public Collection<String> ruleRepositories() {
+    return Arrays.asList(ruleRepositories);
+  }
+
+  public Predicate<Configuration> configurationPredicate() {
+    return configurationPredicate;
+  }
+
+  public boolean isGlobal() {
+    return global;
+  }
+
+  @Override
+  public DefaultSensorDescriptor name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  @Override
+  public DefaultSensorDescriptor onlyOnLanguage(String languageKey) {
+    return onlyOnLanguages(languageKey);
+  }
+
+  @Override
+  public DefaultSensorDescriptor onlyOnLanguages(String... languageKeys) {
+    this.languages = languageKeys;
+    return this;
+  }
+
+  @Override
+  public DefaultSensorDescriptor onlyOnFileType(InputFile.Type type) {
+    this.type = type;
+    return this;
+  }
+
+  @Override
+  public DefaultSensorDescriptor createIssuesForRuleRepository(String... repositoryKey) {
+    return createIssuesForRuleRepositories(repositoryKey);
+  }
+
+  @Override
+  public DefaultSensorDescriptor createIssuesForRuleRepositories(String... repositoryKeys) {
+    this.ruleRepositories = repositoryKeys;
+    return this;
+  }
+
+  @Override
+  public DefaultSensorDescriptor requireProperty(String... propertyKey) {
+    return requireProperties(propertyKey);
+  }
+
+  @Override
+  public DefaultSensorDescriptor requireProperties(String... propertyKeys) {
+    this.configurationPredicate = config -> asList(propertyKeys).stream().allMatch(config::hasKey);
+    return this;
+  }
+
+  @Override
+  public SensorDescriptor global() {
+    this.global = true;
+    return this;
+  }
+
+  @Override
+  public SensorDescriptor onlyWhenConfiguration(Predicate<Configuration> configurationPredicate) {
+    this.configurationPredicate = configurationPredicate;
+    return this;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/DefaultStorable.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/DefaultStorable.java
new file mode 100644 (file)
index 0000000..822ffbc
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.internal;
+
+import javax.annotation.Nullable;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public abstract class DefaultStorable {
+
+  protected final transient SensorStorage storage;
+  private transient boolean saved = false;
+
+  public DefaultStorable() {
+    this.storage = null;
+  }
+
+  public DefaultStorable(@Nullable SensorStorage storage) {
+    this.storage = storage;
+  }
+
+  public final void save() {
+    requireNonNull(this.storage, "No persister on this object");
+    checkState(!saved, "This object was already saved");
+    doSave();
+    this.saved = true;
+  }
+
+  protected abstract void doSave();
+
+  @Override
+  public String toString() {
+    return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorage.java
new file mode 100644 (file)
index 0000000..1d894ae
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.sonar.api.batch.sensor.code.NewSignificantCode;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
+import org.sonar.api.batch.sensor.coverage.NewCoverage;
+import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
+import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
+import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
+import org.sonar.api.batch.sensor.error.AnalysisError;
+import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
+import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
+import org.sonar.api.batch.sensor.issue.ExternalIssue;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.rule.AdHocRule;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
+import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
+
+import static org.sonar.api.utils.Preconditions.checkArgument;
+
+class InMemorySensorStorage implements SensorStorage {
+
+  Map<String, Map<String, Measure>> measuresByComponentAndMetric = new HashMap<>();
+
+  Collection<Issue> allIssues = new ArrayList<>();
+  Collection<ExternalIssue> allExternalIssues = new ArrayList<>();
+  Collection<AdHocRule> allAdHocRules = new ArrayList<>();
+  Collection<AnalysisError> allAnalysisErrors = new ArrayList<>();
+
+  Map<String, NewHighlighting> highlightingByComponent = new HashMap<>();
+  Map<String, DefaultCpdTokens> cpdTokensByComponent = new HashMap<>();
+  Map<String, List<DefaultCoverage>> coverageByComponent = new HashMap<>();
+  Map<String, DefaultSymbolTable> symbolsPerComponent = new HashMap<>();
+  Map<String, String> contextProperties = new HashMap<>();
+  Map<String, DefaultSignificantCode> significantCodePerComponent = new HashMap<>();
+
+  @Override
+  public void store(Measure measure) {
+    // Emulate duplicate measure check
+    String componentKey = measure.inputComponent().key();
+    String metricKey = measure.metric().key();
+    if (measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).containsKey(metricKey)) {
+      throw new IllegalStateException("Can not add the same measure twice");
+    }
+    measuresByComponentAndMetric.computeIfAbsent(componentKey, x -> new HashMap<>()).put(metricKey, measure);
+  }
+
+  @Override
+  public void store(Issue issue) {
+    allIssues.add(issue);
+  }
+
+  @Override
+  public void store(AdHocRule adHocRule) {
+    allAdHocRules.add(adHocRule);
+  }
+
+  @Override
+  public void store(NewHighlighting newHighlighting) {
+    DefaultHighlighting highlighting = (DefaultHighlighting) newHighlighting;
+    String fileKey = highlighting.inputFile().key();
+    // Emulate duplicate storage check
+    if (highlightingByComponent.containsKey(fileKey)) {
+      throw new UnsupportedOperationException("Trying to save highlighting twice for the same file is not supported: " + highlighting.inputFile());
+    }
+    highlightingByComponent.put(fileKey, highlighting);
+  }
+
+  @Override
+  public void store(NewCoverage coverage) {
+    DefaultCoverage defaultCoverage = (DefaultCoverage) coverage;
+    String fileKey = defaultCoverage.inputFile().key();
+    coverageByComponent.computeIfAbsent(fileKey, x -> new ArrayList<>()).add(defaultCoverage);
+  }
+
+  @Override
+  public void store(NewCpdTokens cpdTokens) {
+    DefaultCpdTokens defaultCpdTokens = (DefaultCpdTokens) cpdTokens;
+    String fileKey = defaultCpdTokens.inputFile().key();
+    // Emulate duplicate storage check
+    if (cpdTokensByComponent.containsKey(fileKey)) {
+      throw new UnsupportedOperationException("Trying to save CPD tokens twice for the same file is not supported: " + defaultCpdTokens.inputFile());
+    }
+    cpdTokensByComponent.put(fileKey, defaultCpdTokens);
+  }
+
+  @Override
+  public void store(NewSymbolTable newSymbolTable) {
+    DefaultSymbolTable symbolTable = (DefaultSymbolTable) newSymbolTable;
+    String fileKey = symbolTable.inputFile().key();
+    // Emulate duplicate storage check
+    if (symbolsPerComponent.containsKey(fileKey)) {
+      throw new UnsupportedOperationException("Trying to save symbol table twice for the same file is not supported: " + symbolTable.inputFile());
+    }
+    symbolsPerComponent.put(fileKey, symbolTable);
+  }
+
+  @Override
+  public void store(AnalysisError analysisError) {
+    allAnalysisErrors.add(analysisError);
+  }
+
+  @Override
+  public void storeProperty(String key, String value) {
+    checkArgument(key != null, "Key of context property must not be null");
+    checkArgument(value != null, "Value of context property must not be null");
+    contextProperties.put(key, value);
+  }
+
+  @Override
+  public void store(ExternalIssue issue) {
+    allExternalIssues.add(issue);
+  }
+
+  @Override
+  public void store(NewSignificantCode newSignificantCode) {
+    DefaultSignificantCode significantCode = (DefaultSignificantCode) newSignificantCode;
+    String fileKey = significantCode.inputFile().key();
+    // Emulate duplicate storage check
+    if (significantCodePerComponent.containsKey(fileKey)) {
+      throw new UnsupportedOperationException("Trying to save significant code information twice for the same file is not supported: " + significantCode.inputFile());
+    }
+    significantCodePerComponent.put(fileKey, significantCode);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
new file mode 100644 (file)
index 0000000..2b062e3
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.internal;
+
+import java.io.File;
+import java.io.Serializable;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Stream;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.SonarQubeSide;
+import org.sonar.api.SonarRuntime;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputModule;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.code.NewSignificantCode;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
+import org.sonar.api.batch.sensor.coverage.NewCoverage;
+import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
+import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
+import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
+import org.sonar.api.batch.sensor.cpd.internal.TokensLine;
+import org.sonar.api.batch.sensor.error.AnalysisError;
+import org.sonar.api.batch.sensor.error.NewAnalysisError;
+import org.sonar.api.batch.sensor.error.internal.DefaultAnalysisError;
+import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
+import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
+import org.sonar.api.batch.sensor.issue.ExternalIssue;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.NewExternalIssue;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.batch.sensor.rule.AdHocRule;
+import org.sonar.api.batch.sensor.rule.NewAdHocRule;
+import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
+import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.config.Settings;
+import org.sonar.api.config.internal.ConfigurationBridge;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.internal.MetadataLoader;
+import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.scanner.fs.InputProject;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.Version;
+
+import static java.util.Collections.unmodifiableMap;
+
+/**
+ * Utility class to help testing {@link Sensor}. This is not an API and method signature may evolve.
+ * <p>
+ * Usage: call {@link #create(File)} to create an "in memory" implementation of {@link SensorContext} with a filesystem initialized with provided baseDir.
+ * <p>
+ * You have to manually register inputFiles using:
+ * <pre>
+ *   sensorContextTester.fileSystem().add(new DefaultInputFile("myProjectKey", "src/Foo.java")
+ * .setLanguage("java")
+ * .initMetadata("public class Foo {\n}"));
+ * </pre>
+ * <p>
+ * Then pass it to your {@link Sensor}. You can then query elements provided by your sensor using methods {@link #allIssues()}, ...
+ */
+public class SensorContextTester implements SensorContext {
+
+  private Settings settings;
+  private DefaultFileSystem fs;
+  private ActiveRules activeRules;
+  private InMemorySensorStorage sensorStorage;
+  private DefaultInputProject project;
+  private DefaultInputModule module;
+  private SonarRuntime runtime;
+  private boolean cancelled;
+
+  private SensorContextTester(Path moduleBaseDir) {
+    this.settings = new MapSettings();
+    this.fs = new DefaultFileSystem(moduleBaseDir).setEncoding(Charset.defaultCharset());
+    this.activeRules = new ActiveRulesBuilder().build();
+    this.sensorStorage = new InMemorySensorStorage();
+    this.project = new DefaultInputProject(ProjectDefinition.create().setKey("projectKey").setBaseDir(moduleBaseDir.toFile()).setWorkDir(moduleBaseDir.resolve(".sonar").toFile()));
+    this.module = new DefaultInputModule(ProjectDefinition.create().setKey("projectKey").setBaseDir(moduleBaseDir.toFile()).setWorkDir(moduleBaseDir.resolve(".sonar").toFile()));
+    this.runtime = SonarRuntimeImpl.forSonarQube(MetadataLoader.loadVersion(System2.INSTANCE), SonarQubeSide.SCANNER, MetadataLoader.loadEdition(System2.INSTANCE));
+  }
+
+  public static SensorContextTester create(File moduleBaseDir) {
+    return new SensorContextTester(moduleBaseDir.toPath());
+  }
+
+  public static SensorContextTester create(Path moduleBaseDir) {
+    return new SensorContextTester(moduleBaseDir);
+  }
+
+  @Override
+  public Settings settings() {
+    return settings;
+  }
+
+  @Override
+  public Configuration config() {
+    return new ConfigurationBridge(settings);
+  }
+
+  public SensorContextTester setSettings(Settings settings) {
+    this.settings = settings;
+    return this;
+  }
+
+  @Override
+  public DefaultFileSystem fileSystem() {
+    return fs;
+  }
+
+  public SensorContextTester setFileSystem(DefaultFileSystem fs) {
+    this.fs = fs;
+    return this;
+  }
+
+  @Override
+  public ActiveRules activeRules() {
+    return activeRules;
+  }
+
+  public SensorContextTester setActiveRules(ActiveRules activeRules) {
+    this.activeRules = activeRules;
+    return this;
+  }
+
+  /**
+   * Default value is the version of this API at compilation time. You can override it
+   * using {@link #setRuntime(SonarRuntime)} to test your Sensor behaviour.
+   */
+  @Override
+  public Version getSonarQubeVersion() {
+    return runtime().getApiVersion();
+  }
+
+  /**
+   * @see #setRuntime(SonarRuntime) to override defaults (SonarQube scanner with version
+   * of this API as used at compilation time).
+   */
+  @Override
+  public SonarRuntime runtime() {
+    return runtime;
+  }
+
+  public SensorContextTester setRuntime(SonarRuntime runtime) {
+    this.runtime = runtime;
+    return this;
+  }
+
+  @Override
+  public boolean isCancelled() {
+    return cancelled;
+  }
+
+  public void setCancelled(boolean cancelled) {
+    this.cancelled = cancelled;
+  }
+
+  @Override
+  public InputModule module() {
+    return module;
+  }
+
+  @Override
+  public InputProject project() {
+    return project;
+  }
+
+  @Override
+  public <G extends Serializable> NewMeasure<G> newMeasure() {
+    return new DefaultMeasure<>(sensorStorage);
+  }
+
+  public Collection<Measure> measures(String componentKey) {
+    return sensorStorage.measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).values();
+  }
+
+  public <G extends Serializable> Measure<G> measure(String componentKey, Metric<G> metric) {
+    return measure(componentKey, metric.key());
+  }
+
+  public <G extends Serializable> Measure<G> measure(String componentKey, String metricKey) {
+    return sensorStorage.measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).get(metricKey);
+  }
+
+  @Override
+  public NewIssue newIssue() {
+    return new DefaultIssue(project, sensorStorage);
+  }
+
+  public Collection<Issue> allIssues() {
+    return sensorStorage.allIssues;
+  }
+
+  @Override
+  public NewExternalIssue newExternalIssue() {
+    return new DefaultExternalIssue(project, sensorStorage);
+  }
+
+  @Override
+  public NewAdHocRule newAdHocRule() {
+    return new DefaultAdHocRule(sensorStorage);
+  }
+
+  public Collection<ExternalIssue> allExternalIssues() {
+    return sensorStorage.allExternalIssues;
+  }
+
+  public Collection<AdHocRule> allAdHocRules() {
+    return sensorStorage.allAdHocRules;
+  }
+
+  public Collection<AnalysisError> allAnalysisErrors() {
+    return sensorStorage.allAnalysisErrors;
+  }
+
+  @CheckForNull
+  public Integer lineHits(String fileKey, int line) {
+    return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
+      .map(c -> c.hitsByLine().get(line))
+      .flatMap(Stream::of)
+      .filter(Objects::nonNull)
+      .reduce(null, SensorContextTester::sumOrNull);
+  }
+
+  @CheckForNull
+  public static Integer sumOrNull(@Nullable Integer o1, @Nullable Integer o2) {
+    return o1 == null ? o2 : (o1 + o2);
+  }
+
+  @CheckForNull
+  public Integer conditions(String fileKey, int line) {
+    return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
+      .map(c -> c.conditionsByLine().get(line))
+      .flatMap(Stream::of)
+      .filter(Objects::nonNull)
+      .reduce(null, SensorContextTester::maxOrNull);
+  }
+
+  @CheckForNull
+  public Integer coveredConditions(String fileKey, int line) {
+    return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
+      .map(c -> c.coveredConditionsByLine().get(line))
+      .flatMap(Stream::of)
+      .filter(Objects::nonNull)
+      .reduce(null, SensorContextTester::maxOrNull);
+  }
+
+  @CheckForNull
+  public TextRange significantCodeTextRange(String fileKey, int line) {
+    if (sensorStorage.significantCodePerComponent.containsKey(fileKey)) {
+      return sensorStorage.significantCodePerComponent.get(fileKey)
+        .significantCodePerLine()
+        .get(line);
+    }
+    return null;
+
+  }
+
+  @CheckForNull
+  public static Integer maxOrNull(@Nullable Integer o1, @Nullable Integer o2) {
+    return o1 == null ? o2 : Math.max(o1, o2);
+  }
+
+  @CheckForNull
+  public List<TokensLine> cpdTokens(String componentKey) {
+    DefaultCpdTokens defaultCpdTokens = sensorStorage.cpdTokensByComponent.get(componentKey);
+    return defaultCpdTokens != null ? defaultCpdTokens.getTokenLines() : null;
+  }
+
+  @Override
+  public NewHighlighting newHighlighting() {
+    return new DefaultHighlighting(sensorStorage);
+  }
+
+  @Override
+  public NewCoverage newCoverage() {
+    return new DefaultCoverage(sensorStorage);
+  }
+
+  @Override
+  public NewCpdTokens newCpdTokens() {
+    return new DefaultCpdTokens(sensorStorage);
+  }
+
+  @Override
+  public NewSymbolTable newSymbolTable() {
+    return new DefaultSymbolTable(sensorStorage);
+  }
+
+  @Override
+  public NewAnalysisError newAnalysisError() {
+    return new DefaultAnalysisError(sensorStorage);
+  }
+
+  /**
+   * Return list of syntax highlighting applied for a given position in a file. The result is a list because in theory you
+   * can apply several styles to the same range.
+   *
+   * @param componentKey Key of the file like 'myProjectKey:src/foo.php'
+   * @param line         Line you want to query
+   * @param lineOffset   Offset you want to query.
+   * @return List of styles applied to this position or empty list if there is no highlighting at this position.
+   */
+  public List<TypeOfText> highlightingTypeAt(String componentKey, int line, int lineOffset) {
+    DefaultHighlighting syntaxHighlightingData = (DefaultHighlighting) sensorStorage.highlightingByComponent.get(componentKey);
+    if (syntaxHighlightingData == null) {
+      return Collections.emptyList();
+    }
+    List<TypeOfText> result = new ArrayList<>();
+    DefaultTextPointer location = new DefaultTextPointer(line, lineOffset);
+    for (SyntaxHighlightingRule sortedRule : syntaxHighlightingData.getSyntaxHighlightingRuleSet()) {
+      if (sortedRule.range().start().compareTo(location) <= 0 && sortedRule.range().end().compareTo(location) > 0) {
+        result.add(sortedRule.getTextType());
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Return list of symbol references ranges for the symbol at a given position in a file.
+   *
+   * @param componentKey Key of the file like 'myProjectKey:src/foo.php'
+   * @param line         Line you want to query
+   * @param lineOffset   Offset you want to query.
+   * @return List of references for the symbol (potentially empty) or null if there is no symbol at this position.
+   */
+  @CheckForNull
+  public Collection<TextRange> referencesForSymbolAt(String componentKey, int line, int lineOffset) {
+    DefaultSymbolTable symbolTable = sensorStorage.symbolsPerComponent.get(componentKey);
+    if (symbolTable == null) {
+      return null;
+    }
+    DefaultTextPointer location = new DefaultTextPointer(line, lineOffset);
+    for (Map.Entry<TextRange, Set<TextRange>> symbol : symbolTable.getReferencesBySymbol().entrySet()) {
+      if (symbol.getKey().start().compareTo(location) <= 0 && symbol.getKey().end().compareTo(location) > 0) {
+        return symbol.getValue();
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void addContextProperty(String key, String value) {
+    sensorStorage.storeProperty(key, value);
+  }
+
+  /**
+   * @return an immutable map of the context properties defined with {@link SensorContext#addContextProperty(String, String)}.
+   * @since 6.1
+   */
+  public Map<String, String> getContextProperties() {
+    return unmodifiableMap(sensorStorage.contextProperties);
+  }
+
+  @Override
+  public void markForPublishing(InputFile inputFile) {
+    DefaultInputFile file = (DefaultInputFile) inputFile;
+    file.setPublished(true);
+  }
+
+  @Override
+  public NewSignificantCode newSignificantCode() {
+    return new DefaultSignificantCode(sensorStorage);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/package-info.java
new file mode 100644 (file)
index 0000000..ff282eb
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java
new file mode 100644 (file)
index 0000000..700b520
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.Issue.Flow;
+import org.sonar.api.batch.sensor.issue.IssueLocation;
+import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.utils.PathUtils;
+
+import static java.util.Collections.unmodifiableList;
+import static java.util.stream.Collectors.toList;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> extends DefaultStorable {
+  protected IssueLocation primaryLocation;
+  protected List<List<IssueLocation>> flows = new ArrayList<>();
+  protected DefaultInputProject project;
+
+  protected AbstractDefaultIssue(DefaultInputProject project) {
+    this(project, null);
+  }
+
+  public AbstractDefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
+    super(storage);
+    this.project = project;
+  }
+
+  public IssueLocation primaryLocation() {
+    return primaryLocation;
+  }
+
+  public List<Flow> flows() {
+    return this.flows.stream()
+      .<Flow>map(l -> () -> unmodifiableList(new ArrayList<>(l)))
+      .collect(toList());
+  }
+
+  public NewIssueLocation newLocation() {
+    return new DefaultIssueLocation();
+  }
+
+  public T at(NewIssueLocation primaryLocation) {
+    checkArgument(primaryLocation != null, "Cannot use a location that is null");
+    checkState(this.primaryLocation == null, "at() already called");
+    this.primaryLocation = rewriteLocation((DefaultIssueLocation) primaryLocation);
+    checkArgument(this.primaryLocation.inputComponent() != null, "Cannot use a location with no input component");
+    return (T) this;
+  }
+
+  public T addLocation(NewIssueLocation secondaryLocation) {
+    flows.add(Collections.singletonList(rewriteLocation((DefaultIssueLocation) secondaryLocation)));
+    return (T) this;
+  }
+
+  public T addFlow(Iterable<NewIssueLocation> locations) {
+    List<IssueLocation> flowAsList = new ArrayList<>();
+    for (NewIssueLocation issueLocation : locations) {
+      flowAsList.add(rewriteLocation((DefaultIssueLocation) issueLocation));
+    }
+    flows.add(flowAsList);
+    return (T) this;
+  }
+
+  private DefaultIssueLocation rewriteLocation(DefaultIssueLocation location) {
+    InputComponent component = location.inputComponent();
+    Optional<Path> dirOrModulePath = Optional.empty();
+
+    if (component instanceof DefaultInputDir) {
+      DefaultInputDir dirComponent = (DefaultInputDir) component;
+      dirOrModulePath = Optional.of(project.getBaseDir().relativize(dirComponent.path()));
+    } else if (component instanceof DefaultInputModule && !Objects.equals(project.key(), component.key())) {
+      DefaultInputModule moduleComponent = (DefaultInputModule) component;
+      dirOrModulePath = Optional.of(project.getBaseDir().relativize(moduleComponent.getBaseDir()));
+    }
+
+    if (dirOrModulePath.isPresent()) {
+      String path = PathUtils.sanitize(dirOrModulePath.get().toString());
+      DefaultIssueLocation fixedLocation = new DefaultIssueLocation();
+      fixedLocation.on(project);
+      StringBuilder fullMessage = new StringBuilder();
+      if (path != null && !path.isEmpty()) {
+        fullMessage.append("[").append(path).append("] ");
+      }
+      fullMessage.append(location.message());
+      fixedLocation.message(fullMessage.toString());
+      return fixedLocation;
+    } else {
+      return location;
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java
new file mode 100644 (file)
index 0000000..7b7a3a8
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import javax.annotation.Nullable;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.ExternalIssue;
+import org.sonar.api.batch.sensor.issue.NewExternalIssue;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RuleType;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIssue> implements ExternalIssue, NewExternalIssue {
+  private Long effort;
+  private Severity severity;
+  private RuleType type;
+  private String engineId;
+  private String ruleId;
+
+  public DefaultExternalIssue(DefaultInputProject project) {
+    this(project, null);
+  }
+
+  public DefaultExternalIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
+    super(project, storage);
+  }
+
+  @Override
+  public DefaultExternalIssue remediationEffortMinutes(@Nullable Long effort) {
+    checkArgument(effort == null || effort >= 0, format("effort must be greater than or equal 0 (got %s)", effort));
+    this.effort = effort;
+    return this;
+  }
+
+  @Override
+  public DefaultExternalIssue severity(Severity severity) {
+    this.severity = severity;
+    return this;
+  }
+
+  @Override
+  public String engineId() {
+    return engineId;
+  }
+
+  @Override
+  public String ruleId() {
+    return ruleId;
+  }
+
+  @Override
+  public Severity severity() {
+    return this.severity;
+  }
+
+  @Override
+  public Long remediationEffort() {
+    return this.effort;
+  }
+
+  @Override
+  public void doSave() {
+    requireNonNull(this.engineId, "Engine id is mandatory on external issue");
+    requireNonNull(this.ruleId, "Rule id is mandatory on external issue");
+    checkState(primaryLocation != null, "Primary location is mandatory on every external issue");
+    checkState(primaryLocation.inputComponent().isFile(), "External issues must be located in files");
+    checkState(primaryLocation.message() != null, "External issues must have a message");
+    checkState(severity != null, "Severity is mandatory on every external issue");
+    checkState(type != null, "Type is mandatory on every external issue");
+    storage.store(this);
+  }
+
+  @Override
+  public RuleType type() {
+    return type;
+  }
+
+  @Override
+  public NewExternalIssue engineId(String engineId) {
+    this.engineId = engineId;
+    return this;
+  }
+
+  @Override
+  public NewExternalIssue ruleId(String ruleId) {
+    this.ruleId = ruleId;
+    return this;
+  }
+
+  @Override
+  public DefaultExternalIssue forRule(RuleKey ruleKey) {
+    this.engineId = ruleKey.repository();
+    this.ruleId = ruleKey.rule();
+    return this;
+  }
+
+  @Override
+  public RuleKey ruleKey() {
+    if (engineId != null && ruleId != null) {
+      return RuleKey.of(RuleKey.EXTERNAL_RULE_REPO_PREFIX + engineId, ruleId);
+    }
+    return null;
+  }
+
+  @Override
+  public DefaultExternalIssue type(RuleType type) {
+    this.type = type;
+    return this;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
new file mode 100644 (file)
index 0000000..142c3e0
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import javax.annotation.Nullable;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.IssueLocation;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.rule.RuleKey;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements Issue, NewIssue {
+  private RuleKey ruleKey;
+  private Double gap;
+  private Severity overriddenSeverity;
+
+  public DefaultIssue(DefaultInputProject project) {
+    this(project, null);
+  }
+
+  public DefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
+    super(project, storage);
+  }
+
+  public DefaultIssue forRule(RuleKey ruleKey) {
+    this.ruleKey = ruleKey;
+    return this;
+  }
+
+  public RuleKey ruleKey() {
+    return this.ruleKey;
+  }
+
+  @Override
+  public DefaultIssue gap(@Nullable Double gap) {
+    checkArgument(gap == null || gap >= 0, format("Gap must be greater than or equal 0 (got %s)", gap));
+    this.gap = gap;
+    return this;
+  }
+
+  @Override
+  public DefaultIssue overrideSeverity(@Nullable Severity severity) {
+    this.overriddenSeverity = severity;
+    return this;
+  }
+
+  @Override
+  public Severity overriddenSeverity() {
+    return this.overriddenSeverity;
+  }
+
+  @Override
+  public Double gap() {
+    return this.gap;
+  }
+
+  @Override
+  public IssueLocation primaryLocation() {
+    return primaryLocation;
+  }
+
+  @Override
+  public void doSave() {
+    requireNonNull(this.ruleKey, "ruleKey is mandatory on issue");
+    checkState(primaryLocation != null, "Primary location is mandatory on every issue");
+    storage.store(this);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java
new file mode 100644 (file)
index 0000000..970b38b
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.issue.IssueLocation;
+import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.lang.StringUtils.abbreviate;
+import static org.apache.commons.lang.StringUtils.trim;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultIssueLocation implements NewIssueLocation, IssueLocation {
+
+  private InputComponent component;
+  private TextRange textRange;
+  private String message;
+
+  @Override
+  public DefaultIssueLocation on(InputComponent component) {
+    checkArgument(component != null, "Component can't be null");
+    checkState(this.component == null, "on() already called");
+    this.component = component;
+    return this;
+  }
+
+  @Override
+  public DefaultIssueLocation at(TextRange location) {
+    checkState(this.component != null, "at() should be called after on()");
+    checkState(this.component.isFile(), "at() should be called only for an InputFile.");
+    DefaultInputFile file = (DefaultInputFile) this.component;
+    file.validate(location);
+    this.textRange = location;
+    return this;
+  }
+
+  @Override
+  public DefaultIssueLocation message(String message) {
+    requireNonNull(message, "Message can't be null");
+    if (message.contains("\u0000")) {
+      throw new IllegalArgumentException(unsupportedCharacterError(message, component));
+    }
+    this.message = abbreviate(trim(message), MESSAGE_MAX_SIZE);
+    return this;
+  }
+
+  private static String unsupportedCharacterError(String message, @Nullable InputComponent component) {
+    String error = "Character \\u0000 is not supported in issue message '" + message + "'";
+    if (component != null) {
+      error += ", on component: " + component.toString();
+    }
+    return error;
+  }
+
+  @Override
+  public InputComponent inputComponent() {
+    return this.component;
+  }
+
+  @Override
+  public TextRange textRange() {
+    return textRange;
+  }
+
+  @Override
+  public String message() {
+    return this.message;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultNoSonarFilter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultNoSonarFilter.java
new file mode 100644 (file)
index 0000000..bace869
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import java.util.Set;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.issue.NoSonarFilter;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+
+public class DefaultNoSonarFilter extends NoSonarFilter {
+  public NoSonarFilter noSonarInFile(InputFile inputFile, Set<Integer> noSonarLines) {
+    ((DefaultInputFile) inputFile).noSonarAt(noSonarLines);
+    return this;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/package-info.java
new file mode 100644 (file)
index 0000000..3abee25
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.issue.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java
new file mode 100644 (file)
index 0000000..b359e2d
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.measure.internal;
+
+import java.io.Serializable;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.measure.Metric;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
+
+  private InputComponent component;
+  private Metric<G> metric;
+  private G value;
+  private boolean fromCore = false;
+
+  public DefaultMeasure() {
+    super();
+  }
+
+  public DefaultMeasure(@Nullable SensorStorage storage) {
+    super(storage);
+  }
+
+  @Override
+  public DefaultMeasure<G> on(InputComponent component) {
+    checkArgument(component != null, "Component can't be null");
+    checkState(this.component == null, "on() already called");
+    this.component = component;
+    return this;
+  }
+
+  @Override
+  public DefaultMeasure<G> forMetric(Metric<G> metric) {
+    checkState(this.metric == null, "Metric already defined");
+    requireNonNull(metric, "metric should be non null");
+    this.metric = metric;
+    return this;
+  }
+
+  @Override
+  public DefaultMeasure<G> withValue(G value) {
+    checkState(this.value == null, "Measure value already defined");
+    requireNonNull(value, "Measure value can't be null");
+    this.value = value;
+    return this;
+  }
+
+  /**
+   * For internal use.
+   */
+  public boolean isFromCore() {
+    return fromCore;
+  }
+
+  /**
+   * For internal use. Used by core components to bypass check that prevent a plugin to store core measures.
+   */
+  public DefaultMeasure<G> setFromCore() {
+    this.fromCore = true;
+    return this;
+  }
+
+  @Override
+  public void doSave() {
+    requireNonNull(this.value, "Measure value can't be null");
+    requireNonNull(this.metric, "Measure metric can't be null");
+    checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type %s", this.metric.valueType());
+    storage.store(this);
+  }
+
+  @Override
+  public Metric<G> metric() {
+    return metric;
+  }
+
+  @Override
+  public InputComponent inputComponent() {
+    return component;
+  }
+
+  @Override
+  public G value() {
+    return value;
+  }
+
+  // For testing purpose
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj == null) {
+      return false;
+    }
+    if (obj == this) {
+      return true;
+    }
+    if (obj.getClass() != getClass()) {
+      return false;
+    }
+    DefaultMeasure<?> rhs = (DefaultMeasure<?>) obj;
+    return new EqualsBuilder()
+      .append(component, rhs.component)
+      .append(metric, rhs.metric)
+      .append(value, rhs.value)
+      .isEquals();
+  }
+
+  @Override
+  public int hashCode() {
+    return new HashCodeBuilder(27, 45).append(component).append(metric).append(value).toHashCode();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/measure/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/measure/internal/package-info.java
new file mode 100644 (file)
index 0000000..5f4790b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.measure.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/rule/internal/DefaultAdHocRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/rule/internal/DefaultAdHocRule.java
new file mode 100644 (file)
index 0000000..7ccf8ae
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.rule.internal;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.rule.AdHocRule;
+import org.sonar.api.batch.sensor.rule.NewAdHocRule;
+import org.sonar.api.rules.RuleType;
+
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultAdHocRule extends DefaultStorable implements AdHocRule, NewAdHocRule {
+  private Severity severity;
+  private RuleType type;
+  private String name;
+  private String description;
+  private String engineId;
+  private String ruleId;
+
+  public DefaultAdHocRule() {
+    super(null);
+  }
+
+  public DefaultAdHocRule(@Nullable SensorStorage storage) {
+    super(storage);
+  }
+
+  @Override
+  public DefaultAdHocRule severity(Severity severity) {
+    this.severity = severity;
+    return this;
+  }
+
+  @Override
+  public String engineId() {
+    return engineId;
+  }
+
+  @Override
+  public String ruleId() {
+    return ruleId;
+  }
+
+  @Override
+  public String name() {
+    return name;
+  }
+
+  @CheckForNull
+  @Override
+  public String description() {
+    return description;
+  }
+
+  @Override
+  public Severity severity() {
+    return this.severity;
+  }
+
+  @Override
+  public void doSave() {
+    checkState(isNotBlank(engineId), "Engine id is mandatory on ad hoc rule");
+    checkState(isNotBlank(ruleId), "Rule id is mandatory on ad hoc rule");
+    checkState(isNotBlank(name), "Name is mandatory on every ad hoc rule");
+    checkState(severity != null, "Severity is mandatory on every ad hoc rule");
+    checkState(type != null, "Type is mandatory on every ad hoc rule");
+    storage.store(this);
+  }
+
+  @Override
+  public RuleType type() {
+    return type;
+  }
+
+  @Override
+  public DefaultAdHocRule engineId(String engineId) {
+    this.engineId = engineId;
+    return this;
+  }
+
+  @Override
+  public DefaultAdHocRule ruleId(String ruleId) {
+    this.ruleId = ruleId;
+    return this;
+  }
+
+  @Override
+  public DefaultAdHocRule name(String name) {
+    this.name = name;
+    return this;
+  }
+
+  @Override
+  public DefaultAdHocRule description(@Nullable String description) {
+    this.description = description;
+    return this;
+  }
+
+  @Override
+  public DefaultAdHocRule type(RuleType type) {
+    this.type = type;
+    return this;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/rule/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/rule/internal/package-info.java
new file mode 100644 (file)
index 0000000..26995ef
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.rule.internal;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTable.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTable.java
new file mode 100644 (file)
index 0000000..087681a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.symbol.internal;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.symbol.NewSymbol;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultSymbolTable extends DefaultStorable implements NewSymbolTable {
+
+  private final Map<TextRange, Set<TextRange>> referencesBySymbol;
+  private DefaultInputFile inputFile;
+
+  public DefaultSymbolTable(SensorStorage storage) {
+    super(storage);
+    referencesBySymbol = new LinkedHashMap<>();
+  }
+
+  public Map<TextRange, Set<TextRange>> getReferencesBySymbol() {
+    return referencesBySymbol;
+  }
+
+  @Override
+  public DefaultSymbolTable onFile(InputFile inputFile) {
+    requireNonNull(inputFile, "file can't be null");
+    this.inputFile = (DefaultInputFile) inputFile;
+    return this;
+  }
+
+  public InputFile inputFile() {
+    return inputFile;
+  }
+
+  @Override
+  public NewSymbol newSymbol(int startLine, int startLineOffset, int endLine, int endLineOffset) {
+    checkInputFileNotNull();
+    TextRange declarationRange;
+    try {
+      declarationRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
+    } catch (Exception e) {
+      throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
+    }
+    return newSymbol(declarationRange);
+  }
+
+  @Override
+  public NewSymbol newSymbol(int startOffset, int endOffset) {
+    checkInputFileNotNull();
+    TextRange declarationRange;
+    try {
+      declarationRange = inputFile.newRange(startOffset, endOffset);
+    } catch (Exception e) {
+      throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
+    }
+    return newSymbol(declarationRange);
+  }
+
+  @Override
+  public NewSymbol newSymbol(TextRange range) {
+    checkInputFileNotNull();
+    TreeSet<TextRange> references = new TreeSet<>((o1, o2) -> o1.start().compareTo(o2.start()));
+    referencesBySymbol.put(range, references);
+    return new DefaultSymbol(inputFile, range, references);
+  }
+
+  private static class DefaultSymbol implements NewSymbol {
+
+    private final Collection<TextRange> references;
+    private final DefaultInputFile inputFile;
+    private final TextRange declaration;
+
+    public DefaultSymbol(DefaultInputFile inputFile, TextRange declaration, Collection<TextRange> references) {
+      this.inputFile = inputFile;
+      this.declaration = declaration;
+      this.references = references;
+    }
+
+    @Override
+    public NewSymbol newReference(int startOffset, int endOffset) {
+      TextRange referenceRange;
+      try {
+        referenceRange = inputFile.newRange(startOffset, endOffset);
+      } catch (Exception e) {
+        throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
+      }
+      return newReference(referenceRange);
+    }
+
+    @Override
+    public NewSymbol newReference(int startLine, int startLineOffset, int endLine, int endLineOffset) {
+      TextRange referenceRange;
+      try {
+        referenceRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
+      } catch (Exception e) {
+        throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
+      }
+      return newReference(referenceRange);
+    }
+
+    @Override
+    public NewSymbol newReference(TextRange range) {
+      requireNonNull(range, "Provided range is null");
+      checkArgument(!declaration.overlap(range), "Overlapping symbol declaration and reference for symbol at %s", declaration);
+      references.add(range);
+      return this;
+    }
+
+  }
+
+  @Override
+  protected void doSave() {
+    checkInputFileNotNull();
+    storage.store(this);
+  }
+
+  private void checkInputFileNotNull() {
+    checkState(inputFile != null, "Call onFile() first");
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/symbol/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/symbol/internal/package-info.java
new file mode 100644 (file)
index 0000000..e8dcd39
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.api.batch.sensor.symbol.internal;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java
new file mode 100644 (file)
index 0000000..5455cf0
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.config.internal;
+
+import java.util.Optional;
+import org.sonar.api.config.Settings;
+import org.sonar.api.config.Configuration;
+
+/**
+ * Used to help migration from {@link Settings} to {@link Configuration}
+ */
+public class ConfigurationBridge implements Configuration {
+
+  private final Settings settings;
+
+  public ConfigurationBridge(Settings settings) {
+    this.settings = settings;
+  }
+
+  @Override
+  public Optional<String> get(String key) {
+    return Optional.ofNullable(settings.getString(key));
+  }
+
+  @Override
+  public boolean hasKey(String key) {
+    return settings.hasKey(key);
+  }
+
+  @Override
+  public String[] getStringArray(String key) {
+    return settings.getStringArray(key);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/MapSettings.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/MapSettings.java
new file mode 100644 (file)
index 0000000..5d07d60
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.config.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.config.Encryption;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+
+import static java.util.Collections.unmodifiableMap;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * In-memory map-based implementation of {@link Settings}. It must be used
+ * <b>only for unit tests</b>. This is not the implementation
+ * deployed at runtime, so non-test code must never cast
+ * {@link Settings} to {@link MapSettings}.
+ *
+ * @since 6.1
+ */
+public class MapSettings extends Settings {
+
+  private final Map<String, String> props = new HashMap<>();
+  private final ConfigurationBridge configurationBridge;
+
+  public MapSettings() {
+    this(new PropertyDefinitions());
+  }
+
+  public MapSettings(PropertyDefinitions definitions) {
+    super(definitions, new Encryption(null));
+    configurationBridge = new ConfigurationBridge(this);
+  }
+
+  @Override
+  protected Optional<String> get(String key) {
+    return Optional.ofNullable(props.get(key));
+  }
+
+  @Override
+  protected void set(String key, String value) {
+    props.put(
+      requireNonNull(key, "key can't be null"),
+      requireNonNull(value, "value can't be null").trim());
+  }
+
+  @Override
+  protected void remove(String key) {
+    props.remove(key);
+  }
+
+  @Override
+  public Map<String, String> getProperties() {
+    return unmodifiableMap(props);
+  }
+
+  /**
+   * Delete all properties
+   */
+  public MapSettings clear() {
+    props.clear();
+    return this;
+  }
+
+  @Override
+  public MapSettings setProperty(String key, String value) {
+    return (MapSettings) super.setProperty(key, value);
+  }
+
+  @Override
+  public MapSettings setProperty(String key, Integer value) {
+    return (MapSettings) super.setProperty(key, value);
+  }
+
+  @Override
+  public MapSettings setProperty(String key, Boolean value) {
+    return (MapSettings) super.setProperty(key, value);
+  }
+
+  @Override
+  public MapSettings setProperty(String key, Long value) {
+    return (MapSettings) super.setProperty(key, value);
+  }
+
+  /**
+   * @return a {@link Configuration} proxy on top of this existing {@link Settings} implementation. Changes are reflected in the {@link Configuration} object.
+   * @since 6.5
+   */
+  public Configuration asConfig() {
+    return configurationBridge;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java
new file mode 100644 (file)
index 0000000..dab98c5
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.config.internal;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Function;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVParser;
+import org.apache.commons.csv.CSVRecord;
+import org.apache.commons.lang.ArrayUtils;
+
+public class MultivalueProperty {
+  private MultivalueProperty() {
+    // prevents instantiation
+  }
+
+  public static String[] parseAsCsv(String key, String value) {
+    return parseAsCsv(key, value, Function.identity());
+  }
+
+  public static String[] parseAsCsv(String key, String value, Function<String, String> valueProcessor) {
+    String cleanValue = MultivalueProperty.trimFieldsAndRemoveEmptyFields(value);
+    List<String> result = new ArrayList<>();
+    try (CSVParser csvParser = CSVFormat.RFC4180
+      .withHeader((String) null)
+      .withIgnoreEmptyLines()
+      .withIgnoreSurroundingSpaces()
+      .parse(new StringReader(cleanValue))) {
+      List<CSVRecord> records = csvParser.getRecords();
+      if (records.isEmpty()) {
+        return ArrayUtils.EMPTY_STRING_ARRAY;
+      }
+      processRecords(result, records, valueProcessor);
+      return result.toArray(new String[result.size()]);
+    } catch (IOException e) {
+      throw new IllegalStateException("Property: '" + key + "' doesn't contain a valid CSV value: '" + value + "'", e);
+    }
+  }
+
+  /**
+   * In most cases we expect a single record. <br>Having multiple records means the input value was splitted over multiple lines (this is common in Maven).
+   * For example:
+   * <pre>
+   *   &lt;sonar.exclusions&gt;
+   *     src/foo,
+   *     src/bar,
+   *     src/biz
+   *   &lt;sonar.exclusions&gt;
+   * </pre>
+   * In this case records will be merged to form a single list of items. Last item of a record is appended to first item of next record.
+   * <p>
+   * This is a very curious case, but we try to preserve line break in the middle of an item:
+   * <pre>
+   *   &lt;sonar.exclusions&gt;
+   *     a
+   *     b,
+   *     c
+   *   &lt;sonar.exclusions&gt;
+   * </pre>
+   * will produce ['a\nb', 'c']
+   */
+  private static void processRecords(List<String> result, List<CSVRecord> records, Function<String, String> valueProcessor) {
+    for (CSVRecord csvRecord : records) {
+      Iterator<String> it = csvRecord.iterator();
+      if (!result.isEmpty()) {
+        String next = it.next();
+        if (!next.isEmpty()) {
+          int lastItemIdx = result.size() - 1;
+          String previous = result.get(lastItemIdx);
+          if (previous.isEmpty()) {
+            result.set(lastItemIdx, valueProcessor.apply(next));
+          } else {
+            result.set(lastItemIdx, valueProcessor.apply(previous + "\n" + next));
+          }
+        }
+      }
+      it.forEachRemaining(s -> {
+        String apply = valueProcessor.apply(s);
+        result.add(apply);
+      });
+    }
+  }
+
+  /**
+   * Removes the empty fields from the value of a multi-value property from empty fields, including trimming each field.
+   * <p>
+   * Quotes can be used to prevent an empty field to be removed (as it is used to preserve empty spaces).
+   * <ul>
+   *    <li>{@code "" => ""}</li>
+   *    <li>{@code " " => ""}</li>
+   *    <li>{@code "," => ""}</li>
+   *    <li>{@code ",," => ""}</li>
+   *    <li>{@code ",,," => ""}</li>
+   *    <li>{@code ",a" => "a"}</li>
+   *    <li>{@code "a," => "a"}</li>
+   *    <li>{@code ",a," => "a"}</li>
+   *    <li>{@code "a,,b" => "a,b"}</li>
+   *    <li>{@code "a,   ,b" => "a,b"}</li>
+   *    <li>{@code "a,\"\",b" => "a,b"}</li>
+   *    <li>{@code "\"a\",\"b\"" => "\"a\",\"b\""}</li>
+   *    <li>{@code "\"  a  \",\"b \"" => "\"  a  \",\"b \""}</li>
+   *    <li>{@code "\"a\",\"\",\"b\"" => "\"a\",\"\",\"b\""}</li>
+   *    <li>{@code "\"a\",\"  \",\"b\"" => "\"a\",\"  \",\"b\""}</li>
+   *    <li>{@code "\"  a,,b,c  \",\"d \"" => "\"  a,,b,c  \",\"d \""}</li>
+   *    <li>{@code "a,\"  \",b" => "ab"]}</li>
+   * </ul>
+   */
+  static String trimFieldsAndRemoveEmptyFields(String str) {
+    char[] chars = str.toCharArray();
+    char[] res = new char[chars.length];
+    /*
+     * set when reading the first non trimmable char after a separator char (or the beginning of the string)
+     * unset when reading a separator
+     */
+    boolean inField = false;
+    boolean inQuotes = false;
+    int i = 0;
+    int resI = 0;
+    for (; i < chars.length; i++) {
+      boolean isSeparator = chars[i] == ',';
+      if (!inQuotes && isSeparator) {
+        // exiting field (may already be unset)
+        inField = false;
+        if (resI > 0) {
+          resI = retroTrim(res, resI);
+        }
+      } else {
+        boolean isTrimmed = !inQuotes && istrimmable(chars[i]);
+        if (isTrimmed && !inField) {
+          // we haven't meet any non trimmable char since the last separator yet
+          continue;
+        }
+
+        boolean isEscape = isEscapeChar(chars[i]);
+        if (isEscape) {
+          inQuotes = !inQuotes;
+        }
+
+        // add separator as we already had one field
+        if (!inField && resI > 0) {
+          res[resI] = ',';
+          resI++;
+        }
+
+        // register in field (may already be set)
+        inField = true;
+        // copy current char
+        res[resI] = chars[i];
+        resI++;
+      }
+    }
+    // inQuotes can only be true at this point if quotes are unbalanced
+    if (!inQuotes) {
+      // trim end of str
+      resI = retroTrim(res, resI);
+    }
+    return new String(res, 0, resI);
+  }
+
+  private static boolean isEscapeChar(char aChar) {
+    return aChar == '"';
+  }
+
+  private static boolean istrimmable(char aChar) {
+    return aChar <= ' ';
+  }
+
+  /**
+   * Reads from index {@code resI} to the beginning into {@code res} looking up the location of the trimmable char with
+   * the lowest index before encountering a non-trimmable char.
+   * <p>
+   * This basically trims {@code res} from any trimmable char at its end.
+   *
+   * @return index of next location to put new char in res
+   */
+  private static int retroTrim(char[] res, int resI) {
+    int i = resI;
+    while (i >= 1) {
+      if (!istrimmable(res[i - 1])) {
+        return i;
+      }
+      i--;
+    }
+    return i;
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/package-info.java
new file mode 100644 (file)
index 0000000..f677479
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.config.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/ConfigurationBridge.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/ConfigurationBridge.java
deleted file mode 100644 (file)
index fea9800..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.config;
-
-import java.util.Optional;
-import org.sonar.api.config.Settings;
-import org.sonar.api.config.Configuration;
-
-/**
- * Used to help migration from {@link Settings} to {@link Configuration}
- */
-public class ConfigurationBridge implements Configuration {
-
-  private final Settings settings;
-
-  public ConfigurationBridge(Settings settings) {
-    this.settings = settings;
-  }
-
-  @Override
-  public Optional<String> get(String key) {
-    return Optional.ofNullable(settings.getString(key));
-  }
-
-  @Override
-  public boolean hasKey(String key) {
-    return settings.hasKey(key);
-  }
-
-  @Override
-  public String[] getStringArray(String key) {
-    return settings.getStringArray(key);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MapSettings.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MapSettings.java
deleted file mode 100644 (file)
index 61ac601..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.config;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.config.Encryption;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-
-import static java.util.Collections.unmodifiableMap;
-import static java.util.Objects.requireNonNull;
-
-/**
- * In-memory map-based implementation of {@link Settings}. It must be used
- * <b>only for unit tests</b>. This is not the implementation
- * deployed at runtime, so non-test code must never cast
- * {@link Settings} to {@link MapSettings}.
- *
- * @since 6.1
- */
-public class MapSettings extends Settings {
-
-  private final Map<String, String> props = new HashMap<>();
-  private final ConfigurationBridge configurationBridge;
-
-  public MapSettings() {
-    this(new PropertyDefinitions());
-  }
-
-  public MapSettings(PropertyDefinitions definitions) {
-    super(definitions, new Encryption(null));
-    configurationBridge = new ConfigurationBridge(this);
-  }
-
-  @Override
-  protected Optional<String> get(String key) {
-    return Optional.ofNullable(props.get(key));
-  }
-
-  @Override
-  protected void set(String key, String value) {
-    props.put(
-      requireNonNull(key, "key can't be null"),
-      requireNonNull(value, "value can't be null").trim());
-  }
-
-  @Override
-  protected void remove(String key) {
-    props.remove(key);
-  }
-
-  @Override
-  public Map<String, String> getProperties() {
-    return unmodifiableMap(props);
-  }
-
-  /**
-   * Delete all properties
-   */
-  public MapSettings clear() {
-    props.clear();
-    return this;
-  }
-
-  @Override
-  public MapSettings setProperty(String key, String value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  @Override
-  public MapSettings setProperty(String key, Integer value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  @Override
-  public MapSettings setProperty(String key, Boolean value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  @Override
-  public MapSettings setProperty(String key, Long value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  /**
-   * @return a {@link Configuration} proxy on top of this existing {@link Settings} implementation. Changes are reflected in the {@link Configuration} object.
-   * @since 6.5
-   */
-  public Configuration asConfig() {
-    return configurationBridge;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MultivalueProperty.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MultivalueProperty.java
deleted file mode 100644 (file)
index 3d7d9f0..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.config;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.function.Function;
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.apache.commons.csv.CSVRecord;
-import org.apache.commons.lang.ArrayUtils;
-
-public class MultivalueProperty {
-  private MultivalueProperty() {
-    // prevents instantiation
-  }
-
-  public static String[] parseAsCsv(String key, String value) {
-    return parseAsCsv(key, value, Function.identity());
-  }
-
-  public static String[] parseAsCsv(String key, String value, Function<String, String> valueProcessor) {
-    String cleanValue = MultivalueProperty.trimFieldsAndRemoveEmptyFields(value);
-    List<String> result = new ArrayList<>();
-    try (CSVParser csvParser = CSVFormat.RFC4180
-      .withHeader((String) null)
-      .withIgnoreEmptyLines()
-      .withIgnoreSurroundingSpaces()
-      .parse(new StringReader(cleanValue))) {
-      List<CSVRecord> records = csvParser.getRecords();
-      if (records.isEmpty()) {
-        return ArrayUtils.EMPTY_STRING_ARRAY;
-      }
-      processRecords(result, records, valueProcessor);
-      return result.toArray(new String[result.size()]);
-    } catch (IOException e) {
-      throw new IllegalStateException("Property: '" + key + "' doesn't contain a valid CSV value: '" + value + "'", e);
-    }
-  }
-
-  /**
-   * In most cases we expect a single record. <br>Having multiple records means the input value was splitted over multiple lines (this is common in Maven).
-   * For example:
-   * <pre>
-   *   &lt;sonar.exclusions&gt;
-   *     src/foo,
-   *     src/bar,
-   *     src/biz
-   *   &lt;sonar.exclusions&gt;
-   * </pre>
-   * In this case records will be merged to form a single list of items. Last item of a record is appended to first item of next record.
-   * <p>
-   * This is a very curious case, but we try to preserve line break in the middle of an item:
-   * <pre>
-   *   &lt;sonar.exclusions&gt;
-   *     a
-   *     b,
-   *     c
-   *   &lt;sonar.exclusions&gt;
-   * </pre>
-   * will produce ['a\nb', 'c']
-   */
-  private static void processRecords(List<String> result, List<CSVRecord> records, Function<String, String> valueProcessor) {
-    for (CSVRecord csvRecord : records) {
-      Iterator<String> it = csvRecord.iterator();
-      if (!result.isEmpty()) {
-        String next = it.next();
-        if (!next.isEmpty()) {
-          int lastItemIdx = result.size() - 1;
-          String previous = result.get(lastItemIdx);
-          if (previous.isEmpty()) {
-            result.set(lastItemIdx, valueProcessor.apply(next));
-          } else {
-            result.set(lastItemIdx, valueProcessor.apply(previous + "\n" + next));
-          }
-        }
-      }
-      it.forEachRemaining(s -> {
-        String apply = valueProcessor.apply(s);
-        result.add(apply);
-      });
-    }
-  }
-
-  /**
-   * Removes the empty fields from the value of a multi-value property from empty fields, including trimming each field.
-   * <p>
-   * Quotes can be used to prevent an empty field to be removed (as it is used to preserve empty spaces).
-   * <ul>
-   *    <li>{@code "" => ""}</li>
-   *    <li>{@code " " => ""}</li>
-   *    <li>{@code "," => ""}</li>
-   *    <li>{@code ",," => ""}</li>
-   *    <li>{@code ",,," => ""}</li>
-   *    <li>{@code ",a" => "a"}</li>
-   *    <li>{@code "a," => "a"}</li>
-   *    <li>{@code ",a," => "a"}</li>
-   *    <li>{@code "a,,b" => "a,b"}</li>
-   *    <li>{@code "a,   ,b" => "a,b"}</li>
-   *    <li>{@code "a,\"\",b" => "a,b"}</li>
-   *    <li>{@code "\"a\",\"b\"" => "\"a\",\"b\""}</li>
-   *    <li>{@code "\"  a  \",\"b \"" => "\"  a  \",\"b \""}</li>
-   *    <li>{@code "\"a\",\"\",\"b\"" => "\"a\",\"\",\"b\""}</li>
-   *    <li>{@code "\"a\",\"  \",\"b\"" => "\"a\",\"  \",\"b\""}</li>
-   *    <li>{@code "\"  a,,b,c  \",\"d \"" => "\"  a,,b,c  \",\"d \""}</li>
-   *    <li>{@code "a,\"  \",b" => "ab"]}</li>
-   * </ul>
-   */
-  static String trimFieldsAndRemoveEmptyFields(String str) {
-    char[] chars = str.toCharArray();
-    char[] res = new char[chars.length];
-    /*
-     * set when reading the first non trimmable char after a separator char (or the beginning of the string)
-     * unset when reading a separator
-     */
-    boolean inField = false;
-    boolean inQuotes = false;
-    int i = 0;
-    int resI = 0;
-    for (; i < chars.length; i++) {
-      boolean isSeparator = chars[i] == ',';
-      if (!inQuotes && isSeparator) {
-        // exiting field (may already be unset)
-        inField = false;
-        if (resI > 0) {
-          resI = retroTrim(res, resI);
-        }
-      } else {
-        boolean isTrimmed = !inQuotes && istrimmable(chars[i]);
-        if (isTrimmed && !inField) {
-          // we haven't meet any non trimmable char since the last separator yet
-          continue;
-        }
-
-        boolean isEscape = isEscapeChar(chars[i]);
-        if (isEscape) {
-          inQuotes = !inQuotes;
-        }
-
-        // add separator as we already had one field
-        if (!inField && resI > 0) {
-          res[resI] = ',';
-          resI++;
-        }
-
-        // register in field (may already be set)
-        inField = true;
-        // copy current char
-        res[resI] = chars[i];
-        resI++;
-      }
-    }
-    // inQuotes can only be true at this point if quotes are unbalanced
-    if (!inQuotes) {
-      // trim end of str
-      resI = retroTrim(res, resI);
-    }
-    return new String(res, 0, resI);
-  }
-
-  private static boolean isEscapeChar(char aChar) {
-    return aChar == '"';
-  }
-
-  private static boolean istrimmable(char aChar) {
-    return aChar <= ' ';
-  }
-
-  /**
-   * Reads from index {@code resI} to the beginning into {@code res} looking up the location of the trimmable char with
-   * the lowest index before encountering a non-trimmable char.
-   * <p>
-   * This basically trims {@code res} from any trimmable char at its end.
-   *
-   * @return index of next location to put new char in res
-   */
-  private static int retroTrim(char[] res, int resI) {
-    int i = resI;
-    while (i >= 1) {
-      if (!istrimmable(res[i - 1])) {
-        return i;
-      }
-      i--;
-    }
-    return i;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/package-info.java
deleted file mode 100644 (file)
index bcccfdd..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.impl.config;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/MetadataLoader.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/MetadataLoader.java
deleted file mode 100644 (file)
index 575fc47..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.context;
-
-import java.io.IOException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Scanner;
-import org.sonar.api.SonarEdition;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.Version;
-
-import static org.apache.commons.lang.StringUtils.trimToEmpty;
-
-/**
- * For internal use
- *
- * @since 7.8
- */
-public class MetadataLoader {
-
-  private static final String VERSION_FILE_PATH = "/sonar-api-version.txt";
-  private static final String EDITION_FILE_PATH = "/sonar-edition.txt";
-
-  private MetadataLoader() {
-    // only static methods
-  }
-
-  public static Version loadVersion(System2 system) {
-    URL url = system.getResource(VERSION_FILE_PATH);
-
-    try (Scanner scanner = new Scanner(url.openStream(), StandardCharsets.UTF_8.name())) {
-      String versionInFile = scanner.nextLine();
-      return Version.parse(versionInFile);
-    } catch (IOException e) {
-      throw new IllegalStateException("Can not load " + VERSION_FILE_PATH + " from classpath ", e);
-    }
-  }
-
-  public static SonarEdition loadEdition(System2 system) {
-    URL url = system.getResource(EDITION_FILE_PATH);
-    if (url == null) {
-      return SonarEdition.COMMUNITY;
-    }
-    try (Scanner scanner = new Scanner(url.openStream(), StandardCharsets.UTF_8.name())) {
-      String editionInFile = scanner.nextLine();
-      return parseEdition(editionInFile);
-    } catch (IOException e) {
-      throw new IllegalStateException("Can not load " + EDITION_FILE_PATH + " from classpath", e);
-    }
-  }
-
-  static SonarEdition parseEdition(String edition) {
-    String str = trimToEmpty(edition.toUpperCase());
-    try {
-      return SonarEdition.valueOf(str);
-    } catch (IllegalArgumentException e) {
-      throw new IllegalStateException(String.format("Invalid edition found in '%s': '%s'", EDITION_FILE_PATH, str));
-    }
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/PluginContextImpl.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/PluginContextImpl.java
deleted file mode 100644 (file)
index 211e5ce..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.context;
-
-import org.sonar.api.Plugin;
-import org.sonar.api.SonarRuntime;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.config.MapSettings;
-
-/**
- * Implementation of {@link Plugin.Context} that plugins could use in their unit tests.
- *
- * Example:
- *
- * <pre>
- *   import org.sonar.api.internal.SonarRuntimeImpl;
- *   import org.sonar.api.config.internal.MapSettings;
- *
- *   ...
- *
- *   SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(7, 1), SonarQubeSide.SCANNER);
- *   MapSettings settings = new MapSettings().setProperty("foo", "bar");
- *   Plugin.Context context = new PluginContextImpl.Builder()
- *     .setSonarRuntime(runtime)
- *     .setBootConfiguration(settings.asConfig());
- *     .build();
- * </pre>
- *
- * @since 7.1
- */
-public class PluginContextImpl extends Plugin.Context {
-
-  private final Configuration bootConfiguration;
-
-  private PluginContextImpl(Builder builder) {
-    super(builder.sonarRuntime);
-    this.bootConfiguration = builder.bootConfiguration != null ? builder.bootConfiguration : new MapSettings().asConfig();
-  }
-
-  @Override
-  public Configuration getBootConfiguration() {
-    return bootConfiguration;
-  }
-
-  public static class Builder {
-    private SonarRuntime sonarRuntime;
-    private Configuration bootConfiguration;
-
-    /**
-     * Required.
-     * @see SonarRuntimeImpl
-     * @return this
-     */
-    public Builder setSonarRuntime(SonarRuntime r) {
-      this.sonarRuntime = r;
-      return this;
-    }
-
-    /**
-     * If not set, then an empty configuration is used.
-     * @return this
-     */
-    public Builder setBootConfiguration(Configuration c) {
-      this.bootConfiguration = c;
-      return this;
-    }
-
-    public Plugin.Context build() {
-      return new PluginContextImpl(this);
-    }
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/SonarRuntimeImpl.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/SonarRuntimeImpl.java
deleted file mode 100644 (file)
index 4e4074e..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.context;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.SonarEdition;
-import org.sonar.api.SonarProduct;
-import org.sonar.api.SonarQubeSide;
-import org.sonar.api.SonarRuntime;
-import org.sonar.api.utils.Version;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-
-/**
- * @since 6.0
- */
-@Immutable
-public class SonarRuntimeImpl implements SonarRuntime {
-
-  private final Version version;
-  private final SonarProduct product;
-  private final SonarQubeSide sonarQubeSide;
-  private final SonarEdition edition;
-
-  private SonarRuntimeImpl(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide, @Nullable SonarEdition edition) {
-    this.edition = edition;
-    requireNonNull(product);
-    checkArgument((product == SonarProduct.SONARQUBE) == (sonarQubeSide != null), "sonarQubeSide should be provided only for SonarQube product");
-    checkArgument((product == SonarProduct.SONARQUBE) == (edition != null), "edition should be provided only for SonarQube product");
-    this.version = requireNonNull(version);
-    this.product = product;
-    this.sonarQubeSide = sonarQubeSide;
-  }
-
-  @Override
-  public Version getApiVersion() {
-    return version;
-  }
-
-  @Override
-  public SonarProduct getProduct() {
-    return product;
-  }
-
-  @Override
-  public SonarQubeSide getSonarQubeSide() {
-    if (sonarQubeSide == null) {
-      throw new UnsupportedOperationException("Can only be called in SonarQube");
-    }
-    return sonarQubeSide;
-  }
-
-  @Override
-  public SonarEdition getEdition() {
-    if (sonarQubeSide == null) {
-      throw new UnsupportedOperationException("Can only be called in SonarQube");
-    }
-    return edition;
-  }
-
-  /**
-   * Create an instance for SonarQube runtime environment.
-   */
-  public static SonarRuntime forSonarQube(Version version, SonarQubeSide side, SonarEdition edition) {
-    return new SonarRuntimeImpl(version, SonarProduct.SONARQUBE, side, edition);
-  }
-
-  /**
-   * Create an instance for SonarLint runtime environment.
-   */
-  public static SonarRuntime forSonarLint(Version version) {
-    return new SonarRuntimeImpl(version, SonarProduct.SONARLINT, null, null);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/package-info.java
deleted file mode 100644 (file)
index 632005c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.impl.context;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/AbstractProjectOrModule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/AbstractProjectOrModule.java
deleted file mode 100644 (file)
index 2834b34..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.SystemUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-@Immutable
-public abstract class AbstractProjectOrModule extends DefaultInputComponent {
-  private static final Logger LOGGER = Loggers.get(AbstractProjectOrModule.class);
-  private final Path baseDir;
-  private final Path workDir;
-  private final String name;
-  private final String originalName;
-  private final String description;
-  private final String keyWithBranch;
-  private final String branch;
-  private final Map<String, String> properties;
-
-  private final String key;
-  private final ProjectDefinition definition;
-  private final Charset encoding;
-
-  public AbstractProjectOrModule(ProjectDefinition definition, int scannerComponentId) {
-    super(scannerComponentId);
-    this.baseDir = initBaseDir(definition);
-    this.workDir = initWorkingDir(definition);
-    this.name = definition.getName();
-    this.originalName = definition.getOriginalName();
-    this.description = definition.getDescription();
-    this.keyWithBranch = definition.getKeyWithBranch();
-    this.branch = definition.getBranch();
-    this.properties = Collections.unmodifiableMap(new HashMap<>(definition.properties()));
-
-    this.definition = definition;
-    this.key = definition.getKey();
-    this.encoding = initEncoding(definition);
-  }
-
-  private static Charset initEncoding(ProjectDefinition module) {
-    String encodingStr = module.properties().get(CoreProperties.ENCODING_PROPERTY);
-    Charset result;
-    if (StringUtils.isNotEmpty(encodingStr)) {
-      result = Charset.forName(StringUtils.trim(encodingStr));
-    } else {
-      result = Charset.defaultCharset();
-    }
-    return result;
-  }
-
-  private static Path initBaseDir(ProjectDefinition module) {
-    Path result;
-    try {
-      result = module.getBaseDir().toPath().toRealPath(LinkOption.NOFOLLOW_LINKS);
-    } catch (IOException e) {
-      throw new IllegalStateException("Unable to resolve module baseDir", e);
-    }
-    return result;
-  }
-
-  private static Path initWorkingDir(ProjectDefinition module) {
-    File workingDirAsFile = module.getWorkDir();
-    Path workingDir = workingDirAsFile.getAbsoluteFile().toPath().normalize();
-    if (SystemUtils.IS_OS_WINDOWS) {
-      try {
-        Files.createDirectories(workingDir);
-        Files.setAttribute(workingDir, "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
-      } catch (IOException e) {
-        LOGGER.warn("Failed to set working directory hidden: {}", e.getMessage());
-      }
-    }
-    return workingDir;
-  }
-
-  /**
-   * Module key without branch
-   */
-  @Override
-  public String key() {
-    return key;
-  }
-
-  @Override
-  public boolean isFile() {
-    return false;
-  }
-
-  public ProjectDefinition definition() {
-    return definition;
-  }
-
-  public Path getBaseDir() {
-    return baseDir;
-  }
-
-  public Path getWorkDir() {
-    return workDir;
-  }
-
-  public String getKeyWithBranch() {
-    return keyWithBranch;
-  }
-
-  @CheckForNull
-  public String getBranch() {
-    return branch;
-  }
-
-  public Map<String, String> properties() {
-    return properties;
-  }
-
-  @CheckForNull
-  public String getOriginalName() {
-    return originalName;
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public String getDescription() {
-    return description;
-  }
-
-  public Charset getEncoding() {
-    return encoding;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultFileSystem.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultFileSystem.java
deleted file mode 100644 (file)
index db015d9..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.stream.StreamSupport;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.predicates.DefaultFilePredicates;
-import org.sonar.api.impl.fs.predicates.FileExtensionPredicate;
-import org.sonar.api.impl.fs.predicates.OptimizedFilePredicateAdapter;
-import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * @since 4.2
- */
-public class DefaultFileSystem implements FileSystem {
-
-  private final Cache cache;
-  private final FilePredicates predicates;
-  private final Path baseDir;
-  private Path workDir;
-  private Charset encoding;
-
-  /**
-   * Only for testing
-   */
-  public DefaultFileSystem(Path baseDir) {
-    this(baseDir, new MapCache(), new DefaultFilePredicates(baseDir));
-  }
-
-  /**
-   * Only for testing
-   */
-  public DefaultFileSystem(File baseDir) {
-    this(baseDir.toPath(), new MapCache(), new DefaultFilePredicates(baseDir.toPath()));
-  }
-
-  protected DefaultFileSystem(Path baseDir, Cache cache, FilePredicates filePredicates) {
-    this.baseDir = baseDir;
-    this.cache = cache;
-    this.predicates = filePredicates;
-  }
-
-  public Path baseDirPath() {
-    return baseDir;
-  }
-
-  @Override
-  public File baseDir() {
-    return baseDir.toFile();
-  }
-
-  public DefaultFileSystem setEncoding(Charset e) {
-    this.encoding = e;
-    return this;
-  }
-
-  @Override
-  public Charset encoding() {
-    return encoding;
-  }
-
-  public DefaultFileSystem setWorkDir(Path d) {
-    this.workDir = d;
-    return this;
-  }
-
-  @Override
-  public File workDir() {
-    return workDir.toFile();
-  }
-
-  @Override
-  public InputFile inputFile(FilePredicate predicate) {
-    Iterable<InputFile> files = inputFiles(predicate);
-    Iterator<InputFile> iterator = files.iterator();
-    if (!iterator.hasNext()) {
-      return null;
-    }
-    InputFile first = iterator.next();
-    if (!iterator.hasNext()) {
-      return first;
-    }
-
-    StringBuilder sb = new StringBuilder();
-    sb.append("expected one element but was: <" + first);
-    for (int i = 0; i < 4 && iterator.hasNext(); i++) {
-      sb.append(", " + iterator.next());
-    }
-    if (iterator.hasNext()) {
-      sb.append(", ...");
-    }
-    sb.append('>');
-
-    throw new IllegalArgumentException(sb.toString());
-
-  }
-
-  public Iterable<InputFile> inputFiles() {
-    return inputFiles(predicates.all());
-  }
-
-  @Override
-  public Iterable<InputFile> inputFiles(FilePredicate predicate) {
-    return OptimizedFilePredicateAdapter.create(predicate).get(cache);
-  }
-
-  @Override
-  public boolean hasFiles(FilePredicate predicate) {
-    return inputFiles(predicate).iterator().hasNext();
-  }
-
-  @Override
-  public Iterable<File> files(FilePredicate predicate) {
-    return () -> StreamSupport.stream(inputFiles(predicate).spliterator(), false)
-      .map(InputFile::file)
-      .iterator();
-  }
-
-  @Override
-  public InputDir inputDir(File dir) {
-    String relativePath = PathUtils.sanitize(new PathResolver().relativePath(baseDir.toFile(), dir));
-    if (relativePath == null) {
-      return null;
-    }
-    // Issues on InputDir are moved to the project, so we just return a fake InputDir for backward compatibility
-    return new DefaultInputDir("unused", relativePath).setModuleBaseDir(baseDir);
-  }
-
-  public DefaultFileSystem add(InputFile inputFile) {
-    cache.add(inputFile);
-    return this;
-  }
-
-  @Override
-  public SortedSet<String> languages() {
-    return cache.languages();
-  }
-
-  @Override
-  public FilePredicates predicates() {
-    return predicates;
-  }
-
-  public abstract static class Cache implements Index {
-
-    protected abstract void doAdd(InputFile inputFile);
-
-    final void add(InputFile inputFile) {
-      doAdd(inputFile);
-    }
-
-    protected abstract SortedSet<String> languages();
-  }
-
-  /**
-   * Used only for testing
-   */
-  private static class MapCache extends Cache {
-    private final Map<String, InputFile> fileMap = new HashMap<>();
-    private final Map<String, Set<InputFile>> filesByNameCache = new HashMap<>();
-    private final Map<String, Set<InputFile>> filesByExtensionCache = new HashMap<>();
-    private SortedSet<String> languages = new TreeSet<>();
-
-    @Override
-    public Iterable<InputFile> inputFiles() {
-      return new ArrayList<>(fileMap.values());
-    }
-
-    @Override
-    public InputFile inputFile(String relativePath) {
-      return fileMap.get(relativePath);
-    }
-
-    @Override
-    public Iterable<InputFile> getFilesByName(String filename) {
-      return filesByNameCache.get(filename);
-    }
-
-    @Override
-    public Iterable<InputFile> getFilesByExtension(String extension) {
-      return filesByExtensionCache.get(extension);
-    }
-
-    @Override
-    protected void doAdd(InputFile inputFile) {
-      if (inputFile.language() != null) {
-        languages.add(inputFile.language());
-      }
-      fileMap.put(inputFile.relativePath(), inputFile);
-      filesByNameCache.computeIfAbsent(inputFile.filename(), x -> new HashSet<>()).add(inputFile);
-      filesByExtensionCache.computeIfAbsent(FileExtensionPredicate.getExtension(inputFile), x -> new HashSet<>()).add(inputFile);
-    }
-
-    @Override
-    protected SortedSet<String> languages() {
-      return languages;
-    }
-  }
-
-  @Override
-  public File resolvePath(String path) {
-    File file = new File(path);
-    if (!file.isAbsolute()) {
-      try {
-        file = new File(baseDir(), path).getCanonicalFile();
-      } catch (IOException e) {
-        throw new IllegalArgumentException("Unable to resolve path '" + path + "'", e);
-      }
-    }
-    return file;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultIndexedFile.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultIndexedFile.java
deleted file mode 100644 (file)
index 5dae957..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.fs.IndexedFile;
-import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * @since 6.3
- */
-@Immutable
-public class DefaultIndexedFile extends DefaultInputComponent implements IndexedFile {
-  private static AtomicInteger intGenerator = new AtomicInteger(0);
-
-  private final String projectRelativePath;
-  private final String moduleRelativePath;
-  private final String projectKey;
-  private final String language;
-  private final Type type;
-  private final Path absolutePath;
-  private final SensorStrategy sensorStrategy;
-
-  /**
-   * Testing purposes only!
-   */
-  public DefaultIndexedFile(String projectKey, Path baseDir, String relativePath, @Nullable String language) {
-    this(baseDir.resolve(relativePath), projectKey, relativePath, relativePath, Type.MAIN, language, intGenerator.getAndIncrement(),
-      new SensorStrategy());
-  }
-
-  public DefaultIndexedFile(Path absolutePath, String projectKey, String projectRelativePath, String moduleRelativePath, Type type, @Nullable String language, int batchId,
-    SensorStrategy sensorStrategy) {
-    super(batchId);
-    this.projectKey = projectKey;
-    this.projectRelativePath = PathUtils.sanitize(projectRelativePath);
-    this.moduleRelativePath = PathUtils.sanitize(moduleRelativePath);
-    this.type = type;
-    this.language = language;
-    this.sensorStrategy = sensorStrategy;
-    this.absolutePath = absolutePath;
-  }
-
-  @Override
-  public String relativePath() {
-    return sensorStrategy.isGlobal() ? projectRelativePath : moduleRelativePath;
-  }
-
-  public String getModuleRelativePath() {
-    return moduleRelativePath;
-  }
-
-  public String getProjectRelativePath() {
-    return projectRelativePath;
-  }
-
-  @Override
-  public String absolutePath() {
-    return PathUtils.sanitize(path().toString());
-  }
-
-  @Override
-  public File file() {
-    return path().toFile();
-  }
-
-  @Override
-  public Path path() {
-    return absolutePath;
-  }
-
-  @Override
-  public InputStream inputStream() throws IOException {
-    return Files.newInputStream(path());
-  }
-
-  @CheckForNull
-  @Override
-  public String language() {
-    return language;
-  }
-
-  @Override
-  public Type type() {
-    return type;
-  }
-
-  /**
-   * Component key (without branch).
-   */
-  @Override
-  public String key() {
-    return new StringBuilder().append(projectKey).append(":").append(projectRelativePath).toString();
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-
-    if (!(o instanceof DefaultIndexedFile)) {
-      return false;
-    }
-
-    DefaultIndexedFile that = (DefaultIndexedFile) o;
-    return projectRelativePath.equals(that.projectRelativePath);
-  }
-
-  @Override
-  public int hashCode() {
-    return projectRelativePath.hashCode();
-  }
-
-  @Override
-  public String toString() {
-    return projectRelativePath;
-  }
-
-  @Override
-  public boolean isFile() {
-    return true;
-  }
-
-  @Override
-  public String filename() {
-    return path().getFileName().toString();
-  }
-
-  @Override
-  public URI uri() {
-    return path().toUri();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputComponent.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputComponent.java
deleted file mode 100644 (file)
index 14acba4..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.util.HashSet;
-import java.util.Set;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.measure.Metric;
-
-/**
- * @since 5.2
- */
-public abstract class DefaultInputComponent implements InputComponent {
-  private int id;
-  private Set<String> storedMetricKeys = new HashSet<>();
-
-  public DefaultInputComponent(int scannerId) {
-    this.id = scannerId;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || this.getClass() != o.getClass()) {
-      return false;
-    }
-
-    DefaultInputComponent that = (DefaultInputComponent) o;
-    return key().equals(that.key());
-  }
-
-  public int scannerId() {
-    return id;
-  }
-
-  @Override
-  public int hashCode() {
-    return key().hashCode();
-  }
-
-  @Override
-  public String toString() {
-    return "[key=" + key() + "]";
-  }
-
-  public void setHasMeasureFor(Metric metric) {
-    storedMetricKeys.add(metric.key());
-  }
-
-  public boolean hasMeasureFor(Metric metric) {
-    return storedMetricKeys.contains(metric.key());
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputDir.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputDir.java
deleted file mode 100644 (file)
index 53f1800..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.net.URI;
-import java.nio.file.Path;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * @since 4.5
- */
-public class DefaultInputDir extends DefaultInputComponent implements InputDir {
-
-  private final String relativePath;
-  private final String moduleKey;
-  private Path moduleBaseDir;
-
-  public DefaultInputDir(String moduleKey, String relativePath) {
-    super(-1);
-    this.moduleKey = moduleKey;
-    this.relativePath = PathUtils.sanitize(relativePath);
-  }
-
-  @Override
-  public String relativePath() {
-    return relativePath;
-  }
-
-  @Override
-  public String absolutePath() {
-    return PathUtils.sanitize(path().toString());
-  }
-
-  @Override
-  public File file() {
-    return path().toFile();
-  }
-
-  @Override
-  public Path path() {
-    if (moduleBaseDir == null) {
-      throw new IllegalStateException("Can not return the java.nio.file.Path because module baseDir is not set (see method setModuleBaseDir(java.io.File))");
-    }
-    return moduleBaseDir.resolve(relativePath);
-  }
-
-  public String moduleKey() {
-    return moduleKey;
-  }
-
-  @Override
-  public String key() {
-    StringBuilder sb = new StringBuilder().append(moduleKey).append(":");
-    if (StringUtils.isEmpty(relativePath)) {
-      sb.append("/");
-    } else {
-      sb.append(relativePath);
-    }
-    return sb.toString();
-  }
-
-  /**
-   * For testing purpose. Will be automatically set when dir is added to {@link DefaultFileSystem}
-   */
-  public DefaultInputDir setModuleBaseDir(Path moduleBaseDir) {
-    this.moduleBaseDir = moduleBaseDir.normalize();
-    return this;
-  }
-
-  @Override
-  public boolean isFile() {
-    return false;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || this.getClass() != o.getClass()) {
-      return false;
-    }
-
-    DefaultInputDir that = (DefaultInputDir) o;
-    return moduleKey.equals(that.moduleKey) && relativePath.equals(that.relativePath);
-  }
-
-  @Override
-  public int hashCode() {
-    return moduleKey.hashCode() + relativePath.hashCode() * 13;
-  }
-
-  @Override
-  public String toString() {
-    return "[moduleKey=" + moduleKey + ", relative=" + relativePath + ", basedir=" + moduleBaseDir + "]";
-  }
-
-  @Override
-  public URI uri() {
-    return path().toUri();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputFile.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputFile.java
deleted file mode 100644 (file)
index 61561b0..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.io.ByteOrderMark;
-import org.apache.commons.io.input.BOMInputStream;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextPointer;
-import org.sonar.api.batch.fs.TextRange;
-
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-/**
- * @since 4.2
- * To create {@link InputFile} in tests, use TestInputFileBuilder.
- */
-public class DefaultInputFile extends DefaultInputComponent implements InputFile {
-
-  private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
-
-  private final DefaultIndexedFile indexedFile;
-  private final String contents;
-  private final Consumer<DefaultInputFile> metadataGenerator;
-
-  private boolean published;
-  private boolean excludedForCoverage;
-  private boolean excludedForDuplication;
-  private boolean ignoreAllIssues;
-  // Lazy init to save memory
-  private BitSet noSonarLines;
-  private Status status;
-  private Charset charset;
-  private Metadata metadata;
-  private Collection<int[]> ignoreIssuesOnlineRanges;
-  private BitSet executableLines;
-
-  public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator) {
-    this(indexedFile, metadataGenerator, null);
-  }
-
-  // For testing
-  public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator, @Nullable String contents) {
-    super(indexedFile.scannerId());
-    this.indexedFile = indexedFile;
-    this.metadataGenerator = metadataGenerator;
-    this.metadata = null;
-    this.published = false;
-    this.excludedForCoverage = false;
-    this.contents = contents;
-  }
-
-  public void checkMetadata() {
-    if (metadata == null) {
-      metadataGenerator.accept(this);
-    }
-  }
-
-  @Override
-  public InputStream inputStream() throws IOException {
-    return contents != null ? new ByteArrayInputStream(contents.getBytes(charset()))
-      : new BOMInputStream(Files.newInputStream(path()),
-      ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
-  }
-
-  @Override
-  public String contents() throws IOException {
-    if (contents != null) {
-      return contents;
-    } else {
-      ByteArrayOutputStream result = new ByteArrayOutputStream();
-      try (InputStream inputStream = inputStream()) {
-        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
-        int length;
-        while ((length = inputStream.read(buffer)) != -1) {
-          result.write(buffer, 0, length);
-        }
-      }
-      return result.toString(charset().name());
-    }
-  }
-
-  public DefaultInputFile setPublished(boolean published) {
-    this.published = published;
-    return this;
-  }
-
-  public boolean isPublished() {
-    return published;
-  }
-
-  public DefaultInputFile setExcludedForCoverage(boolean excludedForCoverage) {
-    this.excludedForCoverage = excludedForCoverage;
-    return this;
-  }
-
-  public boolean isExcludedForCoverage() {
-    return excludedForCoverage;
-  }
-
-  public DefaultInputFile setExcludedForDuplication(boolean excludedForDuplication) {
-    this.excludedForDuplication = excludedForDuplication;
-    return this;
-  }
-
-  public boolean isExcludedForDuplication() {
-    return excludedForDuplication;
-  }
-
-  /**
-   * @deprecated since 6.6
-   */
-  @Deprecated
-  @Override
-  public String relativePath() {
-    return indexedFile.relativePath();
-  }
-
-  public String getModuleRelativePath() {
-    return indexedFile.getModuleRelativePath();
-  }
-
-  public String getProjectRelativePath() {
-    return indexedFile.getProjectRelativePath();
-  }
-
-  @Override
-  public String absolutePath() {
-    return indexedFile.absolutePath();
-  }
-
-  @Override
-  public File file() {
-    return indexedFile.file();
-  }
-
-  @Override
-  public Path path() {
-    return indexedFile.path();
-  }
-
-  @CheckForNull
-  @Override
-  public String language() {
-    return indexedFile.language();
-  }
-
-  @Override
-  public Type type() {
-    return indexedFile.type();
-  }
-
-  /**
-   * Component key (without branch).
-   */
-  @Override
-  public String key() {
-    return indexedFile.key();
-  }
-
-  @Override
-  public int hashCode() {
-    return indexedFile.hashCode();
-  }
-
-  @Override
-  public String toString() {
-    return indexedFile.toString();
-  }
-
-  /**
-   * {@link #setStatus(Status)}
-   */
-  @Override
-  public Status status() {
-    checkMetadata();
-    return status;
-  }
-
-  @Override
-  public int lines() {
-    checkMetadata();
-    return metadata.lines();
-  }
-
-  @Override
-  public boolean isEmpty() {
-    checkMetadata();
-    return metadata.isEmpty();
-  }
-
-  @Override
-  public Charset charset() {
-    checkMetadata();
-    return charset;
-  }
-
-  public int lastValidOffset() {
-    checkMetadata();
-    return metadata.lastValidOffset();
-  }
-
-  /**
-   * Digest hash of the file.
-   */
-  public String hash() {
-    checkMetadata();
-    return metadata.hash();
-  }
-
-  public int nonBlankLines() {
-    checkMetadata();
-    return metadata.nonBlankLines();
-  }
-
-  public int[] originalLineStartOffsets() {
-    checkMetadata();
-    checkState(metadata.originalLineStartOffsets() != null, "InputFile is not properly initialized.");
-    checkState(metadata.originalLineStartOffsets().length == metadata.lines(),
-      "InputFile is not properly initialized. 'originalLineStartOffsets' property length should be equal to 'lines'");
-    return metadata.originalLineStartOffsets();
-  }
-
-  public int[] originalLineEndOffsets() {
-    checkMetadata();
-    checkState(metadata.originalLineEndOffsets() != null, "InputFile is not properly initialized.");
-    checkState(metadata.originalLineEndOffsets().length == metadata.lines(),
-      "InputFile is not properly initialized. 'originalLineEndOffsets' property length should be equal to 'lines'");
-    return metadata.originalLineEndOffsets();
-  }
-
-  @Override
-  public TextPointer newPointer(int line, int lineOffset) {
-    checkMetadata();
-    DefaultTextPointer textPointer = new DefaultTextPointer(line, lineOffset);
-    checkValid(textPointer, "pointer");
-    return textPointer;
-  }
-
-  @Override
-  public TextRange newRange(TextPointer start, TextPointer end) {
-    checkMetadata();
-    checkValid(start, "start pointer");
-    checkValid(end, "end pointer");
-    return newRangeValidPointers(start, end, false);
-  }
-
-  @Override
-  public TextRange newRange(int startLine, int startLineOffset, int endLine, int endLineOffset) {
-    checkMetadata();
-    TextPointer start = newPointer(startLine, startLineOffset);
-    TextPointer end = newPointer(endLine, endLineOffset);
-    return newRangeValidPointers(start, end, false);
-  }
-
-  @Override
-  public TextRange selectLine(int line) {
-    checkMetadata();
-    TextPointer startPointer = newPointer(line, 0);
-    TextPointer endPointer = newPointer(line, lineLength(line));
-    return newRangeValidPointers(startPointer, endPointer, true);
-  }
-
-  public void validate(TextRange range) {
-    checkMetadata();
-    checkValid(range.start(), "start pointer");
-    checkValid(range.end(), "end pointer");
-  }
-
-  /**
-   * Create Range from global offsets. Used for backward compatibility with older API.
-   */
-  public TextRange newRange(int startOffset, int endOffset) {
-    checkMetadata();
-    return newRangeValidPointers(newPointer(startOffset), newPointer(endOffset), false);
-  }
-
-  public TextPointer newPointer(int globalOffset) {
-    checkMetadata();
-    checkArgument(globalOffset >= 0, "%s is not a valid offset for a file", globalOffset);
-    checkArgument(globalOffset <= lastValidOffset(), "%s is not a valid offset for file %s. Max offset is %s", globalOffset, this, lastValidOffset());
-    int line = findLine(globalOffset);
-    int startLineOffset = originalLineStartOffsets()[line - 1];
-    // In case the global offset is between \r and \n, move the pointer to a valid location
-    return new DefaultTextPointer(line, Math.min(globalOffset, originalLineEndOffsets()[line - 1]) - startLineOffset);
-  }
-
-  public DefaultInputFile setStatus(Status status) {
-    this.status = status;
-    return this;
-  }
-
-  public DefaultInputFile setCharset(Charset charset) {
-    this.charset = charset;
-    return this;
-  }
-
-  private void checkValid(TextPointer pointer, String owner) {
-    checkArgument(pointer.line() >= 1, "%s is not a valid line for a file", pointer.line());
-    checkArgument(pointer.line() <= this.metadata.lines(), "%s is not a valid line for %s. File %s has %s line(s)", pointer.line(), owner, this, metadata.lines());
-    checkArgument(pointer.lineOffset() >= 0, "%s is not a valid line offset for a file", pointer.lineOffset());
-    int lineLength = lineLength(pointer.line());
-    checkArgument(pointer.lineOffset() <= lineLength,
-      "%s is not a valid line offset for %s. File %s has %s character(s) at line %s", pointer.lineOffset(), owner, this, lineLength, pointer.line());
-  }
-
-  private int lineLength(int line) {
-    return originalLineEndOffsets()[line - 1] - originalLineStartOffsets()[line - 1];
-  }
-
-  private static TextRange newRangeValidPointers(TextPointer start, TextPointer end, boolean acceptEmptyRange) {
-    checkArgument(acceptEmptyRange ? (start.compareTo(end) <= 0) : (start.compareTo(end) < 0),
-      "Start pointer %s should be before end pointer %s", start, end);
-    return new DefaultTextRange(start, end);
-  }
-
-  private int findLine(int globalOffset) {
-    return Math.abs(Arrays.binarySearch(originalLineStartOffsets(), globalOffset) + 1);
-  }
-
-  public DefaultInputFile setMetadata(Metadata metadata) {
-    this.metadata = metadata;
-    return this;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (obj == null) {
-      return false;
-    }
-
-    if (this.getClass() != obj.getClass()) {
-      return false;
-    }
-
-    DefaultInputFile that = (DefaultInputFile) obj;
-    return this.getProjectRelativePath().equals(that.getProjectRelativePath());
-  }
-
-  @Override
-  public boolean isFile() {
-    return true;
-  }
-
-  @Override
-  public String filename() {
-    return indexedFile.filename();
-  }
-
-  @Override
-  public URI uri() {
-    return indexedFile.uri();
-  }
-
-  public void noSonarAt(Set<Integer> noSonarLines) {
-    if (this.noSonarLines == null) {
-      this.noSonarLines = new BitSet(lines());
-    }
-    noSonarLines.forEach(l -> this.noSonarLines.set(l - 1));
-  }
-
-  public boolean hasNoSonarAt(int line) {
-    if (this.noSonarLines == null) {
-      return false;
-    }
-    return this.noSonarLines.get(line - 1);
-  }
-
-  public boolean isIgnoreAllIssues() {
-    return ignoreAllIssues;
-  }
-
-  public void setIgnoreAllIssues(boolean ignoreAllIssues) {
-    this.ignoreAllIssues = ignoreAllIssues;
-  }
-
-  public void addIgnoreIssuesOnLineRanges(Collection<int[]> lineRanges) {
-    if (this.ignoreIssuesOnlineRanges == null) {
-      this.ignoreIssuesOnlineRanges = new ArrayList<>();
-    }
-    this.ignoreIssuesOnlineRanges.addAll(lineRanges);
-  }
-
-  public boolean isIgnoreAllIssuesOnLine(@Nullable Integer line) {
-    if (line == null || ignoreIssuesOnlineRanges == null) {
-      return false;
-    }
-    return ignoreIssuesOnlineRanges.stream().anyMatch(r -> r[0] <= line && line <= r[1]);
-  }
-
-  public void setExecutableLines(Set<Integer> executableLines) {
-    checkState(this.executableLines == null, "Executable lines have already been saved for file: {}", this.toString());
-    this.executableLines = new BitSet(lines());
-    executableLines.forEach(l -> this.executableLines.set(l - 1));
-  }
-
-  public Optional<Set<Integer>> getExecutableLines() {
-    if (this.executableLines == null) {
-      return Optional.empty();
-    }
-    return Optional.of(this.executableLines.stream().map(i -> i + 1).boxed().collect(Collectors.toSet()));
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputModule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputModule.java
deleted file mode 100644 (file)
index 476a719..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.scan.filesystem.PathResolver;
-
-import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
-
-@Immutable
-public class DefaultInputModule extends AbstractProjectOrModule implements InputModule {
-
-  private final List<Path> sourceDirsOrFiles;
-  private final List<Path> testDirsOrFiles;
-
-  /**
-   * For testing only!
-   */
-  public DefaultInputModule(ProjectDefinition definition) {
-    this(definition, 0);
-  }
-
-  public DefaultInputModule(ProjectDefinition definition, int scannerComponentId) {
-    super(definition, scannerComponentId);
-
-    this.sourceDirsOrFiles = initSources(definition, ProjectDefinition.SOURCES_PROPERTY);
-    this.testDirsOrFiles = initSources(definition, ProjectDefinition.TESTS_PROPERTY);
-  }
-
-  @CheckForNull
-  private List<Path> initSources(ProjectDefinition module, String propertyKey) {
-    if (!module.properties().containsKey(propertyKey)) {
-      return null;
-    }
-    List<Path> result = new ArrayList<>();
-    PathResolver pathResolver = new PathResolver();
-    String srcPropValue = module.properties().get(propertyKey);
-    if (srcPropValue != null) {
-      for (String sourcePath : parseAsCsv(propertyKey, srcPropValue)) {
-        File dirOrFile = pathResolver.relativeFile(getBaseDir().toFile(), sourcePath);
-        if (dirOrFile.exists()) {
-          result.add(dirOrFile.toPath());
-        }
-      }
-    }
-    return result;
-  }
-
-  public Optional<List<Path>> getSourceDirsOrFiles() {
-    return Optional.ofNullable(sourceDirsOrFiles);
-  }
-
-  public Optional<List<Path>> getTestDirsOrFiles() {
-    return Optional.ofNullable(testDirsOrFiles);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputProject.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputProject.java
deleted file mode 100644 (file)
index 0ed1500..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.scanner.fs.InputProject;
-
-@Immutable
-public class DefaultInputProject extends AbstractProjectOrModule implements InputProject {
-
-  /**
-   * For testing only!
-   */
-  public DefaultInputProject(ProjectDefinition definition) {
-    super(definition, 0);
-  }
-
-  public DefaultInputProject(ProjectDefinition definition, int scannerComponentId) {
-    super(definition, scannerComponentId);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextPointer.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextPointer.java
deleted file mode 100644 (file)
index 541ee95..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import org.sonar.api.batch.fs.TextPointer;
-
-/**
- * @since 5.2
- */
-public class DefaultTextPointer implements TextPointer {
-
-  private final int line;
-  private final int lineOffset;
-
-  public DefaultTextPointer(int line, int lineOffset) {
-    this.line = line;
-    this.lineOffset = lineOffset;
-  }
-
-  @Override
-  public int line() {
-    return line;
-  }
-
-  @Override
-  public int lineOffset() {
-    return lineOffset;
-  }
-
-  @Override
-  public String toString() {
-    return "[line=" + line + ", lineOffset=" + lineOffset + "]";
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (!(obj instanceof DefaultTextPointer)) {
-      return false;
-    }
-    DefaultTextPointer other = (DefaultTextPointer) obj;
-    return other.line == this.line && other.lineOffset == this.lineOffset;
-  }
-
-  @Override
-  public int hashCode() {
-    return 37 * this.line + lineOffset;
-  }
-
-  @Override
-  public int compareTo(TextPointer o) {
-    if (this.line == o.line()) {
-      return Integer.compare(this.lineOffset, o.lineOffset());
-    }
-    return Integer.compare(this.line, o.line());
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextRange.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextRange.java
deleted file mode 100644 (file)
index 0bf0e51..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import org.sonar.api.batch.fs.TextPointer;
-import org.sonar.api.batch.fs.TextRange;
-
-/**
- * @since 5.2
- */
-public class DefaultTextRange implements TextRange {
-
-  private final TextPointer start;
-  private final TextPointer end;
-
-  public DefaultTextRange(TextPointer start, TextPointer end) {
-    this.start = start;
-    this.end = end;
-  }
-
-  @Override
-  public TextPointer start() {
-    return start;
-  }
-
-  @Override
-  public TextPointer end() {
-    return end;
-  }
-
-  @Override
-  public boolean overlap(TextRange another) {
-    // [A,B] and [C,D]
-    // B > C && D > A
-    return this.end.compareTo(another.start()) > 0 && another.end().compareTo(this.start) > 0;
-  }
-
-  @Override
-  public String toString() {
-    return "Range[from " + start + " to " + end + "]";
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (!(obj instanceof DefaultTextRange)) {
-      return false;
-    }
-    DefaultTextRange other = (DefaultTextRange) obj;
-    return start.equals(other.start) && end.equals(other.end);
-  }
-
-  @Override
-  public int hashCode() {
-    return start.hashCode() * 17 + end.hashCode();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/FileMetadata.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/FileMetadata.java
deleted file mode 100644 (file)
index 8078db1..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.charhandler.CharHandler;
-import org.sonar.api.impl.fs.charhandler.FileHashComputer;
-import org.sonar.api.impl.fs.charhandler.LineCounter;
-import org.sonar.api.impl.fs.charhandler.LineHashComputer;
-import org.sonar.api.impl.fs.charhandler.LineOffsetCounter;
-
-/**
- * Computes hash of files. Ends of Lines are ignored, so files with
- * same content but different EOL encoding have the same hash.
- */
-@Immutable
-public class FileMetadata {
-  private static final char LINE_FEED = '\n';
-  private static final char CARRIAGE_RETURN = '\r';
-
-  /**
-   * Compute hash of a file ignoring line ends differences.
-   * Maximum performance is needed.
-   */
-  public Metadata readMetadata(InputStream stream, Charset encoding, String filePath, @Nullable CharHandler otherHandler) {
-    LineCounter lineCounter = new LineCounter(filePath, encoding);
-    FileHashComputer fileHashComputer = new FileHashComputer(filePath);
-    LineOffsetCounter lineOffsetCounter = new LineOffsetCounter();
-
-    if (otherHandler != null) {
-      CharHandler[] handlers = {lineCounter, fileHashComputer, lineOffsetCounter, otherHandler};
-      readFile(stream, encoding, filePath, handlers);
-    } else {
-      CharHandler[] handlers = {lineCounter, fileHashComputer, lineOffsetCounter};
-      readFile(stream, encoding, filePath, handlers);
-    }
-    return new Metadata(lineCounter.lines(), lineCounter.nonBlankLines(), fileHashComputer.getHash(), lineOffsetCounter.getOriginalLineStartOffsets(),
-      lineOffsetCounter.getOriginalLineEndOffsets(),
-      lineOffsetCounter.getLastValidOffset());
-  }
-
-  public Metadata readMetadata(InputStream stream, Charset encoding, String filePath) {
-    return readMetadata(stream, encoding, filePath, null);
-  }
-
-  /**
-   * For testing purpose
-   */
-  public Metadata readMetadata(Reader reader) {
-    LineCounter lineCounter = new LineCounter("fromString", StandardCharsets.UTF_16);
-    FileHashComputer fileHashComputer = new FileHashComputer("fromString");
-    LineOffsetCounter lineOffsetCounter = new LineOffsetCounter();
-    CharHandler[] handlers = {lineCounter, fileHashComputer, lineOffsetCounter};
-
-    try {
-      read(reader, handlers);
-    } catch (IOException e) {
-      throw new IllegalStateException("Should never occur", e);
-    }
-    return new Metadata(lineCounter.lines(), lineCounter.nonBlankLines(), fileHashComputer.getHash(), lineOffsetCounter.getOriginalLineStartOffsets(),
-      lineOffsetCounter.getOriginalLineEndOffsets(),
-      lineOffsetCounter.getLastValidOffset());
-  }
-
-  public static void readFile(InputStream stream, Charset encoding, String filePath, CharHandler[] handlers) {
-    try (Reader reader = new BufferedReader(new InputStreamReader(stream, encoding))) {
-      read(reader, handlers);
-    } catch (IOException e) {
-      throw new IllegalStateException(String.format("Fail to read file '%s' with encoding '%s'", filePath, encoding), e);
-    }
-  }
-
-  private static void read(Reader reader, CharHandler[] handlers) throws IOException {
-    char c;
-    int i = reader.read();
-    boolean afterCR = false;
-    while (i != -1) {
-      c = (char) i;
-      if (afterCR) {
-        for (CharHandler handler : handlers) {
-          if (c == CARRIAGE_RETURN) {
-            handler.newLine();
-            handler.handleAll(c);
-          } else if (c == LINE_FEED) {
-            handler.handleAll(c);
-            handler.newLine();
-          } else {
-            handler.newLine();
-            handler.handleIgnoreEoL(c);
-            handler.handleAll(c);
-          }
-        }
-        afterCR = c == CARRIAGE_RETURN;
-      } else if (c == LINE_FEED) {
-        for (CharHandler handler : handlers) {
-          handler.handleAll(c);
-          handler.newLine();
-        }
-      } else if (c == CARRIAGE_RETURN) {
-        afterCR = true;
-        for (CharHandler handler : handlers) {
-          handler.handleAll(c);
-        }
-      } else {
-        for (CharHandler handler : handlers) {
-          handler.handleIgnoreEoL(c);
-          handler.handleAll(c);
-        }
-      }
-      i = reader.read();
-    }
-    for (CharHandler handler : handlers) {
-      if (afterCR) {
-        handler.newLine();
-      }
-      handler.eof();
-    }
-  }
-
-  @FunctionalInterface
-  public interface LineHashConsumer {
-    void consume(int lineIdx, @Nullable byte[] hash);
-  }
-
-  /**
-   * Compute a MD5 hash of each line of the file after removing of all blank chars
-   */
-  public static void computeLineHashesForIssueTracking(InputFile f, LineHashConsumer consumer) {
-    try {
-      readFile(f.inputStream(), f.charset(), f.absolutePath(), new CharHandler[] {new LineHashComputer(consumer, f.file())});
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to compute line hashes for " + f.absolutePath(), e);
-    }
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/Metadata.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/Metadata.java
deleted file mode 100644 (file)
index e177041..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.util.Arrays;
-
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-public class Metadata {
-  private final int lines;
-  private final int nonBlankLines;
-  private final String hash;
-  private final int[] originalLineStartOffsets;
-  private final int[] originalLineEndOffsets;
-  private final int lastValidOffset;
-
-  public Metadata(int lines, int nonBlankLines, String hash, int[] originalLineStartOffsets, int[] originalLineEndOffsets, int lastValidOffset) {
-    this.lines = lines;
-    this.nonBlankLines = nonBlankLines;
-    this.hash = hash;
-    this.originalLineStartOffsets = Arrays.copyOf(originalLineStartOffsets, originalLineStartOffsets.length);
-    this.originalLineEndOffsets = Arrays.copyOf(originalLineEndOffsets, originalLineEndOffsets.length);
-    this.lastValidOffset = lastValidOffset;
-  }
-
-  public int lines() {
-    return lines;
-  }
-
-  public int nonBlankLines() {
-    return nonBlankLines;
-  }
-
-  public String hash() {
-    return hash;
-  }
-
-  public int[] originalLineStartOffsets() {
-    return originalLineStartOffsets;
-  }
-
-  public int[] originalLineEndOffsets() {
-    return originalLineEndOffsets;
-  }
-
-  public int lastValidOffset() {
-    return lastValidOffset;
-  }
-
-  public boolean isEmpty() {
-    return lastValidOffset == 0;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/PathPattern.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/PathPattern.java
deleted file mode 100644 (file)
index 30a813d..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.nio.file.Path;
-import javax.annotation.concurrent.ThreadSafe;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.utils.PathUtils;
-import org.sonar.api.utils.WildcardPattern;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-@ThreadSafe
-public abstract class PathPattern {
-
-  private static final Logger LOG = Loggers.get(PathPattern.class);
-
-  /**
-   * @deprecated since 6.6
-   */
-  @Deprecated
-  private static final String ABSOLUTE_PATH_PATTERN_PREFIX = "file:";
-  final WildcardPattern pattern;
-
-  PathPattern(String pattern) {
-    this.pattern = WildcardPattern.create(pattern);
-  }
-
-  public abstract boolean match(Path absolutePath, Path relativePath);
-
-  public abstract boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension);
-
-  public static PathPattern create(String s) {
-    String trimmed = StringUtils.trim(s);
-    if (StringUtils.startsWithIgnoreCase(trimmed, ABSOLUTE_PATH_PATTERN_PREFIX)) {
-      LOG.warn("Using absolute path pattern is deprecated. Please use relative path instead of '" + trimmed + "'");
-      return new AbsolutePathPattern(StringUtils.substring(trimmed, ABSOLUTE_PATH_PATTERN_PREFIX.length()));
-    }
-    return new RelativePathPattern(trimmed);
-  }
-
-  public static PathPattern[] create(String[] s) {
-    PathPattern[] result = new PathPattern[s.length];
-    for (int i = 0; i < s.length; i++) {
-      result[i] = create(s[i]);
-    }
-    return result;
-  }
-
-  /**
-   * @deprecated since 6.6
-   */
-  @Deprecated
-  private static class AbsolutePathPattern extends PathPattern {
-    private AbsolutePathPattern(String pattern) {
-      super(pattern);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath) {
-      return match(absolutePath, relativePath, true);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension) {
-      String path = PathUtils.sanitize(absolutePath.toString());
-      if (!caseSensitiveFileExtension) {
-        String extension = sanitizeExtension(FilenameUtils.getExtension(path));
-        if (StringUtils.isNotBlank(extension)) {
-          path = StringUtils.removeEndIgnoreCase(path, extension);
-          path = path + extension;
-        }
-      }
-      return pattern.match(path);
-    }
-
-    @Override
-    public String toString() {
-      return ABSOLUTE_PATH_PATTERN_PREFIX + pattern.toString();
-    }
-  }
-
-  /**
-   * Path relative to module basedir
-   */
-  private static class RelativePathPattern extends PathPattern {
-    private RelativePathPattern(String pattern) {
-      super(pattern);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath) {
-      return match(absolutePath, relativePath, true);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension) {
-      String path = PathUtils.sanitize(relativePath.toString());
-      if (!caseSensitiveFileExtension) {
-        String extension = sanitizeExtension(FilenameUtils.getExtension(path));
-        if (StringUtils.isNotBlank(extension)) {
-          path = StringUtils.removeEndIgnoreCase(path, extension);
-          path = path + extension;
-        }
-      }
-      return path != null && pattern.match(path);
-    }
-
-    @Override
-    public String toString() {
-      return pattern.toString();
-    }
-  }
-
-  static String sanitizeExtension(String suffix) {
-    return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/SensorStrategy.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/SensorStrategy.java
deleted file mode 100644 (file)
index d956d06..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * A shared, mutable object in the project container.
- * It's used during the execution of sensors to decide whether
- * sensors should be executed once for the entire project, or per-module.
- * It is also injected into each InputFile to change the behavior of {@link InputFile#relativePath()}
- */
-public class SensorStrategy {
-
-  private boolean global = true;
-
-  public boolean isGlobal() {
-    return global;
-  }
-
-  public void setGlobal(boolean global) {
-    this.global = global;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/TestInputFileBuilder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/TestInputFileBuilder.java
deleted file mode 100644 (file)
index e731e7f..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.StringReader;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * Intended to be used in unit tests that need to create {@link InputFile}s.
- * An InputFile is unambiguously identified by a <b>module key</b> and a <b>relative path</b>, so these parameters are mandatory.
- * <p>
- * A module base directory is only needed to construct absolute paths.
- * <p>
- * Examples of usage of the constructors:
- *
- * <pre>
- * InputFile file1 = TestInputFileBuilder.create("module1", "myfile.java").build();
- * InputFile file2 = TestInputFileBuilder.create("", fs.baseDir(), myfile).build();
- * </pre>
- * <p>
- * file1 will have the "module1" as both module key and module base directory.
- * file2 has an empty string as module key, and a relative path which is the path from the filesystem base directory to myfile.
- *
- * @since 6.3
- */
-public class TestInputFileBuilder {
-  private static int batchId = 1;
-
-  private final int id;
-  private final String relativePath;
-  private final String projectKey;
-  @CheckForNull
-  private Path projectBaseDir;
-  private Path moduleBaseDir;
-  private String language;
-  private InputFile.Type type = InputFile.Type.MAIN;
-  private InputFile.Status status;
-  private int lines = -1;
-  private Charset charset;
-  private String hash;
-  private int nonBlankLines;
-  private int[] originalLineStartOffsets = new int[0];
-  private int[] originalLineEndOffsets = new int[0];
-  private int lastValidOffset = -1;
-  private boolean publish = true;
-  private String contents;
-
-  /**
-   * Create a InputFile identified by the given project key and relative path.
-   */
-  public TestInputFileBuilder(String projectKey, String relativePath) {
-    this(projectKey, relativePath, batchId++);
-  }
-
-  /**
-   * Create a InputFile with a given module key and module base directory.
-   * The relative path is generated comparing the file path to the module base directory.
-   * filePath must point to a file that is within the module base directory.
-   */
-  public TestInputFileBuilder(String projectKey, File moduleBaseDir, File filePath) {
-    String relativePath = moduleBaseDir.toPath().relativize(filePath.toPath()).toString();
-    this.projectKey = projectKey;
-    setModuleBaseDir(moduleBaseDir.toPath());
-    this.relativePath = PathUtils.sanitize(relativePath);
-    this.id = batchId++;
-  }
-
-  public TestInputFileBuilder(String projectKey, String relativePath, int id) {
-    this.projectKey = projectKey;
-    setModuleBaseDir(Paths.get(projectKey));
-    this.relativePath = PathUtils.sanitize(relativePath);
-    this.id = id;
-  }
-
-  public static TestInputFileBuilder create(String moduleKey, File moduleBaseDir, File filePath) {
-    return new TestInputFileBuilder(moduleKey, moduleBaseDir, filePath);
-  }
-
-  public static TestInputFileBuilder create(String moduleKey, String relativePath) {
-    return new TestInputFileBuilder(moduleKey, relativePath);
-  }
-
-  public static int nextBatchId() {
-    return batchId++;
-  }
-
-  public TestInputFileBuilder setProjectBaseDir(Path projectBaseDir) {
-    this.projectBaseDir = normalize(projectBaseDir);
-    return this;
-  }
-
-  public TestInputFileBuilder setModuleBaseDir(Path moduleBaseDir) {
-    this.moduleBaseDir = normalize(moduleBaseDir);
-    return this;
-  }
-
-  private static Path normalize(Path path) {
-    try {
-      return path.normalize().toRealPath(LinkOption.NOFOLLOW_LINKS);
-    } catch (IOException e) {
-      return path.normalize();
-    }
-  }
-
-  public TestInputFileBuilder setLanguage(@Nullable String language) {
-    this.language = language;
-    return this;
-  }
-
-  public TestInputFileBuilder setType(InputFile.Type type) {
-    this.type = type;
-    return this;
-  }
-
-  public TestInputFileBuilder setStatus(InputFile.Status status) {
-    this.status = status;
-    return this;
-  }
-
-  public TestInputFileBuilder setLines(int lines) {
-    this.lines = lines;
-    return this;
-  }
-
-  public TestInputFileBuilder setCharset(Charset charset) {
-    this.charset = charset;
-    return this;
-  }
-
-  public TestInputFileBuilder setHash(String hash) {
-    this.hash = hash;
-    return this;
-  }
-
-  /**
-   * Set contents of the file and calculates metadata from it.
-   * The contents will be returned by {@link InputFile#contents()} and {@link InputFile#inputStream()} and can be
-   * inconsistent with the actual physical file pointed by {@link InputFile#path()}, {@link InputFile#absolutePath()}, etc.
-   */
-  public TestInputFileBuilder setContents(String content) {
-    this.contents = content;
-    initMetadata(content);
-    return this;
-  }
-
-  public TestInputFileBuilder setNonBlankLines(int nonBlankLines) {
-    this.nonBlankLines = nonBlankLines;
-    return this;
-  }
-
-  public TestInputFileBuilder setLastValidOffset(int lastValidOffset) {
-    this.lastValidOffset = lastValidOffset;
-    return this;
-  }
-
-  public TestInputFileBuilder setOriginalLineStartOffsets(int[] originalLineStartOffsets) {
-    this.originalLineStartOffsets = originalLineStartOffsets;
-    return this;
-  }
-
-  public TestInputFileBuilder setOriginalLineEndOffsets(int[] originalLineEndOffsets) {
-    this.originalLineEndOffsets = originalLineEndOffsets;
-    return this;
-  }
-
-  public TestInputFileBuilder setPublish(boolean publish) {
-    this.publish = publish;
-    return this;
-  }
-
-  public TestInputFileBuilder setMetadata(Metadata metadata) {
-    this.setLines(metadata.lines());
-    this.setLastValidOffset(metadata.lastValidOffset());
-    this.setNonBlankLines(metadata.nonBlankLines());
-    this.setHash(metadata.hash());
-    this.setOriginalLineStartOffsets(metadata.originalLineStartOffsets());
-    this.setOriginalLineEndOffsets(metadata.originalLineEndOffsets());
-    return this;
-  }
-
-  public TestInputFileBuilder initMetadata(String content) {
-    return setMetadata(new FileMetadata().readMetadata(new StringReader(content)));
-  }
-
-  public DefaultInputFile build() {
-    Path absolutePath = moduleBaseDir.resolve(relativePath);
-    if (projectBaseDir == null) {
-      projectBaseDir = moduleBaseDir;
-    }
-    String projectRelativePath = projectBaseDir.relativize(absolutePath).toString();
-    DefaultIndexedFile indexedFile = new DefaultIndexedFile(absolutePath, projectKey, projectRelativePath, relativePath, type, language, id, new SensorStrategy());
-    DefaultInputFile inputFile = new DefaultInputFile(indexedFile,
-      f -> f.setMetadata(new Metadata(lines, nonBlankLines, hash, originalLineStartOffsets, originalLineEndOffsets, lastValidOffset)),
-      contents);
-    inputFile.setStatus(status);
-    inputFile.setCharset(charset);
-    inputFile.setPublished(publish);
-    return inputFile;
-  }
-
-  public static DefaultInputModule newDefaultInputModule(String moduleKey, File baseDir) {
-    ProjectDefinition definition = ProjectDefinition.create()
-      .setKey(moduleKey)
-      .setBaseDir(baseDir)
-      .setWorkDir(new File(baseDir, ".sonar"));
-    return newDefaultInputModule(definition);
-  }
-
-  public static DefaultInputModule newDefaultInputModule(ProjectDefinition projectDefinition) {
-    return new DefaultInputModule(projectDefinition, TestInputFileBuilder.nextBatchId());
-  }
-
-  public static DefaultInputModule newDefaultInputModule(AbstractProjectOrModule parent, String key) throws IOException {
-    Path basedir = parent.getBaseDir().resolve(key);
-    Files.createDirectory(basedir);
-    return newDefaultInputModule(key, basedir.toFile());
-  }
-
-  public static DefaultInputProject newDefaultInputProject(String projectKey, File baseDir) {
-    ProjectDefinition definition = ProjectDefinition.create()
-      .setKey(projectKey)
-      .setBaseDir(baseDir)
-      .setWorkDir(new File(baseDir, ".sonar"));
-    return newDefaultInputProject(definition);
-  }
-
-  public static DefaultInputProject newDefaultInputProject(ProjectDefinition projectDefinition) {
-    return new DefaultInputProject(projectDefinition, TestInputFileBuilder.nextBatchId());
-  }
-
-  public static DefaultInputProject newDefaultInputProject(String key, Path baseDir) throws IOException {
-    Files.createDirectory(baseDir);
-    return newDefaultInputProject(key, baseDir.toFile());
-  }
-
-  public static DefaultInputDir newDefaultInputDir(AbstractProjectOrModule module, String relativePath) throws IOException {
-    Path basedir = module.getBaseDir().resolve(relativePath);
-    Files.createDirectory(basedir);
-    return new DefaultInputDir(module.key(), relativePath)
-      .setModuleBaseDir(module.getBaseDir());
-  }
-
-  public static DefaultInputFile newDefaultInputFile(Path projectBaseDir, AbstractProjectOrModule module, String relativePath) {
-    return new TestInputFileBuilder(module.key(), relativePath)
-      .setStatus(InputFile.Status.SAME)
-      .setProjectBaseDir(projectBaseDir)
-      .setModuleBaseDir(module.getBaseDir())
-      .build();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/CharHandler.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/CharHandler.java
deleted file mode 100644 (file)
index 06218a6..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.charhandler;
-
-public abstract class CharHandler {
-
-  public void handleAll(char c) {
-  }
-
-  public void handleIgnoreEoL(char c) {
-  }
-
-  public void newLine() {
-  }
-
-  public void eof() {
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/FileHashComputer.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/FileHashComputer.java
deleted file mode 100644 (file)
index eaa5672..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.charhandler;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.codec.digest.DigestUtils;
-
-public class FileHashComputer extends CharHandler {
-  private static final char LINE_FEED = '\n';
-
-  
-  private MessageDigest globalMd5Digest = DigestUtils.getMd5Digest();
-  private StringBuilder sb = new StringBuilder();
-  private final CharsetEncoder encoder;
-  private final String filePath;
-
-  public FileHashComputer(String filePath) {
-    encoder = StandardCharsets.UTF_8.newEncoder()
-      .onMalformedInput(CodingErrorAction.REPLACE)
-      .onUnmappableCharacter(CodingErrorAction.REPLACE);
-    this.filePath = filePath;
-  }
-
-  @Override
-  public void handleIgnoreEoL(char c) {
-    sb.append(c);
-  }
-
-  @Override
-  public void newLine() {
-    sb.append(LINE_FEED);
-    processBuffer();
-    sb.setLength(0);
-  }
-
-  @Override
-  public void eof() {
-    if (sb.length() > 0) {
-      processBuffer();
-    }
-  }
-
-  private void processBuffer() {
-    try {
-      if (sb.length() > 0) {
-        ByteBuffer encoded = encoder.encode(CharBuffer.wrap(sb));
-        globalMd5Digest.update(encoded.array(), 0, encoded.limit());
-      }
-    } catch (CharacterCodingException e) {
-      throw new IllegalStateException("Error encoding line hash in file: " + filePath, e);
-    }
-  }
-
-  public String getHash() {
-    return Hex.encodeHexString(globalMd5Digest.digest());
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/IntArrayList.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/IntArrayList.java
deleted file mode 100644 (file)
index b298b05..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.charhandler;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * Specialization of {@link java.util.ArrayList} to create a list of int (only append elements) and then produce an int[].
- */
-class IntArrayList {
-
-  /**
-   * Default initial capacity.
-   */
-  private static final int DEFAULT_CAPACITY = 10;
-
-  /**
-   * Shared empty array instance used for default sized empty instances. We
-   * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
-   * first element is added.
-   */
-  private static final int[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
-
-  /**
-   * The array buffer into which the elements of the ArrayList are stored.
-   * The capacity of the IntArrayList is the length of this array buffer. Any
-   * empty IntArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
-   * will be expanded to DEFAULT_CAPACITY when the first element is added.
-   */
-  private int[] elementData;
-
-  /**
-   * The size of the IntArrayList (the number of elements it contains).
-   */
-  private int size;
-
-  /**
-   * Constructs an empty list with an initial capacity of ten.
-   */
-  public IntArrayList() {
-    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
-  }
-
-  /**
-   * Trims the capacity of this <tt>IntArrayList</tt> instance to be the
-   * list's current size and return the internal array. An application can use this operation to minimize
-   * the storage of an <tt>IntArrayList</tt> instance.
-   */
-  public int[] trimAndGet() {
-    if (size < elementData.length) {
-      elementData = Arrays.copyOf(elementData, size);
-    }
-    return elementData;
-  }
-
-  private void ensureCapacityInternal(int minCapacity) {
-    int capacity = minCapacity;
-    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
-      capacity = Math.max(DEFAULT_CAPACITY, minCapacity);
-    }
-
-    ensureExplicitCapacity(capacity);
-  }
-
-  private void ensureExplicitCapacity(int minCapacity) {
-    if (minCapacity - elementData.length > 0) {
-      grow(minCapacity);
-    }
-  }
-
-  /**
-   * Increases the capacity to ensure that it can hold at least the
-   * number of elements specified by the minimum capacity argument.
-   *
-   * @param minCapacity the desired minimum capacity
-   */
-  private void grow(int minCapacity) {
-    int oldCapacity = elementData.length;
-    int newCapacity = oldCapacity + (oldCapacity >> 1);
-    if (newCapacity - minCapacity < 0) {
-      newCapacity = minCapacity;
-    }
-    elementData = Arrays.copyOf(elementData, newCapacity);
-  }
-
-  /**
-   * Appends the specified element to the end of this list.
-   *
-   * @param e element to be appended to this list
-   * @return <tt>true</tt> (as specified by {@link Collection#add})
-   */
-  public boolean add(int e) {
-    ensureCapacityInternal(size + 1);
-    elementData[size] = e;
-    size++;
-    return true;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineCounter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineCounter.java
deleted file mode 100644 (file)
index ba5093b..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.charhandler;
-
-import java.nio.charset.Charset;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-public class LineCounter extends CharHandler {
-  private static final Logger LOG = Loggers.get(LineCounter.class);
-    
-  private int lines = 1;
-  private int nonBlankLines = 0;
-  private boolean blankLine = true;
-  boolean alreadyLoggedInvalidCharacter = false;
-  private final String filePath;
-  private final Charset encoding;
-
-  public LineCounter(String filePath, Charset encoding) {
-    this.filePath = filePath;
-    this.encoding = encoding;
-  }
-
-  @Override
-  public void handleAll(char c) {
-    if (!alreadyLoggedInvalidCharacter && c == '\ufffd') {
-      LOG.warn("Invalid character encountered in file {} at line {} for encoding {}. Please fix file content or configure the encoding to be used using property '{}'.", filePath,
-        lines, encoding, CoreProperties.ENCODING_PROPERTY);
-      alreadyLoggedInvalidCharacter = true;
-    }
-  }
-
-  @Override
-  public void newLine() {
-    lines++;
-    if (!blankLine) {
-      nonBlankLines++;
-    }
-    blankLine = true;
-  }
-
-  @Override
-  public void handleIgnoreEoL(char c) {
-    if (!Character.isWhitespace(c)) {
-      blankLine = false;
-    }
-  }
-
-  @Override
-  public void eof() {
-    if (!blankLine) {
-      nonBlankLines++;
-    }
-  }
-
-  public int lines() {
-    return lines;
-  }
-
-  public int nonBlankLines() {
-    return nonBlankLines;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineHashComputer.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineHashComputer.java
deleted file mode 100644 (file)
index 8384258..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.charhandler;
-
-import java.io.File;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.sonar.api.impl.fs.FileMetadata;
-
-public class LineHashComputer extends CharHandler {
-  private final MessageDigest lineMd5Digest = DigestUtils.getMd5Digest();
-  private final CharsetEncoder encoder;
-  private final StringBuilder sb = new StringBuilder();
-  private final FileMetadata.LineHashConsumer consumer;
-  private final File file;
-  private int line = 1;
-
-  public LineHashComputer(FileMetadata.LineHashConsumer consumer, File f) {
-    this.consumer = consumer;
-    this.file = f;
-    this.encoder = StandardCharsets.UTF_8.newEncoder()
-      .onMalformedInput(CodingErrorAction.REPLACE)
-      .onUnmappableCharacter(CodingErrorAction.REPLACE);
-  }
-
-  @Override
-  public void handleIgnoreEoL(char c) {
-    if (!Character.isWhitespace(c)) {
-      sb.append(c);
-    }
-  }
-
-  @Override
-  public void newLine() {
-    processBuffer();
-    sb.setLength(0);
-    line++;
-  }
-
-  @Override
-  public void eof() {
-    if (this.line > 0) {
-      processBuffer();
-    }
-  }
-
-  private void processBuffer() {
-    try {
-      if (sb.length() > 0) {
-        ByteBuffer encoded = encoder.encode(CharBuffer.wrap(sb));
-        lineMd5Digest.update(encoded.array(), 0, encoded.limit());
-        consumer.consume(line, lineMd5Digest.digest());
-      }
-    } catch (CharacterCodingException e) {
-      throw new IllegalStateException("Error encoding line hash in file: " + file.getAbsolutePath(), e);
-    }
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineOffsetCounter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineOffsetCounter.java
deleted file mode 100644 (file)
index 1b0ad31..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.charhandler;
-
-public class LineOffsetCounter extends CharHandler {
-  private long currentOriginalLineStartOffset = 0;
-  private long currentOriginalLineEndOffset = 0;
-  private final IntArrayList originalLineStartOffsets = new IntArrayList();
-  private final IntArrayList originalLineEndOffsets = new IntArrayList();
-  private long lastValidOffset = 0;
-
-  public LineOffsetCounter() {
-    originalLineStartOffsets.add(0);
-  }
-
-  @Override
-  public void handleAll(char c) {
-    currentOriginalLineStartOffset++;
-  }
-
-  @Override
-  public void handleIgnoreEoL(char c) {
-    currentOriginalLineEndOffset++;
-  }
-
-  @Override
-  public void newLine() {
-    if (currentOriginalLineStartOffset > Integer.MAX_VALUE) {
-      throw new IllegalStateException("File is too big: " + currentOriginalLineStartOffset);
-    }
-    originalLineStartOffsets.add((int) currentOriginalLineStartOffset);
-    originalLineEndOffsets.add((int) currentOriginalLineEndOffset);
-    currentOriginalLineEndOffset = currentOriginalLineStartOffset;
-  }
-
-  @Override
-  public void eof() {
-    originalLineEndOffsets.add((int) currentOriginalLineEndOffset);
-    lastValidOffset = currentOriginalLineStartOffset;
-  }
-
-  public int[] getOriginalLineStartOffsets() {
-    return originalLineStartOffsets.trimAndGet();
-  }
-
-  public int[] getOriginalLineEndOffsets() {
-    return originalLineEndOffsets.trimAndGet();
-  }
-
-  public int getLastValidOffset() {
-    if (lastValidOffset > Integer.MAX_VALUE) {
-      throw new IllegalStateException("File is too big: " + lastValidOffset);
-    }
-    return (int) lastValidOffset;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/package-info.java
deleted file mode 100644 (file)
index 9c9bce6..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.impl.fs.charhandler;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/package-info.java
deleted file mode 100644 (file)
index 10a7978..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.impl.fs;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbsolutePathPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbsolutePathPredicate.java
deleted file mode 100644 (file)
index c83cc64..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.io.File;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Collections;
-import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * @since 4.2
- */
-class AbsolutePathPredicate extends AbstractFilePredicate {
-
-  private final String path;
-  private final Path baseDir;
-
-  AbsolutePathPredicate(String path, Path baseDir) {
-    this.baseDir = baseDir;
-    this.path = PathUtils.sanitize(path);
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    return path.equals(f.absolutePath());
-  }
-
-  @Override
-  public Iterable<InputFile> get(Index index) {
-    String relative = PathUtils.sanitize(new PathResolver().relativePath(baseDir.toFile(), new File(path)));
-    if (relative == null) {
-      return Collections.emptyList();
-    }
-    InputFile f = index.inputFile(relative);
-    return f != null ? Arrays.asList(f) : Collections.<InputFile>emptyList();
-  }
-
-  @Override
-  public int priority() {
-    return USE_INDEX;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbstractFilePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbstractFilePredicate.java
deleted file mode 100644 (file)
index 1a964b4..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.stream.StreamSupport;
-import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * Partial implementation of {@link OptimizedFilePredicate}.
- * @since 5.1
- */
-public abstract class AbstractFilePredicate implements OptimizedFilePredicate {
-
-  protected static final int DEFAULT_PRIORITY = 10;
-  protected static final int USE_INDEX = 20;
-
-  @Override
-  public Iterable<InputFile> filter(Iterable<InputFile> target) {
-    return () -> StreamSupport.stream(target.spliterator(), false)
-      .filter(this::apply)
-      .iterator();
-  }
-
-  @Override
-  public Iterable<InputFile> get(Index index) {
-    return filter(index.inputFiles());
-  }
-
-  @Override
-  public int priority() {
-    return DEFAULT_PRIORITY;
-  }
-
-  @Override
-  public final int compareTo(OptimizedFilePredicate o) {
-    return o.priority() - priority();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AndPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AndPredicate.java
deleted file mode 100644 (file)
index d2ea1f3..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.InputFile;
-
-import static java.util.stream.Collectors.toList;
-
-/**
- * @since 4.2
- */
-class AndPredicate extends AbstractFilePredicate implements OperatorPredicate {
-
-  private final List<OptimizedFilePredicate> predicates = new ArrayList<>();
-
-  private AndPredicate() {
-  }
-
-  public static FilePredicate create(Collection<FilePredicate> predicates) {
-    if (predicates.isEmpty()) {
-      return TruePredicate.TRUE;
-    }
-    AndPredicate result = new AndPredicate();
-    for (FilePredicate filePredicate : predicates) {
-      if (filePredicate == TruePredicate.TRUE) {
-        continue;
-      } else if (filePredicate == FalsePredicate.FALSE) {
-        return FalsePredicate.FALSE;
-      } else if (filePredicate instanceof AndPredicate) {
-        result.predicates.addAll(((AndPredicate) filePredicate).predicates);
-      } else {
-        result.predicates.add(OptimizedFilePredicateAdapter.create(filePredicate));
-      }
-    }
-    Collections.sort(result.predicates);
-    return result;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    for (OptimizedFilePredicate predicate : predicates) {
-      if (!predicate.apply(f)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @Override
-  public Iterable<InputFile> filter(Iterable<InputFile> target) {
-    Iterable<InputFile> result = target;
-    for (OptimizedFilePredicate predicate : predicates) {
-      result = predicate.filter(result);
-    }
-    return result;
-  }
-
-  @Override
-  public Iterable<InputFile> get(Index index) {
-    if (predicates.isEmpty()) {
-      return index.inputFiles();
-    }
-    // Optimization, use get on first predicate then filter with next predicates
-    Iterable<InputFile> result = predicates.get(0).get(index);
-    for (int i = 1; i < predicates.size(); i++) {
-      result = predicates.get(i).filter(result);
-    }
-    return result;
-  }
-
-  Collection<OptimizedFilePredicate> predicates() {
-    return predicates;
-  }
-
-  @Override
-  public List<FilePredicate> operands() {
-    return predicates.stream().map(p -> (FilePredicate) p).collect(toList());
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicates.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicates.java
deleted file mode 100644 (file)
index fe005c6..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.io.File;
-import java.net.URI;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.impl.fs.PathPattern;
-
-/**
- * Factory of {@link FilePredicate}
- *
- * @since 4.2
- */
-public class DefaultFilePredicates implements FilePredicates {
-
-  private final Path baseDir;
-
-  /**
-   * Client code should use {@link org.sonar.api.batch.fs.FileSystem#predicates()} to get an instance
-   */
-  public DefaultFilePredicates(Path baseDir) {
-    this.baseDir = baseDir;
-  }
-
-  /**
-   * Returns a predicate that always evaluates to true
-   */
-  @Override
-  public FilePredicate all() {
-    return TruePredicate.TRUE;
-  }
-
-  /**
-   * Returns a predicate that always evaluates to false
-   */
-  @Override
-  public FilePredicate none() {
-    return FalsePredicate.FALSE;
-  }
-
-  @Override
-  public FilePredicate hasAbsolutePath(String s) {
-    return new AbsolutePathPredicate(s, baseDir);
-  }
-
-  /**
-   * non-normalized path and Windows-style path are supported
-   */
-  @Override
-  public FilePredicate hasRelativePath(String s) {
-    return new RelativePathPredicate(s);
-  }
-
-  @Override
-  public FilePredicate hasFilename(String s) {
-    return new FilenamePredicate(s);
-  }
-
-  @Override
-  public FilePredicate hasExtension(String s) {
-    return new FileExtensionPredicate(s);
-  }
-
-  @Override
-  public FilePredicate hasURI(URI uri) {
-    return new URIPredicate(uri, baseDir);
-  }
-
-  @Override
-  public FilePredicate matchesPathPattern(String inclusionPattern) {
-    return new PathPatternPredicate(PathPattern.create(inclusionPattern));
-  }
-
-  @Override
-  public FilePredicate matchesPathPatterns(String[] inclusionPatterns) {
-    if (inclusionPatterns.length == 0) {
-      return TruePredicate.TRUE;
-    }
-    FilePredicate[] predicates = new FilePredicate[inclusionPatterns.length];
-    for (int i = 0; i < inclusionPatterns.length; i++) {
-      predicates[i] = new PathPatternPredicate(PathPattern.create(inclusionPatterns[i]));
-    }
-    return or(predicates);
-  }
-
-  @Override
-  public FilePredicate doesNotMatchPathPattern(String exclusionPattern) {
-    return not(matchesPathPattern(exclusionPattern));
-  }
-
-  @Override
-  public FilePredicate doesNotMatchPathPatterns(String[] exclusionPatterns) {
-    if (exclusionPatterns.length == 0) {
-      return TruePredicate.TRUE;
-    }
-    return not(matchesPathPatterns(exclusionPatterns));
-  }
-
-  @Override
-  public FilePredicate hasPath(String s) {
-    File file = new File(s);
-    if (file.isAbsolute()) {
-      return hasAbsolutePath(s);
-    }
-    return hasRelativePath(s);
-  }
-
-  @Override
-  public FilePredicate is(File ioFile) {
-    if (ioFile.isAbsolute()) {
-      return hasAbsolutePath(ioFile.getAbsolutePath());
-    }
-    return hasRelativePath(ioFile.getPath());
-  }
-
-  @Override
-  public FilePredicate hasLanguage(String language) {
-    return new LanguagePredicate(language);
-  }
-
-  @Override
-  public FilePredicate hasLanguages(Collection<String> languages) {
-    List<FilePredicate> list = new ArrayList<>();
-    for (String language : languages) {
-      list.add(hasLanguage(language));
-    }
-    return or(list);
-  }
-
-  @Override
-  public FilePredicate hasLanguages(String... languages) {
-    List<FilePredicate> list = new ArrayList<>();
-    for (String language : languages) {
-      list.add(hasLanguage(language));
-    }
-    return or(list);
-  }
-
-  @Override
-  public FilePredicate hasType(InputFile.Type type) {
-    return new TypePredicate(type);
-  }
-
-  @Override
-  public FilePredicate not(FilePredicate p) {
-    return new NotPredicate(p);
-  }
-
-  @Override
-  public FilePredicate or(Collection<FilePredicate> or) {
-    return OrPredicate.create(or);
-  }
-
-  @Override
-  public FilePredicate or(FilePredicate... or) {
-    return OrPredicate.create(Arrays.asList(or));
-  }
-
-  @Override
-  public FilePredicate or(FilePredicate first, FilePredicate second) {
-    return OrPredicate.create(Arrays.asList(first, second));
-  }
-
-  @Override
-  public FilePredicate and(Collection<FilePredicate> and) {
-    return AndPredicate.create(and);
-  }
-
-  @Override
-  public FilePredicate and(FilePredicate... and) {
-    return AndPredicate.create(Arrays.asList(and));
-  }
-
-  @Override
-  public FilePredicate and(FilePredicate first, FilePredicate second) {
-    return AndPredicate.create(Arrays.asList(first, second));
-  }
-
-  @Override
-  public FilePredicate hasStatus(Status status) {
-    return new StatusPredicate(status);
-  }
-
-  @Override
-  public FilePredicate hasAnyStatus() {
-    return new StatusPredicate(null);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FalsePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FalsePredicate.java
deleted file mode 100644 (file)
index d6c1d78..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.Collections;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.InputFile;
-
-class FalsePredicate extends AbstractFilePredicate {
-
-  static final FilePredicate FALSE = new FalsePredicate();
-
-  @Override
-  public boolean apply(InputFile inputFile) {
-    return false;
-  }
-
-  @Override
-  public Iterable<InputFile> filter(Iterable<InputFile> target) {
-    return Collections.emptyList();
-  }
-
-  @Override
-  public Iterable<InputFile> get(Index index) {
-    return Collections.emptyList();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicate.java
deleted file mode 100644 (file)
index 7775c56..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.Locale;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @since 6.3
- */
-public class FileExtensionPredicate extends AbstractFilePredicate {
-
-  private final String extension;
-
-  public FileExtensionPredicate(String extension) {
-    this.extension = lowercase(extension);
-  }
-
-  @Override
-  public boolean apply(InputFile inputFile) {
-    return extension.equals(getExtension(inputFile));
-  }
-
-  @Override
-  public Iterable<InputFile> get(FileSystem.Index index) {
-    return index.getFilesByExtension(extension);
-  }
-
-  public static String getExtension(InputFile inputFile) {
-    return getExtension(inputFile.filename());
-  }
-
-  static String getExtension(String name) {
-    int index = name.lastIndexOf('.');
-    if (index < 0) {
-      return "";
-    }
-    return lowercase(name.substring(index + 1));
-  }
-
-  private static String lowercase(String extension) {
-    return extension.toLowerCase(Locale.ENGLISH);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FilenamePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FilenamePredicate.java
deleted file mode 100644 (file)
index 94fac58..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @since 6.3
- */
-public class FilenamePredicate extends AbstractFilePredicate {
-  private final String filename;
-
-  public FilenamePredicate(String filename) {
-    this.filename = filename;
-  }
-
-  @Override
-  public boolean apply(InputFile inputFile) {
-    return filename.equals(inputFile.filename());
-  }
-
-  @Override
-  public Iterable<InputFile> get(FileSystem.Index index) {
-    return index.getFilesByName(filename);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/LanguagePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/LanguagePredicate.java
deleted file mode 100644 (file)
index e553625..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @since 4.2
- */
-class LanguagePredicate extends AbstractFilePredicate {
-  private final String language;
-
-  LanguagePredicate(String language) {
-    this.language = language;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    return language.equals(f.language());
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/NotPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/NotPredicate.java
deleted file mode 100644 (file)
index 4841c55..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.Arrays;
-import java.util.List;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @since 4.2
- */
-class NotPredicate extends AbstractFilePredicate implements OperatorPredicate {
-
-  private final FilePredicate predicate;
-
-  NotPredicate(FilePredicate predicate) {
-    this.predicate = predicate;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    return !predicate.apply(f);
-  }
-
-  @Override
-  public List<FilePredicate> operands() {
-    return Arrays.asList(predicate);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OperatorPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OperatorPredicate.java
deleted file mode 100644 (file)
index bf8e566..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.List;
-import org.sonar.api.batch.fs.FilePredicate;
-
-/**
- * A predicate that associate other predicates
- */
-public interface OperatorPredicate extends FilePredicate {
-
-  List<FilePredicate> operands();
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicate.java
deleted file mode 100644 (file)
index aaba4c8..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * Optimized version of FilePredicate allowing to speed up query by looking at InputFile by index.
- */
-public interface OptimizedFilePredicate extends FilePredicate, Comparable<OptimizedFilePredicate> {
-
-  /**
-   * Filter provided files to keep only the ones that are valid for this predicate
-   */
-  Iterable<InputFile> filter(Iterable<InputFile> inputFiles);
-
-  /**
-   * Get all files that are valid for this predicate.
-   */
-  Iterable<InputFile> get(FileSystem.Index index);
-
-  /**
-   * For optimization. FilePredicates will be applied in priority order. For example when doing
-   * p.and(p1, p2, p3) then p1, p2 and p3 will be applied according to their priority value. Higher priority value
-   * are applied first.
-   * Assign a high priority when the predicate will likely highly reduce the set of InputFiles to filter. Also
-   * {@link RelativePathPredicate} and AbsolutePathPredicate have a high priority since they are using cache index.
-   */
-  int priority();
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicateAdapter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicateAdapter.java
deleted file mode 100644 (file)
index 5de4fee..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-public class OptimizedFilePredicateAdapter extends AbstractFilePredicate {
-
-  private FilePredicate unoptimizedPredicate;
-
-  private OptimizedFilePredicateAdapter(FilePredicate unoptimizedPredicate) {
-    this.unoptimizedPredicate = unoptimizedPredicate;
-  }
-
-  @Override
-  public boolean apply(InputFile inputFile) {
-    return unoptimizedPredicate.apply(inputFile);
-  }
-
-  public static OptimizedFilePredicate create(FilePredicate predicate) {
-    if (predicate instanceof OptimizedFilePredicate) {
-      return (OptimizedFilePredicate) predicate;
-    } else {
-      return new OptimizedFilePredicateAdapter(predicate);
-    }
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OrPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OrPredicate.java
deleted file mode 100644 (file)
index 3f93903..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @since 4.2
- */
-class OrPredicate extends AbstractFilePredicate implements OperatorPredicate {
-
-  private final List<FilePredicate> predicates = new ArrayList<>();
-
-  private OrPredicate() {
-  }
-
-  public static FilePredicate create(Collection<FilePredicate> predicates) {
-    if (predicates.isEmpty()) {
-      return TruePredicate.TRUE;
-    }
-    OrPredicate result = new OrPredicate();
-    for (FilePredicate filePredicate : predicates) {
-      if (filePredicate == TruePredicate.TRUE) {
-        return TruePredicate.TRUE;
-      } else if (filePredicate == FalsePredicate.FALSE) {
-        continue;
-      } else if (filePredicate instanceof OrPredicate) {
-        result.predicates.addAll(((OrPredicate) filePredicate).predicates);
-      } else {
-        result.predicates.add(filePredicate);
-      }
-    }
-    return result;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    for (FilePredicate predicate : predicates) {
-      if (predicate.apply(f)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  Collection<FilePredicate> predicates() {
-    return predicates;
-  }
-
-  @Override
-  public List<FilePredicate> operands() {
-    return predicates;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/PathPatternPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/PathPatternPredicate.java
deleted file mode 100644 (file)
index 1e27675..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.nio.file.Paths;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.PathPattern;
-
-/**
- * @since 4.2
- */
-class PathPatternPredicate extends AbstractFilePredicate {
-
-  private final PathPattern pattern;
-
-  PathPatternPredicate(PathPattern pattern) {
-    this.pattern = pattern;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    return pattern.match(f.path(), Paths.get(f.relativePath()));
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/RelativePathPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/RelativePathPredicate.java
deleted file mode 100644 (file)
index a1cb9f4..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.Collections;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.utils.PathUtils;
-
-/**
- * @since 4.2
- */
-public class RelativePathPredicate extends AbstractFilePredicate {
-
-  @Nullable
-  private final String path;
-
-  RelativePathPredicate(String path) {
-    this.path = PathUtils.sanitize(path);
-  }
-
-  public String path() {
-    return path;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    if (path == null) {
-      return false;
-    }
-
-    return path.equals(f.relativePath());
-  }
-
-  @Override
-  public Iterable<InputFile> get(Index index) {
-    if (path != null) {
-      InputFile f = index.inputFile(this.path);
-      if (f != null) {
-        return Collections.singletonList(f);
-      }
-    }
-    return Collections.emptyList();
-  }
-
-  @Override
-  public int priority() {
-    return USE_INDEX;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/StatusPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/StatusPredicate.java
deleted file mode 100644 (file)
index bcac4e0..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @deprecated since 7.8
- */
-@Deprecated
-public class StatusPredicate extends AbstractFilePredicate {
-
-  private final InputFile.Status status;
-
-  StatusPredicate(@Nullable InputFile.Status status) {
-    this.status = status;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    return status == null || status == f.status();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TruePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TruePredicate.java
deleted file mode 100644 (file)
index 04d56ee..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.InputFile;
-
-class TruePredicate extends AbstractFilePredicate {
-
-  static final FilePredicate TRUE = new TruePredicate();
-
-  @Override
-  public boolean apply(InputFile inputFile) {
-    return true;
-  }
-
-  @Override
-  public Iterable<InputFile> get(Index index) {
-    return index.inputFiles();
-  }
-
-  @Override
-  public Iterable<InputFile> filter(Iterable<InputFile> target) {
-    return target;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TypePredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TypePredicate.java
deleted file mode 100644 (file)
index f9d5705..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * @since 4.2
- */
-class TypePredicate extends AbstractFilePredicate {
-
-  private final InputFile.Type type;
-
-  TypePredicate(InputFile.Type type) {
-    this.type = type;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    return type == f.type();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/URIPredicate.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/URIPredicate.java
deleted file mode 100644 (file)
index 60fea97..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.net.URI;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Optional;
-import org.sonar.api.batch.fs.FileSystem.Index;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.scan.filesystem.PathResolver;
-
-/**
- * @since 6.6
- */
-class URIPredicate extends AbstractFilePredicate {
-
-  private final URI uri;
-  private final Path baseDir;
-
-  URIPredicate(URI uri, Path baseDir) {
-    this.baseDir = baseDir;
-    this.uri = uri;
-  }
-
-  @Override
-  public boolean apply(InputFile f) {
-    return uri.equals(f.uri());
-  }
-
-  @Override
-  public Iterable<InputFile> get(Index index) {
-    Path path = Paths.get(uri);
-    Optional<String> relative = PathResolver.relativize(baseDir, path);
-    if (!relative.isPresent()) {
-      return Collections.emptyList();
-    }
-    InputFile f = index.inputFile(relative.get());
-    return f != null ? Arrays.asList(f) : Collections.<InputFile>emptyList();
-  }
-
-  @Override
-  public int priority() {
-    return USE_INDEX;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/package-info.java
deleted file mode 100644 (file)
index aa33a1e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.impl.fs.predicates;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/AbstractDefaultIssue.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/AbstractDefaultIssue.java
deleted file mode 100644 (file)
index 8705bf2..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.issue;
-
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.issue.Issue.Flow;
-import org.sonar.api.batch.sensor.issue.IssueLocation;
-import org.sonar.api.batch.sensor.issue.NewIssueLocation;
-import org.sonar.api.impl.fs.DefaultInputDir;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.sensor.DefaultStorable;
-import org.sonar.api.utils.PathUtils;
-
-import static java.util.Collections.unmodifiableList;
-import static java.util.stream.Collectors.toList;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> extends DefaultStorable {
-  protected IssueLocation primaryLocation;
-  protected List<List<IssueLocation>> flows = new ArrayList<>();
-  protected DefaultInputProject project;
-
-  protected AbstractDefaultIssue(DefaultInputProject project) {
-    this(project, null);
-  }
-
-  public AbstractDefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
-    super(storage);
-    this.project = project;
-  }
-
-  public IssueLocation primaryLocation() {
-    return primaryLocation;
-  }
-
-  public List<Flow> flows() {
-    return this.flows.stream()
-      .<Flow>map(l -> () -> unmodifiableList(new ArrayList<>(l)))
-      .collect(toList());
-  }
-
-  public NewIssueLocation newLocation() {
-    return new DefaultIssueLocation();
-  }
-
-  public T at(NewIssueLocation primaryLocation) {
-    checkArgument(primaryLocation != null, "Cannot use a location that is null");
-    checkState(this.primaryLocation == null, "at() already called");
-    this.primaryLocation = rewriteLocation((DefaultIssueLocation) primaryLocation);
-    checkArgument(this.primaryLocation.inputComponent() != null, "Cannot use a location with no input component");
-    return (T) this;
-  }
-
-  public T addLocation(NewIssueLocation secondaryLocation) {
-    flows.add(Collections.singletonList(rewriteLocation((DefaultIssueLocation) secondaryLocation)));
-    return (T) this;
-  }
-
-  public T addFlow(Iterable<NewIssueLocation> locations) {
-    List<IssueLocation> flowAsList = new ArrayList<>();
-    for (NewIssueLocation issueLocation : locations) {
-      flowAsList.add(rewriteLocation((DefaultIssueLocation) issueLocation));
-    }
-    flows.add(flowAsList);
-    return (T) this;
-  }
-
-  private DefaultIssueLocation rewriteLocation(DefaultIssueLocation location) {
-    InputComponent component = location.inputComponent();
-    Optional<Path> dirOrModulePath = Optional.empty();
-
-    if (component instanceof DefaultInputDir) {
-      DefaultInputDir dirComponent = (DefaultInputDir) component;
-      dirOrModulePath = Optional.of(project.getBaseDir().relativize(dirComponent.path()));
-    } else if (component instanceof DefaultInputModule && !Objects.equals(project.key(), component.key())) {
-      DefaultInputModule moduleComponent = (DefaultInputModule) component;
-      dirOrModulePath = Optional.of(project.getBaseDir().relativize(moduleComponent.getBaseDir()));
-    }
-
-    if (dirOrModulePath.isPresent()) {
-      String path = PathUtils.sanitize(dirOrModulePath.get().toString());
-      DefaultIssueLocation fixedLocation = new DefaultIssueLocation();
-      fixedLocation.on(project);
-      StringBuilder fullMessage = new StringBuilder();
-      if (path != null && !path.isEmpty()) {
-        fullMessage.append("[").append(path).append("] ");
-      }
-      fullMessage.append(location.message());
-      fixedLocation.message(fullMessage.toString());
-      return fixedLocation;
-    } else {
-      return location;
-    }
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssue.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssue.java
deleted file mode 100644 (file)
index aebe8f9..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.issue;
-
-import javax.annotation.Nullable;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.IssueLocation;
-import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.rule.RuleKey;
-
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements Issue, NewIssue {
-  private RuleKey ruleKey;
-  private Double gap;
-  private Severity overriddenSeverity;
-
-  public DefaultIssue(DefaultInputProject project) {
-    this(project, null);
-  }
-
-  public DefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
-    super(project, storage);
-  }
-
-  public DefaultIssue forRule(RuleKey ruleKey) {
-    this.ruleKey = ruleKey;
-    return this;
-  }
-
-  public RuleKey ruleKey() {
-    return this.ruleKey;
-  }
-
-  @Override
-  public DefaultIssue gap(@Nullable Double gap) {
-    checkArgument(gap == null || gap >= 0, format("Gap must be greater than or equal 0 (got %s)", gap));
-    this.gap = gap;
-    return this;
-  }
-
-  @Override
-  public DefaultIssue overrideSeverity(@Nullable Severity severity) {
-    this.overriddenSeverity = severity;
-    return this;
-  }
-
-  @Override
-  public Severity overriddenSeverity() {
-    return this.overriddenSeverity;
-  }
-
-  @Override
-  public Double gap() {
-    return this.gap;
-  }
-
-  @Override
-  public IssueLocation primaryLocation() {
-    return primaryLocation;
-  }
-
-  @Override
-  public void doSave() {
-    requireNonNull(this.ruleKey, "ruleKey is mandatory on issue");
-    checkState(primaryLocation != null, "Primary location is mandatory on every issue");
-    storage.store(this);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssueLocation.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssueLocation.java
deleted file mode 100644 (file)
index 6b2329c..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.issue;
-
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.issue.IssueLocation;
-import org.sonar.api.batch.sensor.issue.NewIssueLocation;
-import org.sonar.api.impl.fs.DefaultInputFile;
-
-import static java.util.Objects.requireNonNull;
-import static org.apache.commons.lang.StringUtils.abbreviate;
-import static org.apache.commons.lang.StringUtils.trim;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultIssueLocation implements NewIssueLocation, IssueLocation {
-
-  private InputComponent component;
-  private TextRange textRange;
-  private String message;
-
-  @Override
-  public DefaultIssueLocation on(InputComponent component) {
-    checkArgument(component != null, "Component can't be null");
-    checkState(this.component == null, "on() already called");
-    this.component = component;
-    return this;
-  }
-
-  @Override
-  public DefaultIssueLocation at(TextRange location) {
-    checkState(this.component != null, "at() should be called after on()");
-    checkState(this.component.isFile(), "at() should be called only for an InputFile.");
-    DefaultInputFile file = (DefaultInputFile) this.component;
-    file.validate(location);
-    this.textRange = location;
-    return this;
-  }
-
-  @Override
-  public DefaultIssueLocation message(String message) {
-    requireNonNull(message, "Message can't be null");
-    if (message.contains("\u0000")) {
-      throw new IllegalArgumentException(unsupportedCharacterError(message, component));
-    }
-    this.message = abbreviate(trim(message), MESSAGE_MAX_SIZE);
-    return this;
-  }
-
-  private static String unsupportedCharacterError(String message, @Nullable InputComponent component) {
-    String error = "Character \\u0000 is not supported in issue message '" + message + "'";
-    if (component != null) {
-      error += ", on component: " + component.toString();
-    }
-    return error;
-  }
-
-  @Override
-  public InputComponent inputComponent() {
-    return this.component;
-  }
-
-  @Override
-  public TextRange textRange() {
-    return textRange;
-  }
-
-  @Override
-  public String message() {
-    return this.message;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultNoSonarFilter.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultNoSonarFilter.java
deleted file mode 100644 (file)
index 3bef1e9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.issue;
-
-import java.util.Set;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.issue.NoSonarFilter;
-import org.sonar.api.impl.fs.DefaultInputFile;
-
-public class DefaultNoSonarFilter extends NoSonarFilter {
-  public NoSonarFilter noSonarInFile(InputFile inputFile, Set<Integer> noSonarLines) {
-    ((DefaultInputFile) inputFile).noSonarAt(noSonarLines);
-    return this;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/package-info.java
deleted file mode 100644 (file)
index 8d4146c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.impl.issue;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/ActiveRulesBuilder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/ActiveRulesBuilder.java
deleted file mode 100644 (file)
index 318a473..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.rule;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.NewActiveRule;
-import org.sonar.api.rule.RuleKey;
-
-/**
- * Builds instances of {@link org.sonar.api.batch.rule.ActiveRules}.
- * <b>For unit testing and internal use only</b>.
- *
- * @since 4.2
- */
-public class ActiveRulesBuilder {
-
-  private final Map<RuleKey, NewActiveRule> map = new LinkedHashMap<>();
-
-  public ActiveRulesBuilder addRule(NewActiveRule newActiveRule) {
-    if (map.containsKey(newActiveRule.ruleKey())) {
-      throw new IllegalStateException(String.format("Rule '%s' is already activated", newActiveRule.ruleKey()));
-    }
-    map.put(newActiveRule.ruleKey(), newActiveRule);
-    return this;
-  }
-
-  public ActiveRules build() {
-    return new DefaultActiveRules(map.values());
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultActiveRules.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultActiveRules.java
deleted file mode 100644 (file)
index 9add14c..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.rule;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.rule.ActiveRule;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.DefaultActiveRule;
-import org.sonar.api.batch.rule.NewActiveRule;
-import org.sonar.api.rule.RuleKey;
-
-@Immutable
-public class DefaultActiveRules implements ActiveRules {
-  private final Map<String, List<ActiveRule>> activeRulesByRepository = new HashMap<>();
-  private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndKey = new HashMap<>();
-  private final Map<String, Map<String, ActiveRule>> activeRulesByRepositoryAndInternalKey = new HashMap<>();
-  private final Map<String, List<ActiveRule>> activeRulesByLanguage = new HashMap<>();
-
-  public DefaultActiveRules(Collection<NewActiveRule> newActiveRules) {
-    for (NewActiveRule newAR : newActiveRules) {
-      DefaultActiveRule ar = new DefaultActiveRule(newAR);
-      String repo = ar.ruleKey().repository();
-      activeRulesByRepository.computeIfAbsent(repo, x -> new ArrayList<>()).add(ar);
-      if (ar.language() != null) {
-        activeRulesByLanguage.computeIfAbsent(ar.language(), x -> new ArrayList<>()).add(ar);
-      }
-
-      activeRulesByRepositoryAndKey.computeIfAbsent(repo, r -> new HashMap<>()).put(ar.ruleKey().rule(), ar);
-      String internalKey = ar.internalKey();
-      if (internalKey != null) {
-        activeRulesByRepositoryAndInternalKey.computeIfAbsent(repo, r -> new HashMap<>()).put(internalKey, ar);
-      }
-    }
-  }
-
-  @Override
-  public ActiveRule find(RuleKey ruleKey) {
-    return activeRulesByRepositoryAndKey.getOrDefault(ruleKey.repository(), Collections.emptyMap())
-      .get(ruleKey.rule());
-  }
-
-  @Override
-  public Collection<ActiveRule> findAll() {
-    return activeRulesByRepository.entrySet().stream().flatMap(x -> x.getValue().stream()).collect(Collectors.toList());
-  }
-
-  @Override
-  public Collection<ActiveRule> findByRepository(String repository) {
-    return activeRulesByRepository.getOrDefault(repository, Collections.emptyList());
-  }
-
-  @Override
-  public Collection<ActiveRule> findByLanguage(String language) {
-    return activeRulesByLanguage.getOrDefault(language, Collections.emptyList());
-  }
-
-  @Override
-  public ActiveRule findByInternalKey(String repository, String internalKey) {
-    return activeRulesByRepositoryAndInternalKey.containsKey(repository) ? activeRulesByRepositoryAndInternalKey.get(repository).get(internalKey) : null;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultRules.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultRules.java
deleted file mode 100644 (file)
index c7c7b5e..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.rule;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.batch.rule.DefaultRule;
-import org.sonar.api.batch.rule.NewRule;
-import org.sonar.api.batch.rule.Rule;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.rule.RuleKey;
-
-@Immutable
-class DefaultRules implements Rules {
-  private final Map<String, List<Rule>> rulesByRepository;
-  private final Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKey;
-  private final Map<RuleKey, Rule> rulesByRuleKey;
-
-  DefaultRules(Collection<NewRule> newRules) {
-    Map<String, List<Rule>> rulesByRepositoryBuilder = new HashMap<>();
-    Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKeyBuilder = new HashMap<>();
-    Map<RuleKey, Rule> rulesByRuleKeyBuilder = new HashMap<>();
-
-    for (NewRule newRule : newRules) {
-      DefaultRule r = new DefaultRule(newRule);
-      rulesByRuleKeyBuilder.put(r.key(), r);
-      rulesByRepositoryBuilder.computeIfAbsent(r.key().repository(), x -> new ArrayList<>()).add(r);
-      addToTable(rulesByRepositoryAndInternalKeyBuilder, r);
-    }
-
-    rulesByRuleKey = Collections.unmodifiableMap(rulesByRuleKeyBuilder);
-    rulesByRepository = Collections.unmodifiableMap(rulesByRepositoryBuilder);
-    rulesByRepositoryAndInternalKey = Collections.unmodifiableMap(rulesByRepositoryAndInternalKeyBuilder);
-  }
-
-  private static void addToTable(Map<String, Map<String, List<Rule>>> rulesByRepositoryAndInternalKeyBuilder, DefaultRule r) {
-    if (r.internalKey() == null) {
-      return;
-    }
-
-    rulesByRepositoryAndInternalKeyBuilder
-      .computeIfAbsent(r.key().repository(), x -> new HashMap<>())
-      .computeIfAbsent(r.internalKey(), x -> new ArrayList<>())
-      .add(r);
-  }
-
-  @Override
-  public Rule find(RuleKey ruleKey) {
-    return rulesByRuleKey.get(ruleKey);
-  }
-
-  @Override
-  public Collection<Rule> findAll() {
-    return rulesByRepository.values().stream().flatMap(List::stream).collect(Collectors.toList());
-  }
-
-  @Override
-  public Collection<Rule> findByRepository(String repository) {
-    return rulesByRepository.getOrDefault(repository, Collections.emptyList());
-  }
-
-  @Override
-  public Collection<Rule> findByInternalKey(String repository, String internalKey) {
-    return rulesByRepositoryAndInternalKey
-      .getOrDefault(repository, Collections.emptyMap())
-      .getOrDefault(internalKey, Collections.emptyList());
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/RulesBuilder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/RulesBuilder.java
deleted file mode 100644 (file)
index 36c84be..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.rule;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.sonar.api.batch.rule.NewRule;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.rule.RuleKey;
-
-/**
- * For unit testing and internal use only.
- *
- * @since 4.2
- */
-
-public class RulesBuilder {
-
-  private final Map<RuleKey, NewRule> map = new HashMap<>();
-
-  public NewRule add(RuleKey key) {
-    if (map.containsKey(key)) {
-      throw new IllegalStateException(String.format("Rule '%s' already exists", key));
-    }
-    NewRule newRule = new NewRule(key);
-    map.put(key, newRule);
-    return newRule;
-  }
-
-  public Rules build() {
-    return new DefaultRules(map.values());
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAdHocRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAdHocRule.java
deleted file mode 100644 (file)
index 1513fa2..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.rule.AdHocRule;
-import org.sonar.api.batch.sensor.rule.NewAdHocRule;
-import org.sonar.api.rules.RuleType;
-
-import static org.apache.commons.lang.StringUtils.isNotBlank;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultAdHocRule extends DefaultStorable implements AdHocRule, NewAdHocRule {
-  private Severity severity;
-  private RuleType type;
-  private String name;
-  private String description;
-  private String engineId;
-  private String ruleId;
-
-  public DefaultAdHocRule() {
-    super(null);
-  }
-
-  public DefaultAdHocRule(@Nullable SensorStorage storage) {
-    super(storage);
-  }
-
-  @Override
-  public DefaultAdHocRule severity(Severity severity) {
-    this.severity = severity;
-    return this;
-  }
-
-  @Override
-  public String engineId() {
-    return engineId;
-  }
-
-  @Override
-  public String ruleId() {
-    return ruleId;
-  }
-
-  @Override
-  public String name() {
-    return name;
-  }
-
-  @CheckForNull
-  @Override
-  public String description() {
-    return description;
-  }
-
-  @Override
-  public Severity severity() {
-    return this.severity;
-  }
-
-  @Override
-  public void doSave() {
-    checkState(isNotBlank(engineId), "Engine id is mandatory on ad hoc rule");
-    checkState(isNotBlank(ruleId), "Rule id is mandatory on ad hoc rule");
-    checkState(isNotBlank(name), "Name is mandatory on every ad hoc rule");
-    checkState(severity != null, "Severity is mandatory on every ad hoc rule");
-    checkState(type != null, "Type is mandatory on every ad hoc rule");
-    storage.store(this);
-  }
-
-  @Override
-  public RuleType type() {
-    return type;
-  }
-
-  @Override
-  public DefaultAdHocRule engineId(String engineId) {
-    this.engineId = engineId;
-    return this;
-  }
-
-  @Override
-  public DefaultAdHocRule ruleId(String ruleId) {
-    this.ruleId = ruleId;
-    return this;
-  }
-
-  @Override
-  public DefaultAdHocRule name(String name) {
-    this.name = name;
-    return this;
-  }
-
-  @Override
-  public DefaultAdHocRule description(@Nullable String description) {
-    this.description = description;
-    return this;
-  }
-
-  @Override
-  public DefaultAdHocRule type(RuleType type) {
-    this.type = type;
-    return this;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAnalysisError.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAnalysisError.java
deleted file mode 100644 (file)
index 5508461..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextPointer;
-import org.sonar.api.batch.sensor.error.AnalysisError;
-import org.sonar.api.batch.sensor.error.NewAnalysisError;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultAnalysisError extends DefaultStorable implements NewAnalysisError, AnalysisError {
-  private InputFile inputFile;
-  private String message;
-  private TextPointer location;
-
-  public DefaultAnalysisError() {
-    super(null);
-  }
-
-  public DefaultAnalysisError(SensorStorage storage) {
-    super(storage);
-  }
-
-  @Override
-  public InputFile inputFile() {
-    return inputFile;
-  }
-
-  @Override
-  public String message() {
-    return message;
-  }
-
-  @Override
-  public TextPointer location() {
-    return location;
-  }
-
-  @Override
-  public NewAnalysisError onFile(InputFile inputFile) {
-    checkArgument(inputFile != null, "Cannot use a inputFile that is null");
-    checkState(this.inputFile == null, "onFile() already called");
-    this.inputFile = inputFile;
-    return this;
-  }
-
-  @Override
-  public NewAnalysisError message(String message) {
-    this.message = message;
-    return this;
-  }
-
-  @Override
-  public NewAnalysisError at(TextPointer location) {
-    checkState(this.location == null, "at() already called");
-    this.location = location;
-    return this;
-  }
-
-  @Override
-  protected void doSave() {
-    requireNonNull(this.inputFile, "inputFile is mandatory on AnalysisError");
-    storage.store(this);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCoverage.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCoverage.java
deleted file mode 100644 (file)
index c4149ec..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.Collections;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.coverage.CoverageType;
-import org.sonar.api.batch.sensor.coverage.NewCoverage;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.DefaultInputFile;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultCoverage extends DefaultStorable implements NewCoverage {
-
-  private InputFile inputFile;
-  private CoverageType type;
-  private int totalCoveredLines = 0;
-  private int totalConditions = 0;
-  private int totalCoveredConditions = 0;
-  private SortedMap<Integer, Integer> hitsByLine = new TreeMap<>();
-  private SortedMap<Integer, Integer> conditionsByLine = new TreeMap<>();
-  private SortedMap<Integer, Integer> coveredConditionsByLine = new TreeMap<>();
-
-  public DefaultCoverage() {
-    super();
-  }
-
-  public DefaultCoverage(@Nullable SensorStorage storage) {
-    super(storage);
-  }
-
-  @Override
-  public DefaultCoverage onFile(InputFile inputFile) {
-    this.inputFile = inputFile;
-    return this;
-  }
-
-  public InputFile inputFile() {
-    return inputFile;
-  }
-
-  @Override
-  public NewCoverage ofType(CoverageType type) {
-    this.type = requireNonNull(type, "type can't be null");
-    return this;
-  }
-
-  public CoverageType type() {
-    return type;
-  }
-
-  @Override
-  public NewCoverage lineHits(int line, int hits) {
-    validateFile();
-    if (isExcluded()) {
-      return this;
-    }
-    validateLine(line);
-
-    if (!hitsByLine.containsKey(line)) {
-      hitsByLine.put(line, hits);
-      if (hits > 0) {
-        totalCoveredLines += 1;
-      }
-    }
-    return this;
-  }
-
-  private void validateLine(int line) {
-    checkState(line <= inputFile.lines(), "Line %s is out of range in the file %s (lines: %s)", line, inputFile, inputFile.lines());
-    checkState(line > 0, "Line number must be strictly positive: %s", line);
-  }
-
-  private void validateFile() {
-    requireNonNull(inputFile, "Call onFile() first");
-  }
-
-  @Override
-  public NewCoverage conditions(int line, int conditions, int coveredConditions) {
-    validateFile();
-    if (isExcluded()) {
-      return this;
-    }
-    validateLine(line);
-
-    if (conditions > 0 && !conditionsByLine.containsKey(line)) {
-      totalConditions += conditions;
-      totalCoveredConditions += coveredConditions;
-      conditionsByLine.put(line, conditions);
-      coveredConditionsByLine.put(line, coveredConditions);
-    }
-    return this;
-  }
-
-  public int coveredLines() {
-    return totalCoveredLines;
-  }
-
-  public int linesToCover() {
-    return hitsByLine.size();
-  }
-
-  public int conditions() {
-    return totalConditions;
-  }
-
-  public int coveredConditions() {
-    return totalCoveredConditions;
-  }
-
-  public SortedMap<Integer, Integer> hitsByLine() {
-    return Collections.unmodifiableSortedMap(hitsByLine);
-  }
-
-  public SortedMap<Integer, Integer> conditionsByLine() {
-    return Collections.unmodifiableSortedMap(conditionsByLine);
-  }
-
-  public SortedMap<Integer, Integer> coveredConditionsByLine() {
-    return Collections.unmodifiableSortedMap(coveredConditionsByLine);
-  }
-
-  @Override
-  public void doSave() {
-    validateFile();
-    if (!isExcluded()) {
-      storage.store(this);
-    }
-  }
-
-  private boolean isExcluded() {
-    return ((DefaultInputFile) inputFile).isExcludedForCoverage();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCpdTokens.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCpdTokens.java
deleted file mode 100644 (file)
index 9b789d2..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
-import org.sonar.api.batch.sensor.cpd.internal.TokensLine;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-import static java.util.Collections.unmodifiableList;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
-  private static final Logger LOG = Loggers.get(DefaultCpdTokens.class);
-  private final List<TokensLine> result = new ArrayList<>();
-  private DefaultInputFile inputFile;
-  private int startLine = Integer.MIN_VALUE;
-  private int startIndex = 0;
-  private int currentIndex = 0;
-  private StringBuilder sb = new StringBuilder();
-  private TextRange lastRange;
-  private boolean loggedTestCpdWarning = false;
-
-  public DefaultCpdTokens(SensorStorage storage) {
-    super(storage);
-  }
-
-  @Override
-  public DefaultCpdTokens onFile(InputFile inputFile) {
-    this.inputFile = (DefaultInputFile) requireNonNull(inputFile, "file can't be null");
-    return this;
-  }
-
-  public InputFile inputFile() {
-    return inputFile;
-  }
-
-  @Override
-  public NewCpdTokens addToken(int startLine, int startLineOffset, int endLine, int endLineOffset, String image) {
-    checkInputFileNotNull();
-    TextRange newRange;
-    try {
-      newRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
-    } catch (Exception e) {
-      throw new IllegalArgumentException("Unable to register token in file " + inputFile, e);
-    }
-    return addToken(newRange, image);
-  }
-
-  @Override
-  public DefaultCpdTokens addToken(TextRange range, String image) {
-    requireNonNull(range, "Range should not be null");
-    requireNonNull(image, "Image should not be null");
-    checkInputFileNotNull();
-    if (isExcludedForDuplication()) {
-      return this;
-    }
-    checkState(lastRange == null || lastRange.end().compareTo(range.start()) <= 0,
-      "Tokens of file %s should be provided in order.\nPrevious token: %s\nLast token: %s", inputFile, lastRange, range);
-
-    int line = range.start().line();
-    if (line != startLine) {
-      addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
-      startIndex = currentIndex + 1;
-      startLine = line;
-    }
-    currentIndex++;
-    sb.append(image);
-    lastRange = range;
-
-    return this;
-  }
-
-  private boolean isExcludedForDuplication() {
-    if (inputFile.isExcludedForDuplication()) {
-      return true;
-    }
-    if (inputFile.type() == InputFile.Type.TEST) {
-      if (!loggedTestCpdWarning) {
-        LOG.warn("Duplication reported for '{}' will be ignored because it's a test file.", inputFile);
-        loggedTestCpdWarning = true;
-      }
-      return true;
-    }
-    return false;
-  }
-
-  public List<TokensLine> getTokenLines() {
-    return unmodifiableList(new ArrayList<>(result));
-  }
-
-  private static void addNewTokensLine(List<TokensLine> result, int startUnit, int endUnit, int startLine, StringBuilder sb) {
-    if (sb.length() != 0) {
-      result.add(new TokensLine(startUnit, endUnit, startLine, sb.toString()));
-      sb.setLength(0);
-    }
-  }
-
-  @Override
-  protected void doSave() {
-    checkState(inputFile != null, "Call onFile() first");
-    if (isExcludedForDuplication()) {
-      return;
-    }
-    addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
-    storage.store(this);
-  }
-
-  private void checkInputFileNotNull() {
-    checkState(inputFile != null, "Call onFile() first");
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultExternalIssue.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultExternalIssue.java
deleted file mode 100644 (file)
index ae17adb..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import javax.annotation.Nullable;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.issue.ExternalIssue;
-import org.sonar.api.batch.sensor.issue.NewExternalIssue;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.issue.AbstractDefaultIssue;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleType;
-
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIssue> implements ExternalIssue, NewExternalIssue {
-  private Long effort;
-  private Severity severity;
-  private RuleType type;
-  private String engineId;
-  private String ruleId;
-
-  public DefaultExternalIssue(DefaultInputProject project) {
-    this(project, null);
-  }
-
-  public DefaultExternalIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
-    super(project, storage);
-  }
-
-  @Override
-  public DefaultExternalIssue remediationEffortMinutes(@Nullable Long effort) {
-    checkArgument(effort == null || effort >= 0, format("effort must be greater than or equal 0 (got %s)", effort));
-    this.effort = effort;
-    return this;
-  }
-
-  @Override
-  public DefaultExternalIssue severity(Severity severity) {
-    this.severity = severity;
-    return this;
-  }
-
-  @Override
-  public String engineId() {
-    return engineId;
-  }
-
-  @Override
-  public String ruleId() {
-    return ruleId;
-  }
-
-  @Override
-  public Severity severity() {
-    return this.severity;
-  }
-
-  @Override
-  public Long remediationEffort() {
-    return this.effort;
-  }
-
-  @Override
-  public void doSave() {
-    requireNonNull(this.engineId, "Engine id is mandatory on external issue");
-    requireNonNull(this.ruleId, "Rule id is mandatory on external issue");
-    checkState(primaryLocation != null, "Primary location is mandatory on every external issue");
-    checkState(primaryLocation.inputComponent().isFile(), "External issues must be located in files");
-    checkState(primaryLocation.message() != null, "External issues must have a message");
-    checkState(severity != null, "Severity is mandatory on every external issue");
-    checkState(type != null, "Type is mandatory on every external issue");
-    storage.store(this);
-  }
-
-  @Override
-  public RuleType type() {
-    return type;
-  }
-
-  @Override
-  public NewExternalIssue engineId(String engineId) {
-    this.engineId = engineId;
-    return this;
-  }
-
-  @Override
-  public NewExternalIssue ruleId(String ruleId) {
-    this.ruleId = ruleId;
-    return this;
-  }
-
-  @Override
-  public DefaultExternalIssue forRule(RuleKey ruleKey) {
-    this.engineId = ruleKey.repository();
-    this.ruleId = ruleKey.rule();
-    return this;
-  }
-
-  @Override
-  public RuleKey ruleKey() {
-    if (engineId != null && ruleId != null) {
-      return RuleKey.of(RuleKey.EXTERNAL_RULE_REPO_PREFIX + engineId, ruleId);
-    }
-    return null;
-  }
-
-  @Override
-  public DefaultExternalIssue type(RuleType type) {
-    this.type = type;
-    return this;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultHighlighting.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultHighlighting.java
deleted file mode 100644 (file)
index c7e133d..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.DefaultInputFile;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultHighlighting extends DefaultStorable implements NewHighlighting {
-
-  private final List<SyntaxHighlightingRule> syntaxHighlightingRules;
-  private DefaultInputFile inputFile;
-
-  public DefaultHighlighting(SensorStorage storage) {
-    super(storage);
-    syntaxHighlightingRules = new ArrayList<>();
-  }
-
-  public List<SyntaxHighlightingRule> getSyntaxHighlightingRuleSet() {
-    return syntaxHighlightingRules;
-  }
-
-  private void checkOverlappingBoundaries() {
-    if (syntaxHighlightingRules.size() > 1) {
-      Iterator<SyntaxHighlightingRule> it = syntaxHighlightingRules.iterator();
-      SyntaxHighlightingRule previous = it.next();
-      while (it.hasNext()) {
-        SyntaxHighlightingRule current = it.next();
-        if (previous.range().end().compareTo(current.range().start()) > 0 && (previous.range().end().compareTo(current.range().end()) < 0)) {
-          String errorMsg = String.format("Cannot register highlighting rule for characters at %s as it " +
-            "overlaps at least one existing rule", current.range());
-          throw new IllegalStateException(errorMsg);
-        }
-        previous = current;
-      }
-    }
-  }
-
-  @Override
-  public DefaultHighlighting onFile(InputFile inputFile) {
-    requireNonNull(inputFile, "file can't be null");
-    this.inputFile = (DefaultInputFile) inputFile;
-    return this;
-  }
-
-  public InputFile inputFile() {
-    return inputFile;
-  }
-
-  @Override
-  public DefaultHighlighting highlight(int startOffset, int endOffset, TypeOfText typeOfText) {
-    checkInputFileNotNull();
-    TextRange newRange;
-    try {
-      newRange = inputFile.newRange(startOffset, endOffset);
-    } catch (Exception e) {
-      throw new IllegalArgumentException("Unable to highlight file " + inputFile, e);
-    }
-    return highlight(newRange, typeOfText);
-  }
-
-  @Override
-  public DefaultHighlighting highlight(int startLine, int startLineOffset, int endLine, int endLineOffset, TypeOfText typeOfText) {
-    checkInputFileNotNull();
-    TextRange newRange;
-    try {
-      newRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
-    } catch (Exception e) {
-      throw new IllegalArgumentException("Unable to highlight file " + inputFile, e);
-    }
-    return highlight(newRange, typeOfText);
-  }
-
-  @Override
-  public DefaultHighlighting highlight(TextRange range, TypeOfText typeOfText) {
-    SyntaxHighlightingRule syntaxHighlightingRule = SyntaxHighlightingRule.create(range, typeOfText);
-    this.syntaxHighlightingRules.add(syntaxHighlightingRule);
-    return this;
-  }
-
-  @Override
-  protected void doSave() {
-    checkInputFileNotNull();
-    // Sort rules to avoid variation during consecutive runs
-    Collections.sort(syntaxHighlightingRules, (left, right) -> {
-      int result = left.range().start().compareTo(right.range().start());
-      if (result == 0) {
-        result = right.range().end().compareTo(left.range().end());
-      }
-      return result;
-    });
-    checkOverlappingBoundaries();
-    storage.store(this);
-  }
-
-  private void checkInputFileNotNull() {
-    checkState(inputFile != null, "Call onFile() first");
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultMeasure.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultMeasure.java
deleted file mode 100644 (file)
index d2919ab..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.io.Serializable;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.builder.EqualsBuilder;
-import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.measure.Metric;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.NewMeasure;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
-
-  private InputComponent component;
-  private Metric<G> metric;
-  private G value;
-  private boolean fromCore = false;
-
-  public DefaultMeasure() {
-    super();
-  }
-
-  public DefaultMeasure(@Nullable SensorStorage storage) {
-    super(storage);
-  }
-
-  @Override
-  public DefaultMeasure<G> on(InputComponent component) {
-    checkArgument(component != null, "Component can't be null");
-    checkState(this.component == null, "on() already called");
-    this.component = component;
-    return this;
-  }
-
-  @Override
-  public DefaultMeasure<G> forMetric(Metric<G> metric) {
-    checkState(this.metric == null, "Metric already defined");
-    requireNonNull(metric, "metric should be non null");
-    this.metric = metric;
-    return this;
-  }
-
-  @Override
-  public DefaultMeasure<G> withValue(G value) {
-    checkState(this.value == null, "Measure value already defined");
-    requireNonNull(value, "Measure value can't be null");
-    this.value = value;
-    return this;
-  }
-
-  /**
-   * For internal use.
-   */
-  public boolean isFromCore() {
-    return fromCore;
-  }
-
-  /**
-   * For internal use. Used by core components to bypass check that prevent a plugin to store core measures.
-   */
-  public DefaultMeasure<G> setFromCore() {
-    this.fromCore = true;
-    return this;
-  }
-
-  @Override
-  public void doSave() {
-    requireNonNull(this.value, "Measure value can't be null");
-    requireNonNull(this.metric, "Measure metric can't be null");
-    checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type %s", this.metric.valueType());
-    storage.store(this);
-  }
-
-  @Override
-  public Metric<G> metric() {
-    return metric;
-  }
-
-  @Override
-  public InputComponent inputComponent() {
-    return component;
-  }
-
-  @Override
-  public G value() {
-    return value;
-  }
-
-  // For testing purpose
-
-  @Override
-  public boolean equals(Object obj) {
-    if (obj == null) {
-      return false;
-    }
-    if (obj == this) {
-      return true;
-    }
-    if (obj.getClass() != getClass()) {
-      return false;
-    }
-    DefaultMeasure<?> rhs = (DefaultMeasure<?>) obj;
-    return new EqualsBuilder()
-      .append(component, rhs.component)
-      .append(metric, rhs.metric)
-      .append(value, rhs.value)
-      .isEquals();
-  }
-
-  @Override
-  public int hashCode() {
-    return new HashCodeBuilder(27, 45).append(component).append(metric).append(value).toHashCode();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultPostJobDescriptor.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultPostJobDescriptor.java
deleted file mode 100644 (file)
index 152c571..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.Arrays;
-import java.util.Collection;
-import org.sonar.api.batch.postjob.PostJobDescriptor;
-
-public class DefaultPostJobDescriptor implements PostJobDescriptor {
-
-  private String name;
-  private String[] properties = new String[0];
-
-  public String name() {
-    return name;
-  }
-
-  public Collection<String> properties() {
-    return Arrays.asList(properties);
-  }
-
-  @Override
-  public DefaultPostJobDescriptor name(String name) {
-    this.name = name;
-    return this;
-  }
-
-  @Override
-  public DefaultPostJobDescriptor requireProperty(String... propertyKey) {
-    return requireProperties(propertyKey);
-  }
-
-  @Override
-  public DefaultPostJobDescriptor requireProperties(String... propertyKeys) {
-    this.properties = propertyKeys;
-    return this;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSensorDescriptor.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSensorDescriptor.java
deleted file mode 100644 (file)
index 5b60ac2..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.function.Predicate;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.config.Configuration;
-
-import static java.util.Arrays.asList;
-
-public class DefaultSensorDescriptor implements SensorDescriptor {
-
-  private String name;
-  private String[] languages = new String[0];
-  private InputFile.Type type = null;
-  private String[] ruleRepositories = new String[0];
-  private boolean global = false;
-  private Predicate<Configuration> configurationPredicate;
-
-  public String name() {
-    return name;
-  }
-
-  public Collection<String> languages() {
-    return Arrays.asList(languages);
-  }
-
-  @Nullable
-  public InputFile.Type type() {
-    return type;
-  }
-
-  public Collection<String> ruleRepositories() {
-    return Arrays.asList(ruleRepositories);
-  }
-
-  public Predicate<Configuration> configurationPredicate() {
-    return configurationPredicate;
-  }
-
-  public boolean isGlobal() {
-    return global;
-  }
-
-  @Override
-  public DefaultSensorDescriptor name(String name) {
-    this.name = name;
-    return this;
-  }
-
-  @Override
-  public DefaultSensorDescriptor onlyOnLanguage(String languageKey) {
-    return onlyOnLanguages(languageKey);
-  }
-
-  @Override
-  public DefaultSensorDescriptor onlyOnLanguages(String... languageKeys) {
-    this.languages = languageKeys;
-    return this;
-  }
-
-  @Override
-  public DefaultSensorDescriptor onlyOnFileType(InputFile.Type type) {
-    this.type = type;
-    return this;
-  }
-
-  @Override
-  public DefaultSensorDescriptor createIssuesForRuleRepository(String... repositoryKey) {
-    return createIssuesForRuleRepositories(repositoryKey);
-  }
-
-  @Override
-  public DefaultSensorDescriptor createIssuesForRuleRepositories(String... repositoryKeys) {
-    this.ruleRepositories = repositoryKeys;
-    return this;
-  }
-
-  @Override
-  public DefaultSensorDescriptor requireProperty(String... propertyKey) {
-    return requireProperties(propertyKey);
-  }
-
-  @Override
-  public DefaultSensorDescriptor requireProperties(String... propertyKeys) {
-    this.configurationPredicate = config -> asList(propertyKeys).stream().allMatch(config::hasKey);
-    return this;
-  }
-
-  @Override
-  public SensorDescriptor global() {
-    this.global = true;
-    return this;
-  }
-
-  @Override
-  public SensorDescriptor onlyWhenConfiguration(Predicate<Configuration> configurationPredicate) {
-    this.configurationPredicate = configurationPredicate;
-    return this;
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSignificantCode.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSignificantCode.java
deleted file mode 100644 (file)
index 6a373ac..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.SortedMap;
-import java.util.TreeMap;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.code.NewSignificantCode;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.utils.Preconditions;
-
-public class DefaultSignificantCode extends DefaultStorable implements NewSignificantCode {
-  private SortedMap<Integer, TextRange> significantCodePerLine = new TreeMap<>();
-  private InputFile inputFile;
-
-  public DefaultSignificantCode() {
-    super();
-  }
-
-  public DefaultSignificantCode(@Nullable SensorStorage storage) {
-    super(storage);
-  }
-
-  @Override
-  public DefaultSignificantCode onFile(InputFile inputFile) {
-    this.inputFile = inputFile;
-    return this;
-  }
-
-  @Override
-  public DefaultSignificantCode addRange(TextRange range) {
-    Preconditions.checkState(this.inputFile != null, "addRange() should be called after on()");
-
-    int line = range.start().line();
-
-    Preconditions.checkArgument(line == range.end().line(), "Ranges of significant code must be located in a single line");
-    Preconditions.checkState(!significantCodePerLine.containsKey(line), "Significant code was already reported for line '%s'. Can only report once per line.", line);
-
-    significantCodePerLine.put(line, range);
-    return this;
-  }
-
-  @Override
-  protected void doSave() {
-    Preconditions.checkState(inputFile != null, "Call onFile() first");
-    storage.store(this);
-  }
-
-  public InputFile inputFile() {
-    return inputFile;
-  }
-
-  public SortedMap<Integer, TextRange> significantCodePerLine() {
-    return significantCodePerLine;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultStorable.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultStorable.java
deleted file mode 100644 (file)
index c4f6ca3..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import javax.annotation.Nullable;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public abstract class DefaultStorable {
-
-  protected final transient SensorStorage storage;
-  private transient boolean saved = false;
-
-  public DefaultStorable() {
-    this.storage = null;
-  }
-
-  public DefaultStorable(@Nullable SensorStorage storage) {
-    this.storage = storage;
-  }
-
-  public final void save() {
-    requireNonNull(this.storage, "No persister on this object");
-    checkState(!saved, "This object was already saved");
-    doSave();
-    this.saved = true;
-  }
-
-  protected abstract void doSave();
-
-  @Override
-  public String toString() {
-    return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSymbolTable.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSymbolTable.java
deleted file mode 100644 (file)
index 73ec864..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.symbol.NewSymbol;
-import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
-import org.sonar.api.impl.fs.DefaultInputFile;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class DefaultSymbolTable extends DefaultStorable implements NewSymbolTable {
-
-  private final Map<TextRange, Set<TextRange>> referencesBySymbol;
-  private DefaultInputFile inputFile;
-
-  public DefaultSymbolTable(SensorStorage storage) {
-    super(storage);
-    referencesBySymbol = new LinkedHashMap<>();
-  }
-
-  public Map<TextRange, Set<TextRange>> getReferencesBySymbol() {
-    return referencesBySymbol;
-  }
-
-  @Override
-  public DefaultSymbolTable onFile(InputFile inputFile) {
-    requireNonNull(inputFile, "file can't be null");
-    this.inputFile = (DefaultInputFile) inputFile;
-    return this;
-  }
-
-  public InputFile inputFile() {
-    return inputFile;
-  }
-
-  @Override
-  public NewSymbol newSymbol(int startLine, int startLineOffset, int endLine, int endLineOffset) {
-    checkInputFileNotNull();
-    TextRange declarationRange;
-    try {
-      declarationRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
-    } catch (Exception e) {
-      throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
-    }
-    return newSymbol(declarationRange);
-  }
-
-  @Override
-  public NewSymbol newSymbol(int startOffset, int endOffset) {
-    checkInputFileNotNull();
-    TextRange declarationRange;
-    try {
-      declarationRange = inputFile.newRange(startOffset, endOffset);
-    } catch (Exception e) {
-      throw new IllegalArgumentException("Unable to create symbol on file " + inputFile, e);
-    }
-    return newSymbol(declarationRange);
-  }
-
-  @Override
-  public NewSymbol newSymbol(TextRange range) {
-    checkInputFileNotNull();
-    TreeSet<TextRange> references = new TreeSet<>((o1, o2) -> o1.start().compareTo(o2.start()));
-    referencesBySymbol.put(range, references);
-    return new DefaultSymbol(inputFile, range, references);
-  }
-
-  private static class DefaultSymbol implements NewSymbol {
-
-    private final Collection<TextRange> references;
-    private final DefaultInputFile inputFile;
-    private final TextRange declaration;
-
-    public DefaultSymbol(DefaultInputFile inputFile, TextRange declaration, Collection<TextRange> references) {
-      this.inputFile = inputFile;
-      this.declaration = declaration;
-      this.references = references;
-    }
-
-    @Override
-    public NewSymbol newReference(int startOffset, int endOffset) {
-      TextRange referenceRange;
-      try {
-        referenceRange = inputFile.newRange(startOffset, endOffset);
-      } catch (Exception e) {
-        throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
-      }
-      return newReference(referenceRange);
-    }
-
-    @Override
-    public NewSymbol newReference(int startLine, int startLineOffset, int endLine, int endLineOffset) {
-      TextRange referenceRange;
-      try {
-        referenceRange = inputFile.newRange(startLine, startLineOffset, endLine, endLineOffset);
-      } catch (Exception e) {
-        throw new IllegalArgumentException("Unable to create symbol reference on file " + inputFile, e);
-      }
-      return newReference(referenceRange);
-    }
-
-    @Override
-    public NewSymbol newReference(TextRange range) {
-      requireNonNull(range, "Provided range is null");
-      checkArgument(!declaration.overlap(range), "Overlapping symbol declaration and reference for symbol at %s", declaration);
-      references.add(range);
-      return this;
-    }
-
-  }
-
-  @Override
-  protected void doSave() {
-    checkInputFileNotNull();
-    storage.store(this);
-  }
-
-  private void checkInputFileNotNull() {
-    checkState(inputFile != null, "Call onFile() first");
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/InMemorySensorStorage.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/InMemorySensorStorage.java
deleted file mode 100644 (file)
index 26f74db..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.sonar.api.batch.sensor.code.NewSignificantCode;
-import org.sonar.api.batch.sensor.coverage.NewCoverage;
-import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
-import org.sonar.api.batch.sensor.error.AnalysisError;
-import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.issue.ExternalIssue;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.rule.AdHocRule;
-import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
-
-import static org.sonar.api.utils.Preconditions.checkArgument;
-
-class InMemorySensorStorage implements SensorStorage {
-
-  Map<String, Map<String, Measure>> measuresByComponentAndMetric = new HashMap<>();
-
-  Collection<Issue> allIssues = new ArrayList<>();
-  Collection<ExternalIssue> allExternalIssues = new ArrayList<>();
-  Collection<AdHocRule> allAdHocRules = new ArrayList<>();
-  Collection<AnalysisError> allAnalysisErrors = new ArrayList<>();
-
-  Map<String, NewHighlighting> highlightingByComponent = new HashMap<>();
-  Map<String, DefaultCpdTokens> cpdTokensByComponent = new HashMap<>();
-  Map<String, List<DefaultCoverage>> coverageByComponent = new HashMap<>();
-  Map<String, DefaultSymbolTable> symbolsPerComponent = new HashMap<>();
-  Map<String, String> contextProperties = new HashMap<>();
-  Map<String, DefaultSignificantCode> significantCodePerComponent = new HashMap<>();
-
-  @Override
-  public void store(Measure measure) {
-    // Emulate duplicate measure check
-    String componentKey = measure.inputComponent().key();
-    String metricKey = measure.metric().key();
-    if (measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).containsKey(metricKey)) {
-      throw new IllegalStateException("Can not add the same measure twice");
-    }
-    measuresByComponentAndMetric.computeIfAbsent(componentKey, x -> new HashMap<>()).put(metricKey, measure);
-  }
-
-  @Override
-  public void store(Issue issue) {
-    allIssues.add(issue);
-  }
-
-  @Override
-  public void store(AdHocRule adHocRule) {
-    allAdHocRules.add(adHocRule);
-  }
-
-  @Override
-  public void store(NewHighlighting newHighlighting) {
-    DefaultHighlighting highlighting = (DefaultHighlighting) newHighlighting;
-    String fileKey = highlighting.inputFile().key();
-    // Emulate duplicate storage check
-    if (highlightingByComponent.containsKey(fileKey)) {
-      throw new UnsupportedOperationException("Trying to save highlighting twice for the same file is not supported: " + highlighting.inputFile());
-    }
-    highlightingByComponent.put(fileKey, highlighting);
-  }
-
-  @Override
-  public void store(NewCoverage coverage) {
-    DefaultCoverage defaultCoverage = (DefaultCoverage) coverage;
-    String fileKey = defaultCoverage.inputFile().key();
-    coverageByComponent.computeIfAbsent(fileKey, x -> new ArrayList<>()).add(defaultCoverage);
-  }
-
-  @Override
-  public void store(NewCpdTokens cpdTokens) {
-    DefaultCpdTokens defaultCpdTokens = (DefaultCpdTokens) cpdTokens;
-    String fileKey = defaultCpdTokens.inputFile().key();
-    // Emulate duplicate storage check
-    if (cpdTokensByComponent.containsKey(fileKey)) {
-      throw new UnsupportedOperationException("Trying to save CPD tokens twice for the same file is not supported: " + defaultCpdTokens.inputFile());
-    }
-    cpdTokensByComponent.put(fileKey, defaultCpdTokens);
-  }
-
-  @Override
-  public void store(NewSymbolTable newSymbolTable) {
-    DefaultSymbolTable symbolTable = (DefaultSymbolTable) newSymbolTable;
-    String fileKey = symbolTable.inputFile().key();
-    // Emulate duplicate storage check
-    if (symbolsPerComponent.containsKey(fileKey)) {
-      throw new UnsupportedOperationException("Trying to save symbol table twice for the same file is not supported: " + symbolTable.inputFile());
-    }
-    symbolsPerComponent.put(fileKey, symbolTable);
-  }
-
-  @Override
-  public void store(AnalysisError analysisError) {
-    allAnalysisErrors.add(analysisError);
-  }
-
-  @Override
-  public void storeProperty(String key, String value) {
-    checkArgument(key != null, "Key of context property must not be null");
-    checkArgument(value != null, "Value of context property must not be null");
-    contextProperties.put(key, value);
-  }
-
-  @Override
-  public void store(ExternalIssue issue) {
-    allExternalIssues.add(issue);
-  }
-
-  @Override
-  public void store(NewSignificantCode newSignificantCode) {
-    DefaultSignificantCode significantCode = (DefaultSignificantCode) newSignificantCode;
-    String fileKey = significantCode.inputFile().key();
-    // Emulate duplicate storage check
-    if (significantCodePerComponent.containsKey(fileKey)) {
-      throw new UnsupportedOperationException("Trying to save significant code information twice for the same file is not supported: " + significantCode.inputFile());
-    }
-    significantCodePerComponent.put(fileKey, significantCode);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SensorContextTester.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SensorContextTester.java
deleted file mode 100644 (file)
index 6877a77..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.io.File;
-import java.io.Serializable;
-import java.nio.charset.Charset;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Stream;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.SonarQubeSide;
-import org.sonar.api.SonarRuntime;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.code.NewSignificantCode;
-import org.sonar.api.batch.sensor.coverage.NewCoverage;
-import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
-import org.sonar.api.batch.sensor.cpd.internal.TokensLine;
-import org.sonar.api.batch.sensor.error.AnalysisError;
-import org.sonar.api.batch.sensor.error.NewAnalysisError;
-import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.batch.sensor.issue.ExternalIssue;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.NewExternalIssue;
-import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.NewMeasure;
-import org.sonar.api.batch.sensor.rule.AdHocRule;
-import org.sonar.api.batch.sensor.rule.NewAdHocRule;
-import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.ConfigurationBridge;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.issue.DefaultIssue;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
-import org.sonar.api.impl.context.MetadataLoader;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.scanner.fs.InputProject;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.Version;
-
-import static java.util.Collections.unmodifiableMap;
-
-/**
- * Utility class to help testing {@link Sensor}. This is not an API and method signature may evolve.
- * <p>
- * Usage: call {@link #create(File)} to create an "in memory" implementation of {@link SensorContext} with a filesystem initialized with provided baseDir.
- * <p>
- * You have to manually register inputFiles using:
- * <pre>
- *   sensorContextTester.fileSystem().add(new DefaultInputFile("myProjectKey", "src/Foo.java")
- * .setLanguage("java")
- * .initMetadata("public class Foo {\n}"));
- * </pre>
- * <p>
- * Then pass it to your {@link Sensor}. You can then query elements provided by your sensor using methods {@link #allIssues()}, ...
- */
-public class SensorContextTester implements SensorContext {
-
-  private Settings settings;
-  private DefaultFileSystem fs;
-  private ActiveRules activeRules;
-  private InMemorySensorStorage sensorStorage;
-  private DefaultInputProject project;
-  private DefaultInputModule module;
-  private SonarRuntime runtime;
-  private boolean cancelled;
-
-  private SensorContextTester(Path moduleBaseDir) {
-    this.settings = new MapSettings();
-    this.fs = new DefaultFileSystem(moduleBaseDir).setEncoding(Charset.defaultCharset());
-    this.activeRules = new ActiveRulesBuilder().build();
-    this.sensorStorage = new InMemorySensorStorage();
-    this.project = new DefaultInputProject(ProjectDefinition.create().setKey("projectKey").setBaseDir(moduleBaseDir.toFile()).setWorkDir(moduleBaseDir.resolve(".sonar").toFile()));
-    this.module = new DefaultInputModule(ProjectDefinition.create().setKey("projectKey").setBaseDir(moduleBaseDir.toFile()).setWorkDir(moduleBaseDir.resolve(".sonar").toFile()));
-    this.runtime = SonarRuntimeImpl.forSonarQube(MetadataLoader.loadVersion(System2.INSTANCE), SonarQubeSide.SCANNER, MetadataLoader.loadEdition(System2.INSTANCE));
-  }
-
-  public static SensorContextTester create(File moduleBaseDir) {
-    return new SensorContextTester(moduleBaseDir.toPath());
-  }
-
-  public static SensorContextTester create(Path moduleBaseDir) {
-    return new SensorContextTester(moduleBaseDir);
-  }
-
-  @Override
-  public Settings settings() {
-    return settings;
-  }
-
-  @Override
-  public Configuration config() {
-    return new ConfigurationBridge(settings);
-  }
-
-  public SensorContextTester setSettings(Settings settings) {
-    this.settings = settings;
-    return this;
-  }
-
-  @Override
-  public DefaultFileSystem fileSystem() {
-    return fs;
-  }
-
-  public SensorContextTester setFileSystem(DefaultFileSystem fs) {
-    this.fs = fs;
-    return this;
-  }
-
-  @Override
-  public ActiveRules activeRules() {
-    return activeRules;
-  }
-
-  public SensorContextTester setActiveRules(ActiveRules activeRules) {
-    this.activeRules = activeRules;
-    return this;
-  }
-
-  /**
-   * Default value is the version of this API at compilation time. You can override it
-   * using {@link #setRuntime(SonarRuntime)} to test your Sensor behaviour.
-   */
-  @Override
-  public Version getSonarQubeVersion() {
-    return runtime().getApiVersion();
-  }
-
-  /**
-   * @see #setRuntime(SonarRuntime) to override defaults (SonarQube scanner with version
-   * of this API as used at compilation time).
-   */
-  @Override
-  public SonarRuntime runtime() {
-    return runtime;
-  }
-
-  public SensorContextTester setRuntime(SonarRuntime runtime) {
-    this.runtime = runtime;
-    return this;
-  }
-
-  @Override
-  public boolean isCancelled() {
-    return cancelled;
-  }
-
-  public void setCancelled(boolean cancelled) {
-    this.cancelled = cancelled;
-  }
-
-  @Override
-  public InputModule module() {
-    return module;
-  }
-
-  @Override
-  public InputProject project() {
-    return project;
-  }
-
-  @Override
-  public <G extends Serializable> NewMeasure<G> newMeasure() {
-    return new DefaultMeasure<>(sensorStorage);
-  }
-
-  public Collection<Measure> measures(String componentKey) {
-    return sensorStorage.measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).values();
-  }
-
-  public <G extends Serializable> Measure<G> measure(String componentKey, Metric<G> metric) {
-    return measure(componentKey, metric.key());
-  }
-
-  public <G extends Serializable> Measure<G> measure(String componentKey, String metricKey) {
-    return sensorStorage.measuresByComponentAndMetric.getOrDefault(componentKey, Collections.emptyMap()).get(metricKey);
-  }
-
-  @Override
-  public NewIssue newIssue() {
-    return new DefaultIssue(project, sensorStorage);
-  }
-
-  public Collection<Issue> allIssues() {
-    return sensorStorage.allIssues;
-  }
-
-  @Override
-  public NewExternalIssue newExternalIssue() {
-    return new DefaultExternalIssue(project, sensorStorage);
-  }
-
-  @Override
-  public NewAdHocRule newAdHocRule() {
-    return new DefaultAdHocRule(sensorStorage);
-  }
-
-  public Collection<ExternalIssue> allExternalIssues() {
-    return sensorStorage.allExternalIssues;
-  }
-
-  public Collection<AdHocRule> allAdHocRules() {
-    return sensorStorage.allAdHocRules;
-  }
-
-  public Collection<AnalysisError> allAnalysisErrors() {
-    return sensorStorage.allAnalysisErrors;
-  }
-
-  @CheckForNull
-  public Integer lineHits(String fileKey, int line) {
-    return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
-      .map(c -> c.hitsByLine().get(line))
-      .flatMap(Stream::of)
-      .filter(Objects::nonNull)
-      .reduce(null, SensorContextTester::sumOrNull);
-  }
-
-  @CheckForNull
-  public static Integer sumOrNull(@Nullable Integer o1, @Nullable Integer o2) {
-    return o1 == null ? o2 : (o1 + o2);
-  }
-
-  @CheckForNull
-  public Integer conditions(String fileKey, int line) {
-    return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
-      .map(c -> c.conditionsByLine().get(line))
-      .flatMap(Stream::of)
-      .filter(Objects::nonNull)
-      .reduce(null, SensorContextTester::maxOrNull);
-  }
-
-  @CheckForNull
-  public Integer coveredConditions(String fileKey, int line) {
-    return sensorStorage.coverageByComponent.getOrDefault(fileKey, Collections.emptyList()).stream()
-      .map(c -> c.coveredConditionsByLine().get(line))
-      .flatMap(Stream::of)
-      .filter(Objects::nonNull)
-      .reduce(null, SensorContextTester::maxOrNull);
-  }
-
-  @CheckForNull
-  public TextRange significantCodeTextRange(String fileKey, int line) {
-    if (sensorStorage.significantCodePerComponent.containsKey(fileKey)) {
-      return sensorStorage.significantCodePerComponent.get(fileKey)
-        .significantCodePerLine()
-        .get(line);
-    }
-    return null;
-
-  }
-
-  @CheckForNull
-  public static Integer maxOrNull(@Nullable Integer o1, @Nullable Integer o2) {
-    return o1 == null ? o2 : Math.max(o1, o2);
-  }
-
-  @CheckForNull
-  public List<TokensLine> cpdTokens(String componentKey) {
-    DefaultCpdTokens defaultCpdTokens = sensorStorage.cpdTokensByComponent.get(componentKey);
-    return defaultCpdTokens != null ? defaultCpdTokens.getTokenLines() : null;
-  }
-
-  @Override
-  public NewHighlighting newHighlighting() {
-    return new DefaultHighlighting(sensorStorage);
-  }
-
-  @Override
-  public NewCoverage newCoverage() {
-    return new DefaultCoverage(sensorStorage);
-  }
-
-  @Override
-  public NewCpdTokens newCpdTokens() {
-    return new DefaultCpdTokens(sensorStorage);
-  }
-
-  @Override
-  public NewSymbolTable newSymbolTable() {
-    return new DefaultSymbolTable(sensorStorage);
-  }
-
-  @Override
-  public NewAnalysisError newAnalysisError() {
-    return new DefaultAnalysisError(sensorStorage);
-  }
-
-  /**
-   * Return list of syntax highlighting applied for a given position in a file. The result is a list because in theory you
-   * can apply several styles to the same range.
-   *
-   * @param componentKey Key of the file like 'myProjectKey:src/foo.php'
-   * @param line         Line you want to query
-   * @param lineOffset   Offset you want to query.
-   * @return List of styles applied to this position or empty list if there is no highlighting at this position.
-   */
-  public List<TypeOfText> highlightingTypeAt(String componentKey, int line, int lineOffset) {
-    DefaultHighlighting syntaxHighlightingData = (DefaultHighlighting) sensorStorage.highlightingByComponent.get(componentKey);
-    if (syntaxHighlightingData == null) {
-      return Collections.emptyList();
-    }
-    List<TypeOfText> result = new ArrayList<>();
-    DefaultTextPointer location = new DefaultTextPointer(line, lineOffset);
-    for (SyntaxHighlightingRule sortedRule : syntaxHighlightingData.getSyntaxHighlightingRuleSet()) {
-      if (sortedRule.range().start().compareTo(location) <= 0 && sortedRule.range().end().compareTo(location) > 0) {
-        result.add(sortedRule.getTextType());
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Return list of symbol references ranges for the symbol at a given position in a file.
-   *
-   * @param componentKey Key of the file like 'myProjectKey:src/foo.php'
-   * @param line         Line you want to query
-   * @param lineOffset   Offset you want to query.
-   * @return List of references for the symbol (potentially empty) or null if there is no symbol at this position.
-   */
-  @CheckForNull
-  public Collection<TextRange> referencesForSymbolAt(String componentKey, int line, int lineOffset) {
-    DefaultSymbolTable symbolTable = sensorStorage.symbolsPerComponent.get(componentKey);
-    if (symbolTable == null) {
-      return null;
-    }
-    DefaultTextPointer location = new DefaultTextPointer(line, lineOffset);
-    for (Map.Entry<TextRange, Set<TextRange>> symbol : symbolTable.getReferencesBySymbol().entrySet()) {
-      if (symbol.getKey().start().compareTo(location) <= 0 && symbol.getKey().end().compareTo(location) > 0) {
-        return symbol.getValue();
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public void addContextProperty(String key, String value) {
-    sensorStorage.storeProperty(key, value);
-  }
-
-  /**
-   * @return an immutable map of the context properties defined with {@link SensorContext#addContextProperty(String, String)}.
-   * @since 6.1
-   */
-  public Map<String, String> getContextProperties() {
-    return unmodifiableMap(sensorStorage.contextProperties);
-  }
-
-  @Override
-  public void markForPublishing(InputFile inputFile) {
-    DefaultInputFile file = (DefaultInputFile) inputFile;
-    file.setPublished(true);
-  }
-
-  @Override
-  public NewSignificantCode newSignificantCode() {
-    return new DefaultSignificantCode(sensorStorage);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SyntaxHighlightingRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SyntaxHighlightingRule.java
deleted file mode 100644 (file)
index 35d4fbe..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-
-public class SyntaxHighlightingRule {
-
-  private final TextRange range;
-  private final TypeOfText textType;
-
-  private SyntaxHighlightingRule(TextRange range, TypeOfText textType) {
-    this.range = range;
-    this.textType = textType;
-  }
-
-  public static SyntaxHighlightingRule create(TextRange range, TypeOfText textType) {
-    return new SyntaxHighlightingRule(range, textType);
-  }
-
-  public TextRange range() {
-    return range;
-  }
-
-  public TypeOfText getTextType() {
-    return textType;
-  }
-
-  @Override
-  public String toString() {
-    return ReflectionToStringBuilder.toString(this, ToStringStyle.SIMPLE_STYLE);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/package-info.java
deleted file mode 100644 (file)
index b304d31..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.impl.sensor;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
index 9fe35843b8ce6dc6a91324955f686c0cc6d8fe13..823828dc9d0b53ac82338ee9e671ec145dce93b6 100644 (file)
@@ -30,14 +30,14 @@ import org.sonar.api.server.rule.RulesDefinition;
 import static org.sonar.api.utils.Preconditions.checkArgument;
 
 public class DefaultNewRepository implements RulesDefinition.NewRepository {
-  private final RuleDefinitionContext context;
+  private final RulesDefinitionContext context;
   private final String key;
   private final boolean isExternal;
   private final String language;
   private String name;
   private final Map<String, RulesDefinition.NewRule> newRules = new HashMap<>();
 
-  DefaultNewRepository(RuleDefinitionContext context, String key, String language, boolean isExternal) {
+  DefaultNewRepository(RulesDefinitionContext context, String key, String language, boolean isExternal) {
     this.context = context;
     this.key = key;
     this.name = key;
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/RuleDefinitionContext.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/RuleDefinitionContext.java
deleted file mode 100644 (file)
index 7d47fc2..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.server;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.server.rule.RulesDefinition;
-
-import static java.util.Collections.emptyList;
-import static java.util.Collections.unmodifiableList;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-public class RuleDefinitionContext extends RulesDefinition.Context {
-  private final Map<String, RulesDefinition.Repository> repositoriesByKey = new HashMap<>();
-  private String currentPluginKey;
-
-  @Override
-  public RulesDefinition.NewRepository createRepository(String key, String language) {
-    return new DefaultNewRepository(this, key, language, false);
-  }
-
-  @Override
-  public RulesDefinition.NewRepository createExternalRepository(String engineId, String language) {
-    return new DefaultNewRepository(this, RuleKey.EXTERNAL_RULE_REPO_PREFIX + engineId, language, true);
-  }
-
-  @Override
-  @Deprecated
-  public RulesDefinition.NewRepository extendRepository(String key, String language) {
-    return createRepository(key, language);
-  }
-
-  @Override
-  @CheckForNull
-  public RulesDefinition.Repository repository(String key) {
-    return repositoriesByKey.get(key);
-  }
-
-  @Override
-  public List<RulesDefinition.Repository> repositories() {
-    return unmodifiableList(new ArrayList<>(repositoriesByKey.values()));
-  }
-
-  @Override
-  @Deprecated
-  public List<RulesDefinition.ExtendedRepository> extendedRepositories(String repositoryKey) {
-    return emptyList();
-  }
-
-  @Override
-  @Deprecated
-  public List<RulesDefinition.ExtendedRepository> extendedRepositories() {
-    return emptyList();
-  }
-
-  void registerRepository(DefaultNewRepository newRepository) {
-    RulesDefinition.Repository existing = repositoriesByKey.get(newRepository.key());
-    if (existing != null) {
-      String existingLanguage = existing.language();
-      checkState(existingLanguage.equals(newRepository.language()),
-        "The rule repository '%s' must not be defined for two different languages: %s and %s",
-        newRepository.key(), existingLanguage, newRepository.language());
-    }
-    repositoriesByKey.put(newRepository.key(), new DefaultRepository(newRepository, existing));
-  }
-
-  public String currentPluginKey() {
-    return currentPluginKey;
-  }
-
-  @Override
-  public void setCurrentPluginKey(@Nullable String pluginKey) {
-    this.currentPluginKey = pluginKey;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/RulesDefinitionContext.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/RulesDefinitionContext.java
new file mode 100644 (file)
index 0000000..849f598
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.impl.server;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.server.rule.RulesDefinition;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class RulesDefinitionContext extends RulesDefinition.Context {
+  private final Map<String, RulesDefinition.Repository> repositoriesByKey = new HashMap<>();
+  private String currentPluginKey;
+
+  @Override
+  public RulesDefinition.NewRepository createRepository(String key, String language) {
+    return new DefaultNewRepository(this, key, language, false);
+  }
+
+  @Override
+  public RulesDefinition.NewRepository createExternalRepository(String engineId, String language) {
+    return new DefaultNewRepository(this, RuleKey.EXTERNAL_RULE_REPO_PREFIX + engineId, language, true);
+  }
+
+  @Override
+  @Deprecated
+  public RulesDefinition.NewRepository extendRepository(String key, String language) {
+    return createRepository(key, language);
+  }
+
+  @Override
+  @CheckForNull
+  public RulesDefinition.Repository repository(String key) {
+    return repositoriesByKey.get(key);
+  }
+
+  @Override
+  public List<RulesDefinition.Repository> repositories() {
+    return unmodifiableList(new ArrayList<>(repositoriesByKey.values()));
+  }
+
+  @Override
+  @Deprecated
+  public List<RulesDefinition.ExtendedRepository> extendedRepositories(String repositoryKey) {
+    return emptyList();
+  }
+
+  @Override
+  @Deprecated
+  public List<RulesDefinition.ExtendedRepository> extendedRepositories() {
+    return emptyList();
+  }
+
+  void registerRepository(DefaultNewRepository newRepository) {
+    RulesDefinition.Repository existing = repositoriesByKey.get(newRepository.key());
+    if (existing != null) {
+      String existingLanguage = existing.language();
+      checkState(existingLanguage.equals(newRepository.language()),
+        "The rule repository '%s' must not be defined for two different languages: %s and %s",
+        newRepository.key(), existingLanguage, newRepository.language());
+    }
+    repositoriesByKey.put(newRepository.key(), new DefaultRepository(newRepository, existing));
+  }
+
+  public String currentPluginKey() {
+    return currentPluginKey;
+  }
+
+  @Override
+  public void setCurrentPluginKey(@Nullable String pluginKey) {
+    this.currentPluginKey = pluginKey;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/MetadataLoader.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/MetadataLoader.java
new file mode 100644 (file)
index 0000000..d50c429
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.internal;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Scanner;
+import org.sonar.api.SonarEdition;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.Version;
+
+import static org.apache.commons.lang.StringUtils.trimToEmpty;
+
+/**
+ * For internal use
+ *
+ * @since 7.8
+ */
+public class MetadataLoader {
+
+  private static final String VERSION_FILE_PATH = "/sonar-api-version.txt";
+  private static final String EDITION_FILE_PATH = "/sonar-edition.txt";
+
+  private MetadataLoader() {
+    // only static methods
+  }
+
+  public static Version loadVersion(System2 system) {
+    URL url = system.getResource(VERSION_FILE_PATH);
+
+    try (Scanner scanner = new Scanner(url.openStream(), StandardCharsets.UTF_8.name())) {
+      String versionInFile = scanner.nextLine();
+      return Version.parse(versionInFile);
+    } catch (IOException e) {
+      throw new IllegalStateException("Can not load " + VERSION_FILE_PATH + " from classpath ", e);
+    }
+  }
+
+  public static SonarEdition loadEdition(System2 system) {
+    URL url = system.getResource(EDITION_FILE_PATH);
+    if (url == null) {
+      return SonarEdition.COMMUNITY;
+    }
+    try (Scanner scanner = new Scanner(url.openStream(), StandardCharsets.UTF_8.name())) {
+      String editionInFile = scanner.nextLine();
+      return parseEdition(editionInFile);
+    } catch (IOException e) {
+      throw new IllegalStateException("Can not load " + EDITION_FILE_PATH + " from classpath", e);
+    }
+  }
+
+  static SonarEdition parseEdition(String edition) {
+    String str = trimToEmpty(edition.toUpperCase());
+    try {
+      return SonarEdition.valueOf(str);
+    } catch (IllegalArgumentException e) {
+      throw new IllegalStateException(String.format("Invalid edition found in '%s': '%s'", EDITION_FILE_PATH, str));
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/PluginContextImpl.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/PluginContextImpl.java
new file mode 100644 (file)
index 0000000..3fccb4c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.internal;
+
+import org.sonar.api.Plugin;
+import org.sonar.api.SonarRuntime;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.config.internal.MapSettings;
+
+/**
+ * Implementation of {@link Plugin.Context} that plugins could use in their unit tests.
+ *
+ * Example:
+ *
+ * <pre>
+ *   import org.sonar.api.internal.SonarRuntimeImpl;
+ *   import org.sonar.api.config.internal.MapSettings;
+ *
+ *   ...
+ *
+ *   SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(7, 1), SonarQubeSide.SCANNER);
+ *   MapSettings settings = new MapSettings().setProperty("foo", "bar");
+ *   Plugin.Context context = new PluginContextImpl.Builder()
+ *     .setSonarRuntime(runtime)
+ *     .setBootConfiguration(settings.asConfig());
+ *     .build();
+ * </pre>
+ *
+ * @since 7.1
+ */
+public class PluginContextImpl extends Plugin.Context {
+
+  private final Configuration bootConfiguration;
+
+  private PluginContextImpl(Builder builder) {
+    super(builder.sonarRuntime);
+    this.bootConfiguration = builder.bootConfiguration != null ? builder.bootConfiguration : new MapSettings().asConfig();
+  }
+
+  @Override
+  public Configuration getBootConfiguration() {
+    return bootConfiguration;
+  }
+
+  public static class Builder {
+    private SonarRuntime sonarRuntime;
+    private Configuration bootConfiguration;
+
+    /**
+     * Required.
+     * @see SonarRuntimeImpl
+     * @return this
+     */
+    public Builder setSonarRuntime(SonarRuntime r) {
+      this.sonarRuntime = r;
+      return this;
+    }
+
+    /**
+     * If not set, then an empty configuration is used.
+     * @return this
+     */
+    public Builder setBootConfiguration(Configuration c) {
+      this.bootConfiguration = c;
+      return this;
+    }
+
+    public Plugin.Context build() {
+      return new PluginContextImpl(this);
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java
new file mode 100644 (file)
index 0000000..3f69f36
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.internal;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.SonarEdition;
+import org.sonar.api.SonarProduct;
+import org.sonar.api.SonarQubeSide;
+import org.sonar.api.SonarRuntime;
+import org.sonar.api.utils.Version;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+
+/**
+ * @since 6.0
+ */
+@Immutable
+public class SonarRuntimeImpl implements SonarRuntime {
+
+  private final Version version;
+  private final SonarProduct product;
+  private final SonarQubeSide sonarQubeSide;
+  private final SonarEdition edition;
+
+  private SonarRuntimeImpl(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide, @Nullable SonarEdition edition) {
+    this.edition = edition;
+    requireNonNull(product);
+    checkArgument((product == SonarProduct.SONARQUBE) == (sonarQubeSide != null), "sonarQubeSide should be provided only for SonarQube product");
+    checkArgument((product == SonarProduct.SONARQUBE) == (edition != null), "edition should be provided only for SonarQube product");
+    this.version = requireNonNull(version);
+    this.product = product;
+    this.sonarQubeSide = sonarQubeSide;
+  }
+
+  @Override
+  public Version getApiVersion() {
+    return version;
+  }
+
+  @Override
+  public SonarProduct getProduct() {
+    return product;
+  }
+
+  @Override
+  public SonarQubeSide getSonarQubeSide() {
+    if (sonarQubeSide == null) {
+      throw new UnsupportedOperationException("Can only be called in SonarQube");
+    }
+    return sonarQubeSide;
+  }
+
+  @Override
+  public SonarEdition getEdition() {
+    if (sonarQubeSide == null) {
+      throw new UnsupportedOperationException("Can only be called in SonarQube");
+    }
+    return edition;
+  }
+
+  /**
+   * Create an instance for SonarQube runtime environment.
+   */
+  public static SonarRuntime forSonarQube(Version version, SonarQubeSide side, SonarEdition edition) {
+    return new SonarRuntimeImpl(version, SonarProduct.SONARQUBE, side, edition);
+  }
+
+  /**
+   * Create an instance for SonarLint runtime environment.
+   */
+  public static SonarRuntime forSonarLint(Version version) {
+    return new SonarRuntimeImpl(version, SonarProduct.SONARLINT, null, null);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/package-info.java
new file mode 100644 (file)
index 0000000..17dc122
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/charhandler/IntArrayListTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/charhandler/IntArrayListTest.java
new file mode 100644 (file)
index 0000000..c0b505a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.charhandler;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class IntArrayListTest {
+
+  @Test
+  public void addElements() {
+    IntArrayList list = new IntArrayList();
+    assertThat(list.trimAndGet()).isEmpty();
+    list.add(1);
+    list.add(2);
+    assertThat(list.trimAndGet()).containsExactly(1, 2);
+  }
+
+  @Test
+  public void trimIfNeeded() {
+    IntArrayList list = new IntArrayList();
+    list.add(1);
+    list.add(2);
+    assertThat(list.trimAndGet()).isSameAs(list.trimAndGet());
+  }
+
+  @Test
+  public void grow() {
+    // Default capacity is 10
+    IntArrayList list = new IntArrayList();
+    for (int i = 1; i <= 11; i++) {
+      list.add(i);
+    }
+    assertThat(list.trimAndGet()).hasSize(11);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultFileSystemTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultFileSystemTest.java
new file mode 100644 (file)
index 0000000..8038cba
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultFileSystemTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  private DefaultFileSystem fs;
+
+  private File basedir;
+
+  @Before
+  public void prepare() throws Exception {
+    basedir = temp.newFolder();
+    fs = new DefaultFileSystem(basedir.toPath());
+  }
+
+  @Test
+  public void test_directories() throws Exception {
+    assertThat(fs.baseDir()).isAbsolute().isDirectory().exists();
+    assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
+
+    File workdir = temp.newFolder();
+    fs.setWorkDir(workdir.toPath());
+    assertThat(fs.workDir()).isAbsolute().isDirectory().exists();
+    assertThat(fs.workDir().getCanonicalPath()).isEqualTo(workdir.getCanonicalPath());
+  }
+
+  @Test
+  public void test_encoding() throws Exception {
+    fs.setEncoding(Charset.forName("ISO-8859-1"));
+    assertThat(fs.encoding()).isEqualTo(Charset.forName("ISO-8859-1"));
+  }
+
+  @Test
+  public void add_languages() {
+    assertThat(fs.languages()).isEmpty();
+
+    fs.add(new TestInputFileBuilder("foo", "src/Foo.php").setLanguage("php").build());
+    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
+
+    assertThat(fs.languages()).containsOnly("java", "php");
+  }
+
+  @Test
+  public void files() {
+    assertThat(fs.inputFiles(fs.predicates().all())).isEmpty();
+
+    fs.add(new TestInputFileBuilder("foo", "src/Foo.php").setLanguage("php").build());
+    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
+    fs.add(new TestInputFileBuilder("foo", "src/Baz.java").setLanguage("java").build());
+
+    // no language
+    fs.add(new TestInputFileBuilder("foo", "src/readme.txt").build());
+
+    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNotNull();
+    assertThat(fs.inputFile(fs.predicates().hasRelativePath("does/not/exist"))).isNull();
+
+    assertThat(fs.inputFile(fs.predicates().hasAbsolutePath(new File(basedir, "src/Bar.java").getAbsolutePath()))).isNotNull();
+    assertThat(fs.inputFile(fs.predicates().hasAbsolutePath(new File(basedir, "does/not/exist").getAbsolutePath()))).isNull();
+    assertThat(fs.inputFile(fs.predicates().hasAbsolutePath(new File(basedir, "../src/Bar.java").getAbsolutePath()))).isNull();
+
+    assertThat(fs.inputFile(fs.predicates().hasURI(new File(basedir, "src/Bar.java").toURI()))).isNotNull();
+    assertThat(fs.inputFile(fs.predicates().hasURI(new File(basedir, "does/not/exist").toURI()))).isNull();
+    assertThat(fs.inputFile(fs.predicates().hasURI(new File(basedir, "../src/Bar.java").toURI()))).isNull();
+
+    assertThat(fs.files(fs.predicates().all())).hasSize(4);
+    assertThat(fs.files(fs.predicates().hasLanguage("java"))).hasSize(2);
+    assertThat(fs.files(fs.predicates().hasLanguage("cobol"))).isEmpty();
+
+    assertThat(fs.hasFiles(fs.predicates().all())).isTrue();
+    assertThat(fs.hasFiles(fs.predicates().hasLanguage("java"))).isTrue();
+    assertThat(fs.hasFiles(fs.predicates().hasLanguage("cobol"))).isFalse();
+
+    assertThat(fs.inputFiles(fs.predicates().all())).hasSize(4);
+    assertThat(fs.inputFiles(fs.predicates().hasLanguage("php"))).hasSize(1);
+    assertThat(fs.inputFiles(fs.predicates().hasLanguage("java"))).hasSize(2);
+    assertThat(fs.inputFiles(fs.predicates().hasLanguage("cobol"))).isEmpty();
+
+    assertThat(fs.languages()).containsOnly("java", "php");
+  }
+
+  @Test
+  public void input_file_returns_null_if_file_not_found() {
+    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNull();
+    assertThat(fs.inputFile(fs.predicates().hasLanguage("cobol"))).isNull();
+  }
+
+  @Test
+  public void input_file_fails_if_too_many_results() {
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("expected one element");
+
+    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
+    fs.add(new TestInputFileBuilder("foo", "src/Baz.java").setLanguage("java").build());
+
+    fs.inputFile(fs.predicates().all());
+  }
+
+  @Test
+  public void input_file_supports_non_indexed_predicates() {
+    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
+
+    // it would fail if more than one java file
+    assertThat(fs.inputFile(fs.predicates().hasLanguage("java"))).isNotNull();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputDirTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputDirTest.java
new file mode 100644 (file)
index 0000000..531f611
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.File;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultInputDirTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void test() throws Exception {
+    File baseDir = temp.newFolder();
+    DefaultInputDir inputDir = new DefaultInputDir("ABCDE", "src")
+      .setModuleBaseDir(baseDir.toPath());
+
+    assertThat(inputDir.key()).isEqualTo("ABCDE:src");
+    assertThat(inputDir.file().getAbsolutePath()).isEqualTo(new File(baseDir, "src").getAbsolutePath());
+    assertThat(inputDir.relativePath()).isEqualTo("src");
+    assertThat(new File(inputDir.relativePath())).isRelative();
+    assertThat(inputDir.absolutePath()).endsWith("src");
+    assertThat(new File(inputDir.absolutePath())).isAbsolute();
+  }
+
+  @Test
+  public void testEqualsAndHashCode() throws Exception {
+    DefaultInputDir inputDir1 = new DefaultInputDir("ABCDE", "src");
+
+    DefaultInputDir inputDir2 = new DefaultInputDir("ABCDE", "src");
+
+    assertThat(inputDir1.equals(inputDir1)).isTrue();
+    assertThat(inputDir1.equals(inputDir2)).isTrue();
+    assertThat(inputDir1.equals("foo")).isFalse();
+
+    assertThat(inputDir1.hashCode()).isEqualTo(63545559);
+
+    assertThat(inputDir1.toString()).contains("[moduleKey=ABCDE, relative=src, basedir=null");
+
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputFileTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputFileTest.java
new file mode 100644 (file)
index 0000000..63f6b5f
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.stream.Collectors;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.Metadata;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+public class DefaultInputFileTest {
+
+  private static final String PROJECT_RELATIVE_PATH = "module1/src/Foo.php";
+  private static final String MODULE_RELATIVE_PATH = "src/Foo.php";
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private DefaultIndexedFile indexedFile;
+
+  private Path baseDir;
+  private SensorStrategy sensorStrategy;
+
+  @Before
+  public void prepare() throws IOException {
+    baseDir = temp.newFolder().toPath();
+    sensorStrategy = new SensorStrategy();
+    indexedFile = new DefaultIndexedFile(baseDir.resolve(PROJECT_RELATIVE_PATH), "ABCDE", PROJECT_RELATIVE_PATH, MODULE_RELATIVE_PATH, InputFile.Type.TEST, "php", 0,
+      sensorStrategy);
+  }
+
+  @Test
+  public void test() throws Exception {
+
+    Metadata metadata = new Metadata(42, 42, "", new int[0], new int[0], 10);
+    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> f.setMetadata(metadata))
+      .setStatus(InputFile.Status.ADDED)
+      .setCharset(StandardCharsets.ISO_8859_1);
+
+    assertThat(inputFile.absolutePath()).endsWith("Foo.php");
+    assertThat(inputFile.filename()).isEqualTo("Foo.php");
+    assertThat(inputFile.uri()).hasPath(baseDir.resolve(PROJECT_RELATIVE_PATH).toUri().getPath());
+    assertThat(new File(inputFile.absolutePath())).isAbsolute();
+    assertThat(inputFile.language()).isEqualTo("php");
+    assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED);
+    assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST);
+    assertThat(inputFile.lines()).isEqualTo(42);
+    assertThat(inputFile.charset()).isEqualTo(StandardCharsets.ISO_8859_1);
+
+    assertThat(inputFile.getModuleRelativePath()).isEqualTo(MODULE_RELATIVE_PATH);
+    assertThat(inputFile.getProjectRelativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
+
+    sensorStrategy.setGlobal(false);
+    assertThat(inputFile.relativePath()).isEqualTo(MODULE_RELATIVE_PATH);
+    assertThat(new File(inputFile.relativePath())).isRelative();
+    sensorStrategy.setGlobal(true);
+    assertThat(inputFile.relativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
+    assertThat(new File(inputFile.relativePath())).isRelative();
+  }
+
+  @Test
+  public void test_content() throws IOException {
+    Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
+    Files.createDirectories(testFile.getParent());
+    String content = "test Ã© string";
+    Files.write(testFile, content.getBytes(StandardCharsets.ISO_8859_1));
+
+    assertThat(Files.readAllLines(testFile, StandardCharsets.ISO_8859_1).get(0)).hasSize(content.length());
+
+    Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
+
+    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
+      .setStatus(InputFile.Status.ADDED)
+      .setCharset(StandardCharsets.ISO_8859_1);
+
+    assertThat(inputFile.contents()).isEqualTo(content);
+    try (InputStream inputStream = inputFile.inputStream()) {
+      String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
+      assertThat(result).isEqualTo(content);
+    }
+
+  }
+
+  @Test
+  public void test_content_exclude_bom() throws IOException {
+    Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
+    Files.createDirectories(testFile.getParent());
+    try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(testFile.toFile()), StandardCharsets.UTF_8))) {
+      out.write('\ufeff');
+    }
+    String content = "test Ã© string â‚¬";
+    Files.write(testFile, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
+
+    assertThat(Files.readAllLines(testFile, StandardCharsets.UTF_8).get(0)).hasSize(content.length() + 1);
+
+    Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
+
+    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
+      .setStatus(InputFile.Status.ADDED)
+      .setCharset(StandardCharsets.UTF_8);
+
+    assertThat(inputFile.contents()).isEqualTo(content);
+    try (InputStream inputStream = inputFile.inputStream()) {
+      String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
+      assertThat(result).isEqualTo(content);
+    }
+
+  }
+
+  @Test
+  public void test_equals_and_hashcode() throws Exception {
+    DefaultInputFile f1 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
+    DefaultInputFile f1a = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
+    DefaultInputFile f2 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Bar.php", null), (f) -> mock(Metadata.class));
+
+    assertThat(f1).isEqualTo(f1);
+    assertThat(f1).isEqualTo(f1a);
+    assertThat(f1).isNotEqualTo(f2);
+    assertThat(f1.equals("foo")).isFalse();
+    assertThat(f1.equals(null)).isFalse();
+
+    assertThat(f1.hashCode()).isEqualTo(f1.hashCode());
+    assertThat(f1.hashCode()).isEqualTo(f1a.hashCode());
+  }
+
+  @Test
+  public void test_toString() throws Exception {
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
+    assertThat(file.toString()).isEqualTo(MODULE_RELATIVE_PATH);
+  }
+
+  @Test
+  public void checkValidPointer() {
+    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+    assertThat(file.newPointer(1, 0).line()).isEqualTo(1);
+    assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0);
+    // Don't fail
+    file.newPointer(1, 9);
+    file.newPointer(2, 0);
+    file.newPointer(2, 5);
+
+    try {
+      file.newPointer(0, 1);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("0 is not a valid line for a file");
+    }
+    try {
+      file.newPointer(3, 1);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("3 is not a valid line for pointer. File src/Foo.php has 2 line(s)");
+    }
+    try {
+      file.newPointer(1, -1);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("-1 is not a valid line offset for a file");
+    }
+    try {
+      file.newPointer(1, 10);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
+    }
+  }
+
+  @Test
+  public void checkValidPointerUsingGlobalOffset() {
+    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {8, 15}, 16);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+    assertThat(file.newPointer(0).line()).isEqualTo(1);
+    assertThat(file.newPointer(0).lineOffset()).isEqualTo(0);
+
+    assertThat(file.newPointer(9).line()).isEqualTo(1);
+    // Ignore eol characters
+    assertThat(file.newPointer(9).lineOffset()).isEqualTo(8);
+
+    assertThat(file.newPointer(10).line()).isEqualTo(2);
+    assertThat(file.newPointer(10).lineOffset()).isEqualTo(0);
+
+    assertThat(file.newPointer(15).line()).isEqualTo(2);
+    assertThat(file.newPointer(15).lineOffset()).isEqualTo(5);
+
+    assertThat(file.newPointer(16).line()).isEqualTo(2);
+    // Ignore eol characters
+    assertThat(file.newPointer(16).lineOffset()).isEqualTo(5);
+
+    try {
+      file.newPointer(-1);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("-1 is not a valid offset for a file");
+    }
+
+    try {
+      file.newPointer(17);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("17 is not a valid offset for file src/Foo.php. Max offset is 16");
+    }
+  }
+
+  @Test
+  public void checkValidRange() {
+    Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde"));
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+
+    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1);
+    // Don't fail
+    file.newRange(file.newPointer(1, 0), file.newPointer(1, 1));
+    file.newRange(file.newPointer(1, 0), file.newPointer(1, 9));
+    file.newRange(file.newPointer(1, 0), file.newPointer(2, 0));
+    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 5))).isEqualTo(file.newRange(0, 15));
+
+    try {
+      file.newRange(file.newPointer(1, 0), file.newPointer(1, 0));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("Start pointer [line=1, lineOffset=0] should be before end pointer [line=1, lineOffset=0]");
+    }
+    try {
+      file.newRange(file.newPointer(1, 0), file.newPointer(1, 10));
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
+    }
+  }
+
+  @Test
+  public void selectLine() {
+    Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde\n\nabc"));
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+
+    assertThat(file.selectLine(1).start().line()).isEqualTo(1);
+    assertThat(file.selectLine(1).start().lineOffset()).isEqualTo(0);
+    assertThat(file.selectLine(1).end().line()).isEqualTo(1);
+    assertThat(file.selectLine(1).end().lineOffset()).isEqualTo(9);
+
+    // Don't fail when selecting empty line
+    assertThat(file.selectLine(3).start().line()).isEqualTo(3);
+    assertThat(file.selectLine(3).start().lineOffset()).isEqualTo(0);
+    assertThat(file.selectLine(3).end().line()).isEqualTo(3);
+    assertThat(file.selectLine(3).end().lineOffset()).isEqualTo(0);
+
+    try {
+      file.selectLine(5);
+      fail();
+    } catch (Exception e) {
+      assertThat(e).hasMessage("5 is not a valid line for pointer. File src/Foo.php has 4 line(s)");
+    }
+  }
+
+  @Test
+  public void checkValidRangeUsingGlobalOffset() {
+    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+    TextRange newRange = file.newRange(10, 13);
+    assertThat(newRange.start().line()).isEqualTo(2);
+    assertThat(newRange.start().lineOffset()).isEqualTo(0);
+    assertThat(newRange.end().line()).isEqualTo(2);
+    assertThat(newRange.end().lineOffset()).isEqualTo(3);
+  }
+
+  @Test
+  public void testRangeOverlap() {
+    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
+    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
+    // Don't fail
+    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)))).isTrue();
+    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isTrue();
+    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 1), file.newPointer(1, 2)))).isFalse();
+    assertThat(file.newRange(file.newPointer(1, 2), file.newPointer(1, 3)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isFalse();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputModuleTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputModuleTest.java
new file mode 100644 (file)
index 0000000..3466862
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultInputModuleTest {
+
+  private static final String FILE_1 = "file1";
+  private static final String TEST_1 = "test1";
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void check_getters() throws IOException {
+    ProjectDefinition def = ProjectDefinition.create();
+    def.setKey("moduleKey");
+    File baseDir = temp.newFolder();
+    Path src = baseDir.toPath().resolve(FILE_1);
+    Files.createFile(src);
+    Path test = baseDir.toPath().resolve(TEST_1);
+    Files.createFile(test);
+    def.setBaseDir(baseDir);
+    File workDir = temp.newFolder();
+    def.setWorkDir(workDir);
+    def.setSources(FILE_1);
+    def.setTests(TEST_1);
+    DefaultInputModule module = new DefaultInputModule(def);
+
+    assertThat(module.key()).isEqualTo("moduleKey");
+    assertThat(module.definition()).isEqualTo(def);
+    assertThat(module.getBranch()).isNull();
+    assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
+    assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
+    assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
+    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+    assertThat(module.getSourceDirsOrFiles().get()).containsExactlyInAnyOrder(src);
+    assertThat(module.getTestDirsOrFiles().get()).containsExactlyInAnyOrder(test);
+    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+
+    assertThat(module.isFile()).isFalse();
+  }
+
+  @Test
+  public void no_sources() throws IOException {
+    ProjectDefinition def = ProjectDefinition.create();
+    def.setKey("moduleKey");
+    File baseDir = temp.newFolder();
+    Path src = baseDir.toPath().resolve(FILE_1);
+    Files.createFile(src);
+    Path test = baseDir.toPath().resolve(TEST_1);
+    Files.createFile(test);
+    def.setBaseDir(baseDir);
+    File workDir = temp.newFolder();
+    def.setWorkDir(workDir);
+    DefaultInputModule module = new DefaultInputModule(def);
+
+    assertThat(module.key()).isEqualTo("moduleKey");
+    assertThat(module.definition()).isEqualTo(def);
+    assertThat(module.getBranch()).isNull();
+    assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
+    assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
+    assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
+    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+    assertThat(module.getSourceDirsOrFiles()).isNotPresent();
+    assertThat(module.getTestDirsOrFiles()).isNotPresent();
+    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
+
+    assertThat(module.isFile()).isFalse();
+  }
+
+  @Test
+  public void working_directory_should_be_hidden() throws IOException {
+    ProjectDefinition def = ProjectDefinition.create();
+    File workDir = temp.newFolder(".sonar");
+    def.setWorkDir(workDir);
+    File baseDir = temp.newFolder();
+    def.setBaseDir(baseDir);
+    DefaultInputModule module = new DefaultInputModule(def);
+    assertThat(workDir.isHidden()).isTrue();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputProjectTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/DefaultInputProjectTest.java
new file mode 100644 (file)
index 0000000..71a4b9c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultInputProjectTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void testGetters() throws IOException {
+    ProjectDefinition def = ProjectDefinition.create();
+    def.setKey("projectKey");
+    def.setName("projectName");
+    File baseDir = temp.newFolder();
+    def.setBaseDir(baseDir);
+    def.setDescription("desc");
+    File workDir = temp.newFolder();
+    def.setWorkDir(workDir);
+    def.setSources("file1");
+    def.setTests("test1");
+    AbstractProjectOrModule project = new DefaultInputProject(def);
+
+    assertThat(project.key()).isEqualTo("projectKey");
+    assertThat(project.getName()).isEqualTo("projectName");
+    assertThat(project.getOriginalName()).isEqualTo("projectName");
+    assertThat(project.definition()).isEqualTo(def);
+    assertThat(project.getBranch()).isNull();
+    assertThat(project.getBaseDir()).isEqualTo(baseDir.toPath());
+    assertThat(project.getKeyWithBranch()).isEqualTo("projectKey");
+    assertThat(project.getDescription()).isEqualTo("desc");
+    assertThat(project.getWorkDir()).isEqualTo(workDir.toPath());
+    assertThat(project.getEncoding()).isEqualTo(Charset.defaultCharset());
+
+    assertThat(project.properties()).hasSize(5);
+
+    assertThat(project.isFile()).isFalse();
+  }
+
+  @Test
+  public void testEncoding() throws IOException {
+    ProjectDefinition def = ProjectDefinition.create();
+    def.setKey("projectKey");
+    def.setName("projectName");
+    File baseDir = temp.newFolder();
+    def.setBaseDir(baseDir);
+    def.setProjectVersion("version");
+    def.setDescription("desc");
+    File workDir = temp.newFolder();
+    def.setWorkDir(workDir);
+    def.setSources("file1");
+    def.setProperty("sonar.sourceEncoding", "UTF-16");
+    AbstractProjectOrModule project = new DefaultInputProject(def);
+
+    assertThat(project.getEncoding()).isEqualTo(StandardCharsets.UTF_16);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/FileMetadataTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/FileMetadataTest.java
new file mode 100644 (file)
index 0000000..b5f7728
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import javax.annotation.Nullable;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.io.FileUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.Metadata;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+
+import static org.apache.commons.codec.digest.DigestUtils.md5Hex;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+public class FileMetadataTest {
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public LogTester logTester = new LogTester();
+
+  @Test
+  public void empty_file() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.touch(tempFile);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(1);
+    assertThat(metadata.nonBlankLines()).isEqualTo(0);
+    assertThat(metadata.hash()).isNotEmpty();
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(0);
+    assertThat(metadata.isEmpty()).isTrue();
+  }
+
+  @Test
+  public void windows_without_latest_eol() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\r\nbar\r\nbaz", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(3);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 5, 10);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 8, 13);
+    assertThat(metadata.isEmpty()).isFalse();
+  }
+
+  @Test
+  public void read_with_wrong_encoding() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "marker´s\n", Charset.forName("cp1252"));
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(2);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("marker\ufffds\n"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 9);
+  }
+
+  @Test
+  public void non_ascii_utf_8() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(4);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 5, 10, 18);
+  }
+
+  @Test
+  public void non_ascii_utf_16() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", StandardCharsets.UTF_16, true);
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_16, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(4);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n".getBytes(StandardCharsets.UTF_8)));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 5, 10, 18);
+  }
+
+  @Test
+  public void unix_without_latest_eol() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\nbar\nbaz", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(3);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11);
+    assertThat(metadata.isEmpty()).isFalse();
+  }
+
+  @Test
+  public void unix_with_latest_eol() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\nbar\nbaz\n", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(4);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8, 12);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11, 12);
+  }
+
+  @Test
+  public void mac_without_latest_eol() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\rbar\rbaz", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(3);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11);
+  }
+
+  @Test
+  public void mac_with_latest_eol() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\rbar\rbaz\r", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(4);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8, 12);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11, 12);
+  }
+
+  @Test
+  public void mix_of_newlines_with_latest_eol() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\nbar\r\nbaz\n", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(4);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 9, 13);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 12, 13);
+  }
+
+  @Test
+  public void several_new_lines() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\n\n\nbar", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(4);
+    assertThat(metadata.nonBlankLines()).isEqualTo(2);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\n\n\nbar"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 5, 6);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 4, 5, 9);
+  }
+
+  @Test
+  public void mix_of_newlines_without_latest_eol() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "foo\nbar\r\nbaz", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(3);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 9);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 12);
+  }
+
+  @Test
+  public void start_with_newline() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "\nfoo\nbar\r\nbaz", StandardCharsets.UTF_8, true);
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
+    assertThat(metadata.lines()).isEqualTo(4);
+    assertThat(metadata.nonBlankLines()).isEqualTo(3);
+    assertThat(metadata.hash()).isEqualTo(md5Hex("\nfoo\nbar\nbaz"));
+    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 1, 5, 10);
+    assertThat(metadata.originalLineEndOffsets()).containsOnly(0, 4, 8, 13);
+  }
+
+  @Test
+  public void ignore_whitespace_when_computing_line_hashes() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, " foo\nb ar\r\nbaz \t", StandardCharsets.UTF_8, true);
+
+    DefaultInputFile f = new TestInputFileBuilder("foo", tempFile.getName())
+      .setModuleBaseDir(tempFile.getParentFile().toPath())
+      .setCharset(StandardCharsets.UTF_8)
+      .build();
+    FileMetadata.computeLineHashesForIssueTracking(f, new FileMetadata.LineHashConsumer() {
+
+      @Override
+      public void consume(int lineIdx, @Nullable byte[] hash) {
+        switch (lineIdx) {
+          case 1:
+            assertThat(Hex.encodeHexString(hash)).isEqualTo(md5Hex("foo"));
+            break;
+          case 2:
+            assertThat(Hex.encodeHexString(hash)).isEqualTo(md5Hex("bar"));
+            break;
+          case 3:
+            assertThat(Hex.encodeHexString(hash)).isEqualTo(md5Hex("baz"));
+            break;
+          default:
+            fail("Invalid line");
+        }
+      }
+    });
+  }
+
+  @Test
+  public void dont_fail_on_empty_file() throws Exception {
+    File tempFile = temp.newFile();
+    FileUtils.write(tempFile, "", StandardCharsets.UTF_8, true);
+
+    DefaultInputFile f = new TestInputFileBuilder("foo", tempFile.getName())
+      .setModuleBaseDir(tempFile.getParentFile().toPath())
+      .setCharset(StandardCharsets.UTF_8)
+      .build();
+    FileMetadata.computeLineHashesForIssueTracking(f, new FileMetadata.LineHashConsumer() {
+
+      @Override
+      public void consume(int lineIdx, @Nullable byte[] hash) {
+        switch (lineIdx) {
+          case 1:
+            assertThat(hash).isNull();
+            break;
+          default:
+            fail("Invalid line");
+        }
+      }
+    });
+  }
+
+  @Test
+  public void line_feed_is_included_into_hash() throws Exception {
+    File file1 = temp.newFile();
+    FileUtils.write(file1, "foo\nbar\n", StandardCharsets.UTF_8, true);
+
+    // same as file1, except an additional return carriage
+    File file1a = temp.newFile();
+    FileUtils.write(file1a, "foo\r\nbar\n", StandardCharsets.UTF_8, true);
+
+    File file2 = temp.newFile();
+    FileUtils.write(file2, "foo\nbar", StandardCharsets.UTF_8, true);
+
+    String hash1 = new FileMetadata().readMetadata(new FileInputStream(file1), StandardCharsets.UTF_8, file1.getName()).hash();
+    String hash1a = new FileMetadata().readMetadata(new FileInputStream(file1a), StandardCharsets.UTF_8, file1a.getName()).hash();
+    String hash2 = new FileMetadata().readMetadata(new FileInputStream(file2), StandardCharsets.UTF_8, file2.getName()).hash();
+
+    assertThat(hash1).isEqualTo(hash1a);
+    assertThat(hash1).isNotEqualTo(hash2);
+  }
+
+  @Test
+  public void binary_file_with_unmappable_character() throws Exception {
+    File woff = new File(this.getClass().getResource("glyphicons-halflings-regular.woff").toURI());
+
+    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(woff), StandardCharsets.UTF_8, woff.getAbsolutePath());
+
+    assertThat(metadata.lines()).isEqualTo(135);
+    assertThat(metadata.nonBlankLines()).isEqualTo(133);
+    assertThat(metadata.hash()).isNotEmpty();
+
+    assertThat(logTester.logs(LoggerLevel.WARN).get(0)).contains("Invalid character encountered in file");
+    assertThat(logTester.logs(LoggerLevel.WARN).get(0)).contains(
+      "glyphicons-halflings-regular.woff at line 1 for encoding UTF-8. Please fix file content or configure the encoding to be used using property 'sonar.sourceEncoding'.");
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/MetadataTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/MetadataTest.java
new file mode 100644 (file)
index 0000000..246aeec
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.sonar.api.batch.fs.internal.Metadata;
+
+public class MetadataTest {
+  @Test
+  public void testRoundtrip() {
+    Metadata metadata = new Metadata(10, 20, "hash", new int[] {1, 3}, new int[] {2, 4}, 5);
+    assertThat(metadata.isEmpty()).isFalse();
+    assertThat(metadata.lines()).isEqualTo(10);
+    assertThat(metadata.nonBlankLines()).isEqualTo(20);
+    assertThat(metadata.originalLineStartOffsets()).isEqualTo(new int[] {1, 3});
+    assertThat(metadata.originalLineEndOffsets()).isEqualTo(new int[] {2, 4});
+    assertThat(metadata.lastValidOffset()).isEqualTo(5);
+    assertThat(metadata.hash()).isEqualTo("hash");
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/PathPatternTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/PathPatternTest.java
new file mode 100644 (file)
index 0000000..312e908
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.IndexedFile;
+import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
+import org.sonar.api.batch.fs.internal.PathPattern;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PathPatternTest {
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+  private Path baseDir;
+
+  @Before
+  public void setUp() throws IOException {
+    baseDir = temp.newFolder().toPath();
+  }
+
+  @Test
+  public void match_relative_path() {
+    PathPattern pattern = PathPattern.create("**/*Foo.java");
+    assertThat(pattern.toString()).isEqualTo("**/*Foo.java");
+
+    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.java", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isTrue();
+
+    // case sensitive by default
+    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
+
+    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.java", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
+  }
+
+  @Test
+  public void match_relative_path_and_insensitive_file_extension() throws Exception {
+    PathPattern pattern = PathPattern.create("**/*Foo.java");
+
+    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isTrue();
+
+    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.java", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isFalse();
+  }
+
+  @Test
+  public void match_absolute_path() throws Exception {
+    PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
+    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
+
+    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.java", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isTrue();
+
+    // case sensitive by default
+    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
+
+    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.java", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
+  }
+
+  @Test
+  public void match_absolute_path_and_insensitive_file_extension() throws Exception {
+    PathPattern pattern = PathPattern.create("file:**/src/main/**Foo.java");
+    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
+
+    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isTrue();
+
+    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.JAVA", null);
+    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isFalse();
+  }
+
+  @Test
+  public void create_array_of_patterns() {
+    PathPattern[] patterns = PathPattern.create(new String[] {
+      "**/src/main/**Foo.java",
+      "file:**/src/main/**Bar.java"
+    });
+    assertThat(patterns).hasSize(2);
+    assertThat(patterns[0].toString()).isEqualTo("**/src/main/**Foo.java");
+    assertThat(patterns[1].toString()).isEqualTo("file:**/src/main/**Bar.java");
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/TestInputFileBuilderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/fs/TestInputFileBuilderTest.java
new file mode 100644 (file)
index 0000000..bd6c6da
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.fs;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.IOUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile.Status;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class TestInputFileBuilderTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void setContent() throws IOException {
+    DefaultInputFile file = TestInputFileBuilder.create("module", "invalidPath")
+      .setContents("my content")
+      .setCharset(StandardCharsets.UTF_8)
+      .build();
+    assertThat(file.contents()).isEqualTo("my content");
+    assertThat(IOUtils.toString(file.inputStream())).isEqualTo("my content");
+  }
+
+  @Test
+  public void testGetters() {
+    DefaultInputFile file = TestInputFileBuilder.create("module", new File("baseDir"), new File("baseDir", "path"))
+      .setStatus(Status.SAME)
+      .setType(Type.MAIN)
+      .build();
+
+    assertThat(file.type()).isEqualTo(Type.MAIN);
+    assertThat(file.status()).isEqualTo(Status.SAME);
+    assertThat(file.isPublished()).isTrue();
+    assertThat(file.type()).isEqualTo(Type.MAIN);
+    assertThat(file.relativePath()).isEqualTo("path");
+    assertThat(file.absolutePath()).isEqualTo("baseDir/path");
+
+  }
+
+  @Test
+  public void testCreateInputModule() throws IOException {
+    File baseDir = temp.newFolder();
+    AbstractProjectOrModule module = TestInputFileBuilder.newDefaultInputModule("key", baseDir);
+    assertThat(module.key()).isEqualTo("key");
+    assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/AndPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/AndPredicateTest.java
new file mode 100644 (file)
index 0000000..b58d1cd
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.util.Arrays;
+import org.junit.Test;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.PathPattern;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class AndPredicateTest {
+
+  @Test
+  public void flattenNestedAnd() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
+    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("foo3/**"));
+    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
+      AndPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
+    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2, pathPatternPredicate3);
+  }
+
+  @Test
+  public void applyPredicates() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo/file1"));
+    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("**"));
+    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
+      AndPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
+
+    InputFile file1 = TestInputFileBuilder.create("module", "foo/file1").build();
+    InputFile file2 = TestInputFileBuilder.create("module", "foo2/file1").build();
+    InputFile file3 = TestInputFileBuilder.create("module", "foo/file2").build();
+
+    assertThat(andPredicate.apply(file1)).isTrue();
+    assertThat(andPredicate.apply(file2)).isFalse();
+    assertThat(andPredicate.apply(file3)).isFalse();
+  }
+
+  @Test
+  public void filterIndex() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo/file1"));
+    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("**"));
+
+    InputFile file1 = TestInputFileBuilder.create("module", "foo/file1").build();
+    InputFile file2 = TestInputFileBuilder.create("module", "foo2/file1").build();
+    InputFile file3 = TestInputFileBuilder.create("module", "foo/file2").build();
+
+    FileSystem.Index index = mock(FileSystem.Index.class);
+    when(index.inputFiles()).thenReturn(Arrays.asList(file1, file2, file3));
+
+    OptimizedFilePredicate andPredicate = (OptimizedFilePredicate) AndPredicate.create(Arrays.asList(pathPatternPredicate1,
+      AndPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
+
+    assertThat(andPredicate.get(index)).containsOnly(file1);
+  }
+
+  @Test
+  public void sortPredicatesByPriority() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
+    RelativePathPredicate relativePathPredicate = new RelativePathPredicate("foo");
+    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
+      relativePathPredicate, pathPatternPredicate2));
+    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(relativePathPredicate, pathPatternPredicate1, pathPatternPredicate2);
+  }
+
+  @Test
+  public void simplifyAndExpressionsWhenEmpty() {
+    FilePredicate andPredicate = AndPredicate.create(Arrays.asList());
+    assertThat(andPredicate).isEqualTo(TruePredicate.TRUE);
+  }
+
+  @Test
+  public void simplifyAndExpressionsWhenTrue() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
+    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
+      TruePredicate.TRUE, pathPatternPredicate2));
+    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2);
+  }
+
+  @Test
+  public void simplifyAndExpressionsWhenFalse() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
+    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
+      FalsePredicate.FALSE, pathPatternPredicate2));
+    assertThat(andPredicate).isEqualTo(FalsePredicate.FALSE);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/DefaultFilePredicatesTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/DefaultFilePredicatesTest.java
new file mode 100644 (file)
index 0000000..e47bd8a
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Status;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultFilePredicatesTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private Path moduleBasePath;
+
+  @Before
+  public void setUp() throws IOException {
+    moduleBasePath = temp.newFolder().toPath();
+  }
+
+  InputFile javaFile;
+  FilePredicates predicates;
+
+  @Before
+  public void before() throws IOException {
+    predicates = new DefaultFilePredicates(temp.newFolder().toPath());
+    javaFile = new TestInputFileBuilder("foo", "src/main/java/struts/Action.java")
+      .setModuleBaseDir(moduleBasePath)
+      .setLanguage("java")
+      .setStatus(Status.SAME)
+      .build();
+
+  }
+
+  @Test
+  public void all() {
+    assertThat(predicates.all().apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void none() {
+    assertThat(predicates.none().apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void matches_inclusion_pattern() {
+    assertThat(predicates.matchesPathPattern("src/main/**/Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.matchesPathPattern("Action.java").apply(javaFile)).isFalse();
+    assertThat(predicates.matchesPathPattern("src/**/*.php").apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void matches_inclusion_patterns() {
+    assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isTrue();
+    assertThat(predicates.matchesPathPatterns(new String[] {}).apply(javaFile)).isTrue();
+    assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void does_not_match_exclusion_pattern() {
+    assertThat(predicates.doesNotMatchPathPattern("src/main/**/Action.java").apply(javaFile)).isFalse();
+    assertThat(predicates.doesNotMatchPathPattern("Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.doesNotMatchPathPattern("src/**/*.php").apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void does_not_match_exclusion_patterns() {
+    assertThat(predicates.doesNotMatchPathPatterns(new String[] {}).apply(javaFile)).isTrue();
+    assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isTrue();
+    assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_relative_path() {
+    assertThat(predicates.hasRelativePath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasRelativePath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
+
+    // path is normalized
+    assertThat(predicates.hasRelativePath("src/main/java/../java/struts/Action.java").apply(javaFile)).isTrue();
+
+    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Other.java").apply(javaFile)).isFalse();
+    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\..\\struts\\Action.java").apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void has_absolute_path() throws Exception {
+    String path = javaFile.file().getAbsolutePath();
+    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
+    assertThat(predicates.hasAbsolutePath(path.replaceAll("/", "\\\\")).apply(javaFile)).isTrue();
+
+    assertThat(predicates.hasAbsolutePath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
+    assertThat(predicates.hasAbsolutePath("src/main/java/struts/Action.java").apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_uri() throws Exception {
+    URI uri = javaFile.uri();
+    assertThat(predicates.hasURI(uri).apply(javaFile)).isTrue();
+
+    assertThat(predicates.hasURI(temp.newFile().toURI()).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_path() throws Exception {
+    // is relative path
+    assertThat(predicates.hasPath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasPath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
+
+    // is absolute path
+    String path = javaFile.file().getAbsolutePath();
+    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
+    assertThat(predicates.hasPath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void is_file() throws Exception {
+    // relative file
+    assertThat(predicates.is(new File(javaFile.relativePath())).apply(javaFile)).isTrue();
+
+    // absolute file
+    assertThat(predicates.is(javaFile.file()).apply(javaFile)).isTrue();
+    assertThat(predicates.is(javaFile.file().getAbsoluteFile()).apply(javaFile)).isTrue();
+    assertThat(predicates.is(new File(javaFile.file().toURI())).apply(javaFile)).isTrue();
+    assertThat(predicates.is(temp.newFile()).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_language() {
+    assertThat(predicates.hasLanguage("java").apply(javaFile)).isTrue();
+    assertThat(predicates.hasLanguage("php").apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_languages() {
+    assertThat(predicates.hasLanguages(Arrays.asList("java", "php")).apply(javaFile)).isTrue();
+    assertThat(predicates.hasLanguages(Arrays.asList("cobol", "php")).apply(javaFile)).isFalse();
+    assertThat(predicates.hasLanguages(Collections.<String>emptyList()).apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void has_type() {
+    assertThat(predicates.hasType(InputFile.Type.MAIN).apply(javaFile)).isTrue();
+    assertThat(predicates.hasType(InputFile.Type.TEST).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void has_status() {
+    assertThat(predicates.hasAnyStatus().apply(javaFile)).isTrue();
+    assertThat(predicates.hasStatus(InputFile.Status.SAME).apply(javaFile)).isTrue();
+    assertThat(predicates.hasStatus(InputFile.Status.ADDED).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void not() {
+    assertThat(predicates.not(predicates.hasType(InputFile.Type.MAIN)).apply(javaFile)).isFalse();
+    assertThat(predicates.not(predicates.hasType(InputFile.Type.TEST)).apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void and() {
+    // empty
+    assertThat(predicates.and().apply(javaFile)).isTrue();
+    assertThat(predicates.and(new FilePredicate[0]).apply(javaFile)).isTrue();
+    assertThat(predicates.and(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
+
+    // two arguments
+    assertThat(predicates.and(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
+    assertThat(predicates.and(predicates.all(), predicates.none()).apply(javaFile)).isFalse();
+    assertThat(predicates.and(predicates.none(), predicates.all()).apply(javaFile)).isFalse();
+
+    // collection
+    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
+    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isFalse();
+
+    // array
+    assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
+    assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void or() {
+    // empty
+    assertThat(predicates.or().apply(javaFile)).isTrue();
+    assertThat(predicates.or(new FilePredicate[0]).apply(javaFile)).isTrue();
+    assertThat(predicates.or(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
+
+    // two arguments
+    assertThat(predicates.or(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
+    assertThat(predicates.or(predicates.all(), predicates.none()).apply(javaFile)).isTrue();
+    assertThat(predicates.or(predicates.none(), predicates.all()).apply(javaFile)).isTrue();
+    assertThat(predicates.or(predicates.none(), predicates.none()).apply(javaFile)).isFalse();
+
+    // collection
+    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
+    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isTrue();
+    assertThat(predicates.or(Arrays.asList(predicates.none(), predicates.none())).apply(javaFile)).isFalse();
+
+    // array
+    assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
+    assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isTrue();
+    assertThat(predicates.or(new FilePredicate[] {predicates.none(), predicates.none()}).apply(javaFile)).isFalse();
+  }
+
+  @Test
+  public void hasFilename() {
+    assertThat(predicates.hasFilename("Action.java").apply(javaFile)).isTrue();
+  }
+
+  @Test
+  public void hasExtension() {
+    assertThat(predicates.hasExtension("java").apply(javaFile)).isTrue();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FileExtensionPredicateTest.java
new file mode 100644 (file)
index 0000000..a8edf89
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.io.IOException;
+import org.junit.Test;
+import org.sonar.api.batch.fs.InputFile;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.batch.fs.internal.predicates.FileExtensionPredicate.getExtension;
+
+public class FileExtensionPredicateTest {
+
+  @Test
+  public void should_match_correct_extension() throws IOException {
+    FileExtensionPredicate predicate = new FileExtensionPredicate("bat");
+    assertThat(predicate.apply(mockWithName("prog.bat"))).isTrue();
+    assertThat(predicate.apply(mockWithName("prog.bat.bat"))).isTrue();
+  }
+
+  @Test
+  public void should_not_match_incorrect_extension() throws IOException {
+    FileExtensionPredicate predicate = new FileExtensionPredicate("bat");
+    assertThat(predicate.apply(mockWithName("prog.batt"))).isFalse();
+    assertThat(predicate.apply(mockWithName("prog.abat"))).isFalse();
+    assertThat(predicate.apply(mockWithName("prog."))).isFalse();
+    assertThat(predicate.apply(mockWithName("prog.bat."))).isFalse();
+    assertThat(predicate.apply(mockWithName("prog.bat.batt"))).isFalse();
+    assertThat(predicate.apply(mockWithName("prog"))).isFalse();
+  }
+
+  @Test
+  public void should_match_correct_extension_case_insensitively() throws IOException {
+    FileExtensionPredicate predicate = new FileExtensionPredicate("jAVa");
+    assertThat(predicate.apply(mockWithName("Program.java"))).isTrue();
+    assertThat(predicate.apply(mockWithName("Program.JAVA"))).isTrue();
+    assertThat(predicate.apply(mockWithName("Program.Java"))).isTrue();
+    assertThat(predicate.apply(mockWithName("Program.JaVa"))).isTrue();
+  }
+
+  @Test
+  public void test_empty_extension() {
+    assertThat(getExtension("prog")).isEmpty();
+    assertThat(getExtension("prog.")).isEmpty();
+    assertThat(getExtension(".")).isEmpty();
+  }
+
+  private InputFile mockWithName(String filename) throws IOException {
+    InputFile inputFile = mock(InputFile.class);
+    when(inputFile.filename()).thenReturn(filename);
+    return inputFile;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/FilenamePredicateTest.java
new file mode 100644 (file)
index 0000000..2ec9b1b
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import java.io.IOException;
+import java.util.Collections;
+import org.junit.Test;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class FilenamePredicateTest {
+  @Test
+  public void should_match_file_by_filename() throws IOException {
+    String filename = "some name";
+    InputFile inputFile = mock(InputFile.class);
+    when(inputFile.filename()).thenReturn(filename);
+
+    assertThat(new FilenamePredicate(filename).apply(inputFile)).isTrue();
+  }
+
+  @Test
+  public void should_not_match_file_by_different_filename() throws IOException {
+    String filename = "some name";
+    InputFile inputFile = mock(InputFile.class);
+    when(inputFile.filename()).thenReturn(filename + "x");
+
+    assertThat(new FilenamePredicate(filename).apply(inputFile)).isFalse();
+  }
+
+  @Test
+  public void should_find_matching_file_in_index() throws IOException {
+    String filename = "some name";
+    InputFile inputFile = mock(InputFile.class);
+    when(inputFile.filename()).thenReturn(filename);
+
+    FileSystem.Index index = mock(FileSystem.Index.class);
+    when(index.getFilesByName(filename)).thenReturn(Collections.singleton(inputFile));
+
+    assertThat(new FilenamePredicate(filename).get(index)).containsOnly(inputFile);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/OrPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/OrPredicateTest.java
new file mode 100644 (file)
index 0000000..4a22fdd
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.junit.Test;
+import org.sonar.api.batch.fs.FilePredicate;
+
+import java.util.Arrays;
+import org.sonar.api.batch.fs.internal.PathPattern;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class OrPredicateTest {
+
+  @Test
+  public void flattenNestedOr() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
+    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("foo3/**"));
+    FilePredicate orPredicate = OrPredicate.create(Arrays.asList(pathPatternPredicate1,
+      OrPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
+    assertThat(((OrPredicate) orPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2, pathPatternPredicate3);
+  }
+
+  @Test
+  public void simplifyOrExpressionsWhenEmpty() {
+    FilePredicate orPredicate = OrPredicate.create(Arrays.asList());
+    assertThat(orPredicate).isEqualTo(TruePredicate.TRUE);
+  }
+
+  @Test
+  public void simplifyOrExpressionsWhenFalse() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
+    FilePredicate andPredicate = OrPredicate.create(Arrays.asList(pathPatternPredicate1,
+      FalsePredicate.FALSE, pathPatternPredicate2));
+    assertThat(((OrPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2);
+  }
+
+  @Test
+  public void simplifyAndExpressionsWhenTrue() {
+    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
+    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
+    FilePredicate andPredicate = OrPredicate.create(Arrays.asList(pathPatternPredicate1,
+      TruePredicate.TRUE, pathPatternPredicate2));
+    assertThat(andPredicate).isEqualTo(TruePredicate.TRUE);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/RelativePathPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/fs/internal/predicates/RelativePathPredicateTest.java
new file mode 100644 (file)
index 0000000..9dda6bf
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.fs.internal.predicates;
+
+import org.junit.Test;
+import org.sonar.api.batch.fs.InputFile;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class RelativePathPredicateTest {
+  @Test
+  public void returns_false_when_path_is_invalid() {
+    RelativePathPredicate predicate = new RelativePathPredicate("..");
+    InputFile inputFile = mock(InputFile.class);
+    when(inputFile.relativePath()).thenReturn("path");
+    assertThat(predicate.apply(inputFile)).isFalse();
+  }
+
+  @Test
+  public void returns_true_if_matches() {
+    RelativePathPredicate predicate = new RelativePathPredicate("path");
+    InputFile inputFile = mock(InputFile.class);
+    when(inputFile.relativePath()).thenReturn("path");
+    assertThat(predicate.apply(inputFile)).isTrue();
+  }
+
+  @Test
+  public void returns_false_if_doesnt_match() {
+    RelativePathPredicate predicate = new RelativePathPredicate("path1");
+    InputFile inputFile = mock(InputFile.class);
+    when(inputFile.relativePath()).thenReturn("path2");
+    assertThat(predicate.apply(inputFile)).isFalse();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/DefaultRulesTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/DefaultRulesTest.java
new file mode 100644 (file)
index 0000000..4c3fdde
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import java.util.LinkedList;
+import java.util.List;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultRulesTest {
+  @Test
+  public void testRepeatedInternalKey() {
+    List<NewRule> newRules = new LinkedList<>();
+    newRules.add(createRule("key1", "repo", "internal"));
+    newRules.add(createRule("key2", "repo", "internal"));
+    
+    DefaultRules rules = new DefaultRules(newRules);
+    assertThat(rules.findByInternalKey("repo", "internal")).hasSize(2);
+    assertThat(rules.find(RuleKey.of("repo", "key1"))).isNotNull();
+    assertThat(rules.find(RuleKey.of("repo", "key2"))).isNotNull();
+    assertThat(rules.findByRepository("repo")).hasSize(2);
+  }
+  
+  @Test
+  public void testNonExistingKey() {
+    List<NewRule> newRules = new LinkedList<>();
+    newRules.add(createRule("key1", "repo", "internal"));
+    newRules.add(createRule("key2", "repo", "internal"));
+    
+    DefaultRules rules = new DefaultRules(newRules);
+    assertThat(rules.findByInternalKey("xx", "xx")).hasSize(0);
+    assertThat(rules.find(RuleKey.of("xxx", "xx"))).isNull();
+    assertThat(rules.findByRepository("xxxx")).hasSize(0);
+  }
+  
+  @Test
+  public void testRepeatedRule() {
+    List<NewRule> newRules = new LinkedList<>();
+    newRules.add(createRule("key", "repo", "internal"));
+    newRules.add(createRule("key", "repo", "internal"));
+    
+    DefaultRules rules = new DefaultRules(newRules);
+    assertThat(rules.find(RuleKey.of("repo", "key"))).isNotNull();
+  }
+  
+  private NewRule createRule(String key, String repo, String internalKey) {
+    RuleKey ruleKey = RuleKey.of(repo, key);
+    NewRule newRule = new NewRule(ruleKey);
+    newRule.setInternalKey(internalKey);
+    
+    return newRule;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/NewActiveRuleTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/NewActiveRuleTest.java
new file mode 100644 (file)
index 0000000..1485265
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class NewActiveRuleTest {
+
+  private NewActiveRule.Builder builder;
+
+  @Before
+  public void setBuilder() {
+    builder = new NewActiveRule.Builder();
+  }
+
+  @Test
+  public void builder_should_set_every_param() {
+    NewActiveRule rule = builder
+      .setRuleKey(RuleKey.of("foo", "bar"))
+      .setName("name")
+      .setSeverity(org.sonar.api.rule.Severity.CRITICAL)
+      .setParam("key", "value")
+      .setCreatedAt(1_000L)
+      .setUpdatedAt(1_000L)
+      .setInternalKey("internal_key")
+      .setLanguage("language")
+      .setTemplateRuleKey("templateRuleKey")
+      .setQProfileKey("qProfileKey")
+      .build();
+
+    assertThat(rule.ruleKey).isEqualTo(RuleKey.of("foo", "bar"));
+    assertThat(rule.name).isEqualTo("name");
+    assertThat(rule.severity).isEqualTo(org.sonar.api.rule.Severity.CRITICAL);
+    assertThat(rule.params).isEqualTo(ImmutableMap.of("key", "value"));
+    assertThat(rule.createdAt).isEqualTo(1_000L);
+    assertThat(rule.updatedAt).isEqualTo(1_000L);
+    assertThat(rule.internalKey).isEqualTo("internal_key");
+    assertThat(rule.language).isEqualTo("language");
+    assertThat(rule.templateRuleKey).isEqualTo("templateRuleKey");
+    assertThat(rule.qProfileKey).isEqualTo("qProfileKey");
+  }
+
+  @Test
+  public void severity_should_have_default_value() {
+    NewActiveRule rule = builder.build();
+    assertThat(rule.severity).isEqualTo(Severity.defaultSeverity());
+  }
+
+  @Test
+  public void params_should_be_empty_map_if_no_params() {
+    NewActiveRule rule = builder.build();
+    assertThat(rule.params).isEqualTo(ImmutableMap.of());
+  }
+
+  @Test
+  public void set_param_remove_param_if_value_is_null() {
+    NewActiveRule rule = builder
+      .setParam("foo", "bar")
+      .setParam("removed", "value")
+      .setParam("removed", null)
+      .build();
+    assertThat(rule.params).isEqualTo(ImmutableMap.of("foo", "bar"));
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java
new file mode 100644 (file)
index 0000000..8cb59a8
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.rule.internal;
+
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.rule.Rule;
+import org.sonar.api.batch.rule.Rules;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RulesBuilderTest {
+  @org.junit.Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Test
+  public void no_rules() {
+    RulesBuilder builder = new RulesBuilder();
+    Rules rules = builder.build();
+    assertThat(rules.findAll()).isEmpty();
+  }
+
+  @Test
+  public void build_rules() {
+    RulesBuilder builder = new RulesBuilder();
+    NewRule newSquid1 = builder.add(RuleKey.of("squid", "S0001"));
+    newSquid1.setName("Detect bug");
+    newSquid1.setDescription("Detect potential bug");
+    newSquid1.setInternalKey("foo=bar");
+    newSquid1.setSeverity(org.sonar.api.rule.Severity.CRITICAL);
+    newSquid1.setStatus(RuleStatus.BETA);
+    newSquid1.addParam("min");
+    newSquid1.addParam("max").setDescription("Maximum");
+    // most simple rule
+    builder.add(RuleKey.of("squid", "S0002"));
+    builder.add(RuleKey.of("findbugs", "NPE"));
+
+    Rules rules = builder.build();
+
+    assertThat(rules.findAll()).hasSize(3);
+    assertThat(rules.findByRepository("squid")).hasSize(2);
+    assertThat(rules.findByRepository("findbugs")).hasSize(1);
+    assertThat(rules.findByRepository("unknown")).isEmpty();
+
+    Rule squid1 = rules.find(RuleKey.of("squid", "S0001"));
+    assertThat(squid1.key().repository()).isEqualTo("squid");
+    assertThat(squid1.key().rule()).isEqualTo("S0001");
+    assertThat(squid1.name()).isEqualTo("Detect bug");
+    assertThat(squid1.description()).isEqualTo("Detect potential bug");
+    assertThat(squid1.internalKey()).isEqualTo("foo=bar");
+    assertThat(squid1.status()).isEqualTo(RuleStatus.BETA);
+    assertThat(squid1.severity()).isEqualTo(org.sonar.api.rule.Severity.CRITICAL);
+    assertThat(squid1.params()).hasSize(2);
+    assertThat(squid1.param("min").key()).isEqualTo("min");
+    assertThat(squid1.param("min").description()).isNull();
+    assertThat(squid1.param("max").key()).isEqualTo("max");
+    assertThat(squid1.param("max").description()).isEqualTo("Maximum");
+
+    Rule squid2 = rules.find(RuleKey.of("squid", "S0002"));
+    assertThat(squid2.key().repository()).isEqualTo("squid");
+    assertThat(squid2.key().rule()).isEqualTo("S0002");
+    assertThat(squid2.description()).isNull();
+    assertThat(squid2.internalKey()).isNull();
+    assertThat(squid2.status()).isEqualTo(RuleStatus.defaultStatus());
+    assertThat(squid2.severity()).isEqualTo(Severity.defaultSeverity());
+    assertThat(squid2.params()).isEmpty();
+  }
+
+  @Test
+  public void fail_to_add_twice_the_same_rule() {
+    RulesBuilder builder = new RulesBuilder();
+    builder.add(RuleKey.of("squid", "S0001"));
+
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("Rule 'squid:S0001' already exists");
+
+    builder.add(RuleKey.of("squid", "S0001"));
+  }
+
+  @Test
+  public void fail_to_add_twice_the_same_param() {
+    RulesBuilder builder = new RulesBuilder();
+    NewRule newRule = builder.add(RuleKey.of("squid", "S0001"));
+    newRule.addParam("min");
+    newRule.addParam("max");
+
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("Parameter 'min' already exists on rule 'squid:S0001'");
+
+    newRule.addParam("min");
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCodeTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/code/internal/DefaultSignificantCodeTest.java
new file mode 100644 (file)
index 0000000..ca84d64
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.code.internal;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class DefaultSignificantCodeTest {
+  private SensorStorage sensorStorage = mock(SensorStorage.class);
+  private DefaultSignificantCode underTest = new DefaultSignificantCode(sensorStorage);
+  private InputFile inputFile = TestInputFileBuilder.create("module", "file1.xoo")
+    .setContents("this is\na file\n with some code")
+    .build();
+
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
+  @Test
+  public void should_save_ranges() {
+    underTest.onFile(inputFile)
+      .addRange(inputFile.selectLine(1))
+      .save();
+    verify(sensorStorage).store(underTest);
+  }
+
+  @Test
+  public void fail_if_save_without_file() {
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Call onFile() first");
+    underTest.save();
+  }
+
+  @Test
+  public void fail_if_add_range_to_same_line_twice() {
+    underTest.onFile(inputFile);
+    underTest.addRange(inputFile.selectLine(1));
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Significant code was already reported for line '1'.");
+    underTest.addRange(inputFile.selectLine(1));
+  }
+
+  @Test
+  public void fail_if_range_includes_many_lines() {
+    underTest.onFile(inputFile);
+
+    exception.expect(IllegalArgumentException.class);
+    exception.expectMessage("Ranges of significant code must be located in a single line");
+    underTest.addRange(inputFile.newRange(1, 1, 2, 1));
+  }
+
+  @Test
+  public void fail_if_add_range_before_setting_file() {
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("addRange() should be called after on()");
+    underTest.addRange(inputFile.selectLine(1));
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java
new file mode 100644 (file)
index 0000000..861c10a
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.cpd.internal;
+
+import org.junit.Test;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class DefaultCpdTokensTest {
+  private final SensorStorage sensorStorage = mock(SensorStorage.class);
+
+  private final DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
+    .setLines(2)
+    .setOriginalLineStartOffsets(new int[] {0, 50})
+    .setOriginalLineEndOffsets(new int[] {49, 100})
+    .setLastValidOffset(101)
+    .build();
+
+  @Test
+  public void save_no_tokens() {
+    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+      .onFile(inputFile);
+
+    tokens.save();
+
+    verify(sensorStorage).store(tokens);
+
+    assertThat(tokens.inputFile()).isEqualTo(inputFile);
+  }
+
+  @Test
+  public void save_one_token() {
+    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+      .onFile(inputFile)
+      .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+
+    tokens.save();
+
+    verify(sensorStorage).store(tokens);
+
+    assertThat(tokens.getTokenLines()).extracting("value", "startLine", "hashCode", "startUnit", "endUnit").containsExactly(tuple("foo", 1, "foo".hashCode(), 1, 1));
+  }
+
+  @Test
+  public void handle_exclusions() {
+    inputFile.setExcludedForDuplication(true);
+    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+      .onFile(inputFile)
+      .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+
+    tokens.save();
+
+    verifyZeroInteractions(sensorStorage);
+
+    assertThat(tokens.getTokenLines()).isEmpty();
+  }
+
+  @Test
+  public void dont_save_for_test_files() {
+    DefaultInputFile testInputFile = new TestInputFileBuilder("foo", "src/Foo.java")
+      .setLines(2)
+      .setOriginalLineStartOffsets(new int[] {0, 50})
+      .setOriginalLineEndOffsets(new int[] {49, 100})
+      .setLastValidOffset(101)
+      .setType(InputFile.Type.TEST)
+      .build();
+
+    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+      .onFile(testInputFile)
+      .addToken(testInputFile.newRange(1, 2, 1, 5), "foo");
+
+    tokens.save();
+    verifyZeroInteractions(sensorStorage);
+    assertThat(tokens.getTokenLines()).isEmpty();
+  }
+
+  @Test
+  public void save_many_tokens() {
+    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+      .onFile(inputFile)
+      .addToken(inputFile.newRange(1, 2, 1, 5), "foo")
+      .addToken(inputFile.newRange(1, 6, 1, 10), "bar")
+      .addToken(inputFile.newRange(1, 20, 1, 25), "biz")
+      .addToken(inputFile.newRange(2, 1, 2, 10), "next");
+
+    tokens.save();
+
+    verify(sensorStorage).store(tokens);
+
+    assertThat(tokens.getTokenLines())
+      .extracting("value", "startLine", "hashCode", "startUnit", "endUnit")
+      .containsExactly(
+        tuple("foobarbiz", 1, "foobarbiz".hashCode(), 1, 3),
+        tuple("next", 2, "next".hashCode(), 4, 4));
+  }
+
+  @Test
+  public void basic_validation() {
+    SensorStorage sensorStorage = mock(SensorStorage.class);
+    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage);
+    try {
+      tokens.save();
+      fail("Expected exception");
+    } catch (Exception e) {
+      assertThat(e).hasMessage("Call onFile() first");
+    }
+    try {
+      tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+      fail("Expected exception");
+    } catch (Exception e) {
+      assertThat(e).hasMessage("Call onFile() first");
+    }
+    try {
+      tokens.addToken(null, "foo");
+      fail("Expected exception");
+    } catch (Exception e) {
+      assertThat(e).hasMessage("Range should not be null");
+    }
+    try {
+      tokens.addToken(inputFile.newRange(1, 2, 1, 5), null);
+      fail("Expected exception");
+    } catch (Exception e) {
+      assertThat(e).hasMessage("Image should not be null");
+    }
+  }
+
+  @Test
+  public void validate_tokens_order() {
+    SensorStorage sensorStorage = mock(SensorStorage.class);
+    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+      .onFile(inputFile)
+      .addToken(inputFile.newRange(1, 6, 1, 10), "bar");
+
+    try {
+      tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
+      fail("Expected exception");
+    } catch (Exception e) {
+      assertThat(e).hasMessage("Tokens of file src/Foo.java should be provided in order.\n" +
+        "Previous token: Range[from [line=1, lineOffset=6] to [line=1, lineOffset=10]]\n" +
+        "Last token: Range[from [line=1, lineOffset=2] to [line=1, lineOffset=5]]");
+    }
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisErrorTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/error/internal/DefaultAnalysisErrorTest.java
new file mode 100644 (file)
index 0000000..2b13f62
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.error.internal;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.error.NewAnalysisError;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static org.junit.Assert.fail;
+
+public class DefaultAnalysisErrorTest {
+  private InputFile inputFile;
+  private SensorStorage storage;
+  private TextPointer textPointer;
+
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
+  @Before
+  public void setUp() {
+    inputFile = new TestInputFileBuilder("module1", "src/File.java").build();
+    textPointer = new DefaultTextPointer(5, 2);
+    storage = Mockito.mock(SensorStorage.class);
+  }
+
+  @Test
+  public void test_analysis_error() {
+    DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
+    analysisError.onFile(inputFile)
+      .at(textPointer)
+      .message("msg");
+
+    Assertions.assertThat(analysisError.location()).isEqualTo(textPointer);
+    Assertions.assertThat(analysisError.message()).isEqualTo("msg");
+    Assertions.assertThat(analysisError.inputFile()).isEqualTo(inputFile);
+  }
+
+  @Test
+  public void test_save() {
+    DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
+    analysisError.onFile(inputFile).save();
+
+    Mockito.verify(storage).store(analysisError);
+    Mockito.verifyNoMoreInteractions(storage);
+  }
+
+  @Test
+  public void test_no_storage() {
+    exception.expect(NullPointerException.class);
+    DefaultAnalysisError analysisError = new DefaultAnalysisError();
+    analysisError.onFile(inputFile).save();
+  }
+
+  @Test
+  public void test_validation() {
+    try {
+      new DefaultAnalysisError(storage).onFile(null);
+      fail("Expected exception");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+
+    NewAnalysisError error = new DefaultAnalysisError(storage).onFile(inputFile);
+    try {
+      error.onFile(inputFile);
+      fail("Expected exception");
+    } catch (IllegalStateException e) {
+      // expected
+    }
+
+    error = new DefaultAnalysisError(storage).at(textPointer);
+    try {
+      error.at(textPointer);
+      fail("Expected exception");
+    } catch (IllegalStateException e) {
+      // expected
+    }
+
+    try {
+      new DefaultAnalysisError(storage).save();
+      fail("Expected exception");
+    } catch (NullPointerException e) {
+      // expected
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java
new file mode 100644 (file)
index 0000000..d4dba09
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.highlighting.internal;
+
+import java.util.Collection;
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.DefaultTextRange;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.COMMENT;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.CPP_DOC;
+import static org.sonar.api.batch.sensor.highlighting.TypeOfText.KEYWORD;
+
+public class DefaultHighlightingTest {
+
+  private static final InputFile INPUT_FILE = new TestInputFileBuilder("foo", "src/Foo.java")
+    .setLines(2)
+    .setOriginalLineStartOffsets(new int[] {0, 50})
+    .setOriginalLineEndOffsets(new int[] {49, 100})
+    .setLastValidOffset(101)
+    .build();
+
+  private Collection<SyntaxHighlightingRule> highlightingRules;
+
+  @Rule
+  public ExpectedException throwable = ExpectedException.none();
+
+  @Before
+  public void setUpSampleRules() {
+
+    DefaultHighlighting highlightingDataBuilder = new DefaultHighlighting(Mockito.mock(SensorStorage.class))
+      .onFile(INPUT_FILE)
+      .highlight(0, 10, COMMENT)
+      .highlight(1, 10, 1, 12, KEYWORD)
+      .highlight(24, 38, KEYWORD)
+      .highlight(42, 50, KEYWORD)
+      .highlight(24, 65, CPP_DOC)
+      .highlight(12, 20, COMMENT);
+
+    highlightingDataBuilder.save();
+
+    highlightingRules = highlightingDataBuilder.getSyntaxHighlightingRuleSet();
+  }
+
+  @Test
+  public void should_register_highlighting_rule() {
+    Assertions.assertThat(highlightingRules).hasSize(6);
+  }
+
+  private static TextRange rangeOf(int startLine, int startOffset, int endLine, int endOffset) {
+    return new DefaultTextRange(new DefaultTextPointer(startLine, startOffset), new DefaultTextPointer(endLine, endOffset));
+  }
+
+  @Test
+  public void should_order_by_start_then_end_offset() {
+    Assertions.assertThat(highlightingRules).extracting("range", TextRange.class).containsExactly(
+      rangeOf(1, 0, 1, 10),
+      rangeOf(1, 10, 1, 12),
+      rangeOf(1, 12, 1, 20),
+      rangeOf(1, 24, 2, 15),
+      rangeOf(1, 24, 1, 38),
+      rangeOf(1, 42, 2, 0));
+    Assertions.assertThat(highlightingRules).extracting("textType").containsExactly(COMMENT, KEYWORD, COMMENT, CPP_DOC, KEYWORD, KEYWORD);
+  }
+
+  @Test
+  public void should_support_overlapping() {
+    new DefaultHighlighting(Mockito.mock(SensorStorage.class))
+      .onFile(INPUT_FILE)
+      .highlight(0, 15, KEYWORD)
+      .highlight(8, 12, CPP_DOC)
+      .save();
+  }
+
+  @Test
+  public void should_prevent_start_equal_end() {
+    throwable.expect(IllegalArgumentException.class);
+    throwable
+      .expectMessage("Unable to highlight file");
+
+    new DefaultHighlighting(Mockito.mock(SensorStorage.class))
+      .onFile(INPUT_FILE)
+      .highlight(10, 10, KEYWORD)
+      .save();
+  }
+
+  @Test
+  public void should_prevent_boudaries_overlapping() {
+    throwable.expect(IllegalStateException.class);
+    throwable
+      .expectMessage("Cannot register highlighting rule for characters at Range[from [line=1, lineOffset=8] to [line=1, lineOffset=15]] as it overlaps at least one existing rule");
+
+    new DefaultHighlighting(Mockito.mock(SensorStorage.class))
+      .onFile(INPUT_FILE)
+      .highlight(0, 10, KEYWORD)
+      .highlight(8, 15, KEYWORD)
+      .save();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptorTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/DefaultSensorDescriptorTest.java
new file mode 100644 (file)
index 0000000..25a1088
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.internal;
+
+import org.junit.Test;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.config.internal.MapSettings;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultSensorDescriptorTest {
+
+  @Test
+  public void describe() {
+    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor();
+    descriptor
+      .name("Foo")
+      .onlyOnLanguage("java")
+      .onlyOnFileType(InputFile.Type.MAIN)
+      .requireProperty("sonar.foo.reportPath", "sonar.foo.reportPath2")
+      .createIssuesForRuleRepository("squid-java");
+
+    assertThat(descriptor.name()).isEqualTo("Foo");
+    assertThat(descriptor.languages()).containsOnly("java");
+    assertThat(descriptor.type()).isEqualTo(InputFile.Type.MAIN);
+    MapSettings settings = new MapSettings();
+    settings.setProperty("sonar.foo.reportPath", "foo");
+    assertThat(descriptor.configurationPredicate().test(settings.asConfig())).isFalse();
+    settings.setProperty("sonar.foo.reportPath2", "foo");
+    assertThat(descriptor.configurationPredicate().test(settings.asConfig())).isTrue();
+    assertThat(descriptor.ruleRepositories()).containsOnly("squid-java");
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorageTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/InMemorySensorStorageTest.java
new file mode 100644 (file)
index 0000000..fe3ce41
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.internal;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.data.MapEntry.entry;
+
+public class InMemorySensorStorageTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  InMemorySensorStorage underTest = new InMemorySensorStorage();
+
+  @Test
+  public void test_storeProperty() {
+    assertThat(underTest.contextProperties).isEmpty();
+
+    underTest.storeProperty("foo", "bar");
+    assertThat(underTest.contextProperties).containsOnly(entry("foo", "bar"));
+  }
+
+  @Test
+  public void storeProperty_throws_IAE_if_key_is_null() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Key of context property must not be null");
+
+    underTest.storeProperty(null, "bar");
+  }
+
+  @Test
+  public void storeProperty_throws_IAE_if_value_is_null() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Value of context property must not be null");
+
+    underTest.storeProperty("foo", null);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
new file mode 100644 (file)
index 0000000..f9de1dc
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.internal;
+
+import java.io.File;
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.error.AnalysisError;
+import org.sonar.api.batch.sensor.error.NewAnalysisError;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.batch.sensor.issue.NewExternalIssue;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
+import org.sonar.api.config.Settings;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RuleType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.assertj.core.data.MapEntry.entry;
+
+public class SensorContextTesterTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
+  private SensorContextTester tester;
+  private File baseDir;
+
+  @Before
+  public void prepare() throws Exception {
+    baseDir = temp.newFolder();
+    tester = SensorContextTester.create(baseDir);
+  }
+
+  @Test
+  public void testSettings() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "bar");
+    tester.setSettings(settings);
+    assertThat(tester.settings().getString("foo")).isEqualTo("bar");
+  }
+
+  @Test
+  public void testActiveRules() {
+    NewActiveRule activeRule = new NewActiveRule.Builder()
+      .setRuleKey(RuleKey.of("foo", "bar"))
+      .build();
+    ActiveRules activeRules = new ActiveRulesBuilder().addRule(activeRule).build();
+    tester.setActiveRules(activeRules);
+    assertThat(tester.activeRules().findAll()).hasSize(1);
+  }
+
+  @Test
+  public void testFs() throws Exception {
+    DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder());
+    tester.setFileSystem(fs);
+    assertThat(tester.fileSystem().baseDir()).isNotEqualTo(baseDir);
+  }
+
+  @Test
+  public void testIssues() {
+    assertThat(tester.allIssues()).isEmpty();
+    NewIssue newIssue = tester.newIssue();
+    newIssue
+      .at(newIssue.newLocation().on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
+      .forRule(RuleKey.of("repo", "rule"))
+      .save();
+    newIssue = tester.newIssue();
+    newIssue
+      .at(newIssue.newLocation().on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
+      .forRule(RuleKey.of("repo", "rule"))
+      .save();
+    assertThat(tester.allIssues()).hasSize(2);
+  }
+
+  @Test
+  public void testExternalIssues() {
+    assertThat(tester.allExternalIssues()).isEmpty();
+    NewExternalIssue newExternalIssue = tester.newExternalIssue();
+    newExternalIssue
+      .at(newExternalIssue.newLocation().message("message").on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
+      .forRule(RuleKey.of("repo", "rule"))
+      .type(RuleType.BUG)
+      .severity(Severity.BLOCKER)
+      .save();
+    newExternalIssue = tester.newExternalIssue();
+    newExternalIssue
+      .at(newExternalIssue.newLocation().message("message").on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
+      .type(RuleType.BUG)
+      .severity(Severity.BLOCKER)
+      .forRule(RuleKey.of("repo", "rule"))
+      .save();
+    assertThat(tester.allExternalIssues()).hasSize(2);
+  }
+
+  @Test
+  public void testAnalysisErrors() {
+    assertThat(tester.allAnalysisErrors()).isEmpty();
+    NewAnalysisError newAnalysisError = tester.newAnalysisError();
+
+    InputFile file = new TestInputFileBuilder("foo", "src/Foo.java").build();
+    newAnalysisError.onFile(file)
+      .message("error")
+      .at(new DefaultTextPointer(5, 2))
+      .save();
+
+    assertThat(tester.allAnalysisErrors()).hasSize(1);
+    AnalysisError analysisError = tester.allAnalysisErrors().iterator().next();
+
+    assertThat(analysisError.inputFile()).isEqualTo(file);
+    assertThat(analysisError.message()).isEqualTo("error");
+    assertThat(analysisError.location()).isEqualTo(new DefaultTextPointer(5, 2));
+
+  }
+
+  @Test
+  public void testMeasures() throws IOException {
+    assertThat(tester.measures("foo:src/Foo.java")).isEmpty();
+    assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNull();
+    tester.<Integer>newMeasure()
+      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
+      .forMetric(CoreMetrics.NCLOC)
+      .withValue(2)
+      .save();
+    assertThat(tester.measures("foo:src/Foo.java")).hasSize(1);
+    assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNotNull();
+    tester.<Integer>newMeasure()
+      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
+      .forMetric(CoreMetrics.LINES)
+      .withValue(4)
+      .save();
+    assertThat(tester.measures("foo:src/Foo.java")).hasSize(2);
+    assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNotNull();
+    assertThat(tester.measure("foo:src/Foo.java", "lines")).isNotNull();
+    tester.<Integer>newMeasure()
+      .on(new DefaultInputModule(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder())))
+      .forMetric(CoreMetrics.DIRECTORIES)
+      .withValue(4)
+      .save();
+    assertThat(tester.measures("foo")).hasSize(1);
+    assertThat(tester.measure("foo", "directories")).isNotNull();
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void duplicateMeasures() {
+    tester.<Integer>newMeasure()
+      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
+      .forMetric(CoreMetrics.NCLOC)
+      .withValue(2)
+      .save();
+    tester.<Integer>newMeasure()
+      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
+      .forMetric(CoreMetrics.NCLOC)
+      .withValue(2)
+      .save();
+  }
+
+  @Test
+  public void testHighlighting() {
+    assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 3)).isEmpty();
+    tester.newHighlighting()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
+      .highlight(1, 0, 1, 5, TypeOfText.ANNOTATION)
+      .highlight(8, 10, TypeOfText.CONSTANT)
+      .highlight(9, 10, TypeOfText.COMMENT)
+      .save();
+    assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 3)).containsExactly(TypeOfText.ANNOTATION);
+    assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 9)).containsExactly(TypeOfText.CONSTANT, TypeOfText.COMMENT);
+  }
+
+  @Test(expected = UnsupportedOperationException.class)
+  public void duplicateHighlighting() {
+    tester.newHighlighting()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
+      .highlight(1, 0, 1, 5, TypeOfText.ANNOTATION)
+      .save();
+    tester.newHighlighting()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
+      .highlight(1, 0, 1, 5, TypeOfText.ANNOTATION)
+      .save();
+  }
+
+  @Test
+  public void testSymbolReferences() {
+    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 0)).isNull();
+
+    NewSymbolTable symbolTable = tester.newSymbolTable()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build());
+    symbolTable
+      .newSymbol(1, 8, 1, 10);
+
+    symbolTable
+      .newSymbol(1, 1, 1, 5)
+      .newReference(6, 9)
+      .newReference(1, 10, 1, 13);
+
+    symbolTable.save();
+
+    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 0)).isNull();
+    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 8)).isEmpty();
+    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 3)).extracting("start.line", "start.lineOffset", "end.line", "end.lineOffset").containsExactly(tuple(1, 6, 1, 9),
+      tuple(1, 10, 1, 13));
+  }
+
+  @Test(expected = UnsupportedOperationException.class)
+  public void duplicateSymbolReferences() {
+    NewSymbolTable symbolTable = tester.newSymbolTable()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build());
+    symbolTable
+      .newSymbol(1, 8, 1, 10);
+
+    symbolTable.save();
+
+    symbolTable = tester.newSymbolTable()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build());
+    symbolTable
+      .newSymbol(1, 8, 1, 10);
+
+    symbolTable.save();
+  }
+
+  @Test
+  public void testCoverageAtLineZero() {
+    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isNull();
+    assertThat(tester.lineHits("foo:src/Foo.java", 4)).isNull();
+
+    exception.expect(IllegalStateException.class);
+    tester.newCoverage()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
+      .lineHits(0, 3);
+  }
+
+  @Test
+  public void testCoverageAtLineOutOfRange() {
+    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isNull();
+    assertThat(tester.lineHits("foo:src/Foo.java", 4)).isNull();
+    exception.expect(IllegalStateException.class);
+
+    tester.newCoverage()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
+      .lineHits(4, 3);
+  }
+
+  @Test
+  public void testLineHits() {
+    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isNull();
+    assertThat(tester.lineHits("foo:src/Foo.java", 4)).isNull();
+    tester.newCoverage()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar\nasdas").build())
+      .lineHits(1, 2)
+      .lineHits(2, 3)
+      .save();
+    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isEqualTo(2);
+    assertThat(tester.lineHits("foo:src/Foo.java", 2)).isEqualTo(3);
+  }
+
+  public void multipleCoverage() {
+    tester.newCoverage()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar\nasdas").build())
+      .lineHits(1, 2)
+      .conditions(3, 4, 2)
+      .save();
+    tester.newCoverage()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar\nasdas").build())
+      .lineHits(1, 2)
+      .conditions(3, 4, 3)
+      .save();
+    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isEqualTo(4);
+    assertThat(tester.conditions("foo:src/Foo.java", 3)).isEqualTo(4);
+    assertThat(tester.coveredConditions("foo:src/Foo.java", 3)).isEqualTo(3);
+  }
+
+  @Test
+  public void testConditions() {
+    assertThat(tester.conditions("foo:src/Foo.java", 1)).isNull();
+    assertThat(tester.coveredConditions("foo:src/Foo.java", 1)).isNull();
+    tester.newCoverage()
+      .onFile(new TestInputFileBuilder("foo", "src/Foo.java")
+        .initMetadata("annot dsf fds foo bar\nasd\nasdas\nasdfas")
+        .build())
+      .conditions(1, 4, 2)
+      .save();
+    assertThat(tester.conditions("foo:src/Foo.java", 1)).isEqualTo(4);
+    assertThat(tester.coveredConditions("foo:src/Foo.java", 1)).isEqualTo(2);
+  }
+
+  @Test
+  public void testCpdTokens() {
+    assertThat(tester.cpdTokens("foo:src/Foo.java")).isNull();
+    DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
+      .initMetadata("public class Foo {\n\n}")
+      .build();
+    tester.newCpdTokens()
+      .onFile(inputFile)
+      .addToken(inputFile.newRange(0, 6), "public")
+      .addToken(inputFile.newRange(7, 12), "class")
+      .addToken(inputFile.newRange(13, 16), "$IDENTIFIER")
+      .addToken(inputFile.newRange(17, 18), "{")
+      .addToken(inputFile.newRange(3, 0, 3, 1), "}")
+      .save();
+    assertThat(tester.cpdTokens("foo:src/Foo.java")).extracting("value", "startLine", "startUnit", "endUnit")
+      .containsExactly(
+        tuple("publicclass$IDENTIFIER{", 1, 1, 4),
+        tuple("}", 3, 5, 5));
+  }
+
+  @Test(expected = UnsupportedOperationException.class)
+  public void duplicateCpdTokens() {
+    DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
+      .initMetadata("public class Foo {\n\n}")
+      .build();
+    tester.newCpdTokens()
+      .onFile(inputFile)
+      .addToken(inputFile.newRange(0, 6), "public")
+      .save();
+
+    tester.newCpdTokens()
+      .onFile(inputFile)
+      .addToken(inputFile.newRange(0, 6), "public")
+      .save();
+  }
+
+  @Test
+  public void testCancellation() {
+    assertThat(tester.isCancelled()).isFalse();
+    tester.setCancelled(true);
+    assertThat(tester.isCancelled()).isTrue();
+  }
+
+  @Test
+  public void testContextProperties() {
+    assertThat(tester.getContextProperties()).isEmpty();
+
+    tester.addContextProperty("foo", "bar");
+    assertThat(tester.getContextProperties()).containsOnly(entry("foo", "bar"));
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java
new file mode 100644 (file)
index 0000000..bb06582
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RuleType;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class DefaultExternalIssueTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private DefaultInputProject project;
+
+  @Before
+  public void setup() throws IOException {
+    project = new DefaultInputProject(ProjectDefinition.create()
+      .setKey("foo")
+      .setBaseDir(temp.newFolder())
+      .setWorkDir(temp.newFolder()));
+  }
+
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
+  private DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
+    .initMetadata("Foo\nBar\n")
+    .build();
+
+  @Test
+  public void build_file_issue() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(inputFile)
+        .at(inputFile.selectLine(1))
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .remediationEffortMinutes(10l)
+      .type(RuleType.BUG)
+      .severity(Severity.BLOCKER);
+
+    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(inputFile);
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("external_repo", "rule"));
+    assertThat(issue.engineId()).isEqualTo("repo");
+    assertThat(issue.ruleId()).isEqualTo("rule");
+    assertThat(issue.primaryLocation().textRange().start().line()).isEqualTo(1);
+    assertThat(issue.remediationEffort()).isEqualTo(10l);
+    assertThat(issue.type()).isEqualTo(RuleType.BUG);
+    assertThat(issue.severity()).isEqualTo(Severity.BLOCKER);
+    assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!");
+
+    issue.save();
+
+    verify(storage).store(issue);
+  }
+
+  @Test
+  public void fail_to_store_if_no_type() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(inputFile)
+        .at(inputFile.selectLine(1))
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .remediationEffortMinutes(10l)
+      .severity(Severity.BLOCKER);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Type is mandatory");
+    issue.save();
+  }
+
+  @Test
+  public void fail_to_store_if_primary_location_is_not_a_file() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(mock(InputComponent.class))
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .remediationEffortMinutes(10l)
+      .severity(Severity.BLOCKER);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("External issues must be located in files");
+    issue.save();
+  }
+
+  @Test
+  public void fail_to_store_if_primary_location_has_no_message() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(inputFile)
+        .at(inputFile.selectLine(1)))
+      .forRule(RuleKey.of("repo", "rule"))
+      .remediationEffortMinutes(10l)
+      .type(RuleType.BUG)
+      .severity(Severity.BLOCKER);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("External issues must have a message");
+    issue.save();
+  }
+
+  @Test
+  public void fail_to_store_if_no_severity() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(inputFile)
+        .at(inputFile.selectLine(1))
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .remediationEffortMinutes(10l)
+      .type(RuleType.BUG);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Severity is mandatory");
+    issue.save();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocationTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocationTest.java
new file mode 100644 (file)
index 0000000..2a399c2
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import org.apache.commons.lang.StringUtils;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.rules.ExpectedException.none;
+
+public class DefaultIssueLocationTest {
+
+  @Rule
+  public ExpectedException thrown = none();
+
+  private InputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
+    .initMetadata("Foo\nBar\n")
+    .build();
+
+  @Test
+  public void should_build() {
+    assertThat(new DefaultIssueLocation()
+      .on(inputFile)
+      .message("pipo bimbo")
+      .message()
+    ).isEqualTo("pipo bimbo");
+  }
+
+  @Test
+  public void not_allowed_to_call_on_twice() {
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("on() already called");
+    new DefaultIssueLocation()
+      .on(inputFile)
+      .on(inputFile)
+      .message("Wrong way!");
+  }
+
+  @Test
+  public void prevent_too_long_messages() {
+    assertThat(new DefaultIssueLocation()
+      .on(inputFile)
+      .message(StringUtils.repeat("a", 4000)).message()).hasSize(4000);
+
+    assertThat(new DefaultIssueLocation()
+      .on(inputFile)
+      .message(StringUtils.repeat("a", 4001)).message()).hasSize(4000);
+  }
+
+  @Test
+  public void prevent_null_character_in_message_text() {
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage("Character \\u0000 is not supported in issue message");
+
+    new DefaultIssueLocation()
+      .message("pipo " + '\u0000' + " bimbo");
+  }
+
+  @Test
+  public void prevent_null_character_in_message_text_when_builder_has_been_initialized() {
+    thrown.expect(IllegalArgumentException.class);
+    thrown.expectMessage(customMatcher("Character \\u0000 is not supported in issue message", ", on component: src/Foo.php"));
+
+    new DefaultIssueLocation()
+      .on(inputFile)
+      .message("pipo " + '\u0000' + " bimbo");
+  }
+
+  private Matcher<String> customMatcher(String startWith, String endWith) {
+    return new TypeSafeMatcher<String>() {
+      @Override
+      public void describeTo(Description description) {
+        description.appendText("Invalid message");
+      }
+
+      @Override
+      protected boolean matchesSafely(final String item) {
+        return item.startsWith(startWith) && item.endsWith(endWith);
+      }
+    };
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java
new file mode 100644 (file)
index 0000000..b666f4c
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.issue.internal;
+
+import java.io.File;
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class DefaultIssueTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private DefaultInputProject project;
+
+  private DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
+    .initMetadata("Foo\nBar\n")
+    .build();
+
+  @Before
+  public void prepare() throws IOException {
+    project = new DefaultInputProject(ProjectDefinition.create()
+      .setKey("foo")
+      .setBaseDir(temp.newFolder())
+      .setWorkDir(temp.newFolder()));
+  }
+
+  @Test
+  public void build_file_issue() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultIssue issue = new DefaultIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(inputFile)
+        .at(inputFile.selectLine(1))
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .gap(10.0);
+
+    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(inputFile);
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
+    assertThat(issue.primaryLocation().textRange().start().line()).isEqualTo(1);
+    assertThat(issue.gap()).isEqualTo(10.0);
+    assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!");
+
+    issue.save();
+
+    verify(storage).store(issue);
+  }
+
+  @Test
+  public void move_directory_issue_to_project_root() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultIssue issue = new DefaultIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(new DefaultInputDir("foo", "src/main").setModuleBaseDir(project.getBaseDir()))
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .overrideSeverity(Severity.BLOCKER);
+
+    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(project);
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
+    assertThat(issue.primaryLocation().textRange()).isNull();
+    assertThat(issue.primaryLocation().message()).isEqualTo("[src/main] Wrong way!");
+    assertThat(issue.overriddenSeverity()).isEqualTo(Severity.BLOCKER);
+
+    issue.save();
+
+    verify(storage).store(issue);
+  }
+
+  @Test
+  public void move_submodule_issue_to_project_root() {
+    File subModuleDirectory = new File(project.getBaseDir().toString(), "bar");
+    subModuleDirectory.mkdir();
+
+    ProjectDefinition subModuleDefinition = ProjectDefinition.create()
+      .setKey("foo/bar")
+      .setBaseDir(subModuleDirectory)
+      .setWorkDir(subModuleDirectory);
+    project.definition().addSubProject(subModuleDefinition);
+    DefaultInputModule subModule = new DefaultInputModule(subModuleDefinition);
+
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultIssue issue = new DefaultIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(subModule)
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .overrideSeverity(Severity.BLOCKER);
+
+    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(project);
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
+    assertThat(issue.primaryLocation().textRange()).isNull();
+    assertThat(issue.primaryLocation().message()).isEqualTo("[bar] Wrong way!");
+    assertThat(issue.overriddenSeverity()).isEqualTo(Severity.BLOCKER);
+
+    issue.save();
+
+    verify(storage).store(issue);
+  }
+
+  @Test
+  public void build_project_issue() throws IOException {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultInputModule inputModule = new DefaultInputModule(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()));
+    DefaultIssue issue = new DefaultIssue(project, storage)
+      .at(new DefaultIssueLocation()
+        .on(inputModule)
+        .message("Wrong way!"))
+      .forRule(RuleKey.of("repo", "rule"))
+      .gap(10.0);
+
+    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(inputModule);
+    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
+    assertThat(issue.primaryLocation().textRange()).isNull();
+    assertThat(issue.gap()).isEqualTo(10.0);
+    assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!");
+
+    issue.save();
+
+    verify(storage).store(issue);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java
new file mode 100644 (file)
index 0000000..d640242
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.measure.internal;
+
+import java.io.IOException;
+import org.assertj.core.api.Assertions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.measures.CoreMetrics;
+
+public class DefaultMeasureTest {
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void build_file_measure() {
+    SensorStorage storage = Mockito.mock(SensorStorage.class);
+    DefaultMeasure<Integer> newMeasure = new DefaultMeasure<Integer>(storage)
+      .forMetric(CoreMetrics.LINES)
+      .on(new TestInputFileBuilder("foo", "src/Foo.php").build())
+      .withValue(3);
+
+    Assertions.assertThat(newMeasure.inputComponent()).isEqualTo(new TestInputFileBuilder("foo", "src/Foo.php").build());
+    Assertions.assertThat(newMeasure.metric()).isEqualTo(CoreMetrics.LINES);
+    Assertions.assertThat(newMeasure.value()).isEqualTo(3);
+
+    newMeasure.save();
+
+    Mockito.verify(storage).store(newMeasure);
+  }
+
+  @Test
+  public void build_project_measure() throws IOException {
+    SensorStorage storage = Mockito.mock(SensorStorage.class);
+    AbstractProjectOrModule module = new DefaultInputProject(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()));
+    DefaultMeasure<Integer> newMeasure = new DefaultMeasure<Integer>(storage)
+      .forMetric(CoreMetrics.LINES)
+      .on(module)
+      .withValue(3);
+
+    Assertions.assertThat(newMeasure.inputComponent()).isEqualTo(module);
+    Assertions.assertThat(newMeasure.metric()).isEqualTo(CoreMetrics.LINES);
+    Assertions.assertThat(newMeasure.value()).isEqualTo(3);
+
+    newMeasure.save();
+
+    Mockito.verify(storage).store(newMeasure);
+  }
+
+  @Test
+  public void not_allowed_to_call_on_twice() throws IOException {
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("on() already called");
+    new DefaultMeasure<Integer>()
+      .on(new DefaultInputProject(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder())))
+      .on(new TestInputFileBuilder("foo", "src/Foo.php").build())
+      .withValue(3)
+      .save();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/rule/internal/DefaultAdHocRuleTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/rule/internal/DefaultAdHocRuleTest.java
new file mode 100644 (file)
index 0000000..b30593d
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.rule.internal;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.rule.NewAdHocRule;
+import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
+import org.sonar.api.rules.RuleType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class DefaultAdHocRuleTest {
+
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
+  @Test
+  public void store() {
+    SensorStorage storage = mock(SensorStorage.class);
+    DefaultAdHocRule rule = new DefaultAdHocRule(storage)
+      .engineId("engine")
+      .ruleId("ruleId")
+      .name("name")
+      .description("desc")
+      .severity(Severity.BLOCKER)
+      .type(RuleType.CODE_SMELL);
+      rule.save();
+
+    assertThat(rule.engineId()).isEqualTo("engine");
+    assertThat(rule.ruleId()).isEqualTo("ruleId");
+    assertThat(rule.name()).isEqualTo("name");
+    assertThat(rule.description()).isEqualTo("desc");
+    assertThat(rule.severity()).isEqualTo(Severity.BLOCKER);
+    assertThat(rule.type()).isEqualTo(RuleType.CODE_SMELL);
+
+    verify(storage).store(any(DefaultAdHocRule.class));
+  }
+
+
+  @Test
+  public void description_is_optional() {
+    SensorStorage storage = mock(SensorStorage.class);
+    new DefaultAdHocRule(storage)
+      .engineId("engine")
+      .ruleId("ruleId")
+      .name("name")
+      .severity(Severity.BLOCKER)
+      .type(RuleType.CODE_SMELL)
+      .save();
+
+    verify(storage).store(any(DefaultAdHocRule.class));
+  }
+
+  @Test
+  public void fail_to_store_if_no_engine_id() {
+    SensorStorage storage = mock(SensorStorage.class);
+    NewAdHocRule rule = new DefaultAdHocRule(storage)
+      .engineId(" ")
+      .ruleId("ruleId")
+      .name("name")
+      .description("desc")
+      .severity(Severity.BLOCKER)
+      .type(RuleType.CODE_SMELL);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Engine id is mandatory");
+    rule.save();
+  }
+
+  @Test
+  public void fail_to_store_if_no_rule_id() {
+    SensorStorage storage = mock(SensorStorage.class);
+    NewAdHocRule rule = new DefaultAdHocRule(storage)
+      .engineId("engine")
+      .ruleId("  ")
+      .name("name")
+      .description("desc")
+      .severity(Severity.BLOCKER)
+      .type(RuleType.CODE_SMELL);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Rule id is mandatory");
+    rule.save();
+  }
+
+  @Test
+  public void fail_to_store_if_no_name() {
+    SensorStorage storage = mock(SensorStorage.class);
+    NewAdHocRule rule = new DefaultAdHocRule(storage)
+      .engineId("engine")
+      .ruleId("ruleId")
+      .name("  ")
+      .description("desc")
+      .severity(Severity.BLOCKER)
+      .type(RuleType.CODE_SMELL);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Name is mandatory");
+    rule.save();
+  }
+
+
+  @Test
+  public void fail_to_store_if_no_severity() {
+    SensorStorage storage = mock(SensorStorage.class);
+    NewAdHocRule rule = new DefaultAdHocRule(storage)
+      .engineId("engine")
+      .ruleId("ruleId")
+      .name("name")
+      .description("desc")
+      .type(RuleType.CODE_SMELL);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Severity is mandatory");
+    rule.save();
+  }
+
+  @Test
+  public void fail_to_store_if_no_type() {
+    SensorStorage storage = mock(SensorStorage.class);
+    NewAdHocRule rule = new DefaultAdHocRule(storage)
+      .engineId("engine")
+      .ruleId("ruleId")
+      .name("name")
+      .description("desc")
+      .severity(Severity.BLOCKER);
+
+    exception.expect(IllegalStateException.class);
+    exception.expectMessage("Type is mandatory");
+    rule.save();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java
new file mode 100644 (file)
index 0000000..52ae8d8
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.batch.sensor.symbol.internal;
+
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class DefaultSymbolTableTest {
+
+  private static final InputFile INPUT_FILE = new TestInputFileBuilder("foo", "src/Foo.java")
+    .setLines(2)
+    .setOriginalLineStartOffsets(new int[] {0, 50})
+    .setOriginalLineEndOffsets(new int[] {49, 100})
+    .setLastValidOffset(101)
+    .build();
+
+  private Map<TextRange, Set<TextRange>> referencesPerSymbol;
+
+  @Rule
+  public ExpectedException throwable = ExpectedException.none();
+
+  @Before
+  public void setUpSampleSymbols() {
+
+    DefaultSymbolTable symbolTableBuilder = new DefaultSymbolTable(mock(SensorStorage.class))
+      .onFile(INPUT_FILE);
+    symbolTableBuilder
+      .newSymbol(0, 10)
+      .newReference(12, 15)
+      .newReference(2, 10, 2, 15);
+
+    symbolTableBuilder.newSymbol(1, 12, 1, 15).newReference(52, 55);
+
+    symbolTableBuilder.save();
+
+    referencesPerSymbol = symbolTableBuilder.getReferencesBySymbol();
+  }
+
+  @Test
+  public void should_register_symbols() {
+    assertThat(referencesPerSymbol).hasSize(2);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/config/internal/MapSettingsTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/config/internal/MapSettingsTest.java
new file mode 100644 (file)
index 0000000..a793aa7
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.config.internal;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+import java.util.function.BiConsumer;
+import java.util.stream.IntStream;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.data.Offset;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
+import org.sonar.api.PropertyType;
+import org.sonar.api.config.PropertyDefinition;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.DateUtils;
+
+import static java.util.Collections.singletonList;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(DataProviderRunner.class)
+public class MapSettingsTest {
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private PropertyDefinitions definitions;
+
+  @Properties({
+    @Property(key = "hello", name = "Hello", defaultValue = "world"),
+    @Property(key = "date", name = "Date", defaultValue = "2010-05-18"),
+    @Property(key = "datetime", name = "DateTime", defaultValue = "2010-05-18T15:50:45+0100"),
+    @Property(key = "boolean", name = "Boolean", defaultValue = "true"),
+    @Property(key = "falseboolean", name = "False Boolean", defaultValue = "false"),
+    @Property(key = "integer", name = "Integer", defaultValue = "12345"),
+    @Property(key = "array", name = "Array", defaultValue = "one,two,three"),
+    @Property(key = "multi_values", name = "Array", defaultValue = "1,2,3", multiValues = true),
+    @Property(key = "sonar.jira", name = "Jira Server", type = PropertyType.PROPERTY_SET, propertySetKey = "jira"),
+    @Property(key = "newKey", name = "New key", deprecatedKey = "oldKey"),
+    @Property(key = "newKeyWithDefaultValue", name = "New key with default value", deprecatedKey = "oldKeyWithDefaultValue", defaultValue = "default_value"),
+    @Property(key = "new_multi_values", name = "New multi values", defaultValue = "1,2,3", multiValues = true, deprecatedKey = "old_multi_values")
+  })
+  private static class Init {
+  }
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Before
+  public void init_definitions() {
+    definitions = new PropertyDefinitions();
+    definitions.addComponent(Init.class);
+  }
+
+  @Test
+  public void set_throws_NPE_if_key_is_null() {
+    MapSettings underTest = new MapSettings();
+
+    expectKeyNullNPE();
+
+    underTest.set(null, randomAlphanumeric(3));
+  }
+
+  @Test
+  public void set_throws_NPE_if_value_is_null() {
+    MapSettings underTest = new MapSettings();
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("value can't be null");
+
+    underTest.set(randomAlphanumeric(3), null);
+  }
+
+  @Test
+  public void set_accepts_empty_value_and_trims_it() {
+    MapSettings underTest = new MapSettings();
+    Random random = new Random();
+    String key = randomAlphanumeric(3);
+
+    underTest.set(key, blank(random));
+
+    assertThat(underTest.getString(key)).isEmpty();
+  }
+
+  @Test
+  public void default_values_should_be_loaded_from_definitions() {
+    Settings settings = new MapSettings(definitions);
+    assertThat(settings.getDefaultValue("hello")).isEqualTo("world");
+  }
+
+  @Test
+  @UseDataProvider("setPropertyCalls")
+  public void all_setProperty_methods_throws_NPE_if_key_is_null(BiConsumer<Settings, String> setPropertyCaller) {
+    Settings settings = new MapSettings();
+
+    expectKeyNullNPE();
+
+    setPropertyCaller.accept(settings, null);
+  }
+
+  @Test
+  public void set_property_string_throws_NPE_if_key_is_null() {
+    String key = randomAlphanumeric(3);
+
+    Settings underTest = new MapSettings(new PropertyDefinitions(singletonList(PropertyDefinition.builder(key).multiValues(true).build())));
+
+    expectKeyNullNPE();
+
+    underTest.setProperty(null, new String[] {"1", "2"});
+  }
+
+  private void expectKeyNullNPE() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("key can't be null");
+  }
+
+  @Test
+  @UseDataProvider("setPropertyCalls")
+  public void all_set_property_methods_trims_key(BiConsumer<Settings, String> setPropertyCaller) {
+    Settings underTest = new MapSettings();
+
+    Random random = new Random();
+    String blankBefore = blank(random);
+    String blankAfter = blank(random);
+    String key = randomAlphanumeric(3);
+
+    setPropertyCaller.accept(underTest, blankBefore + key + blankAfter);
+
+    assertThat(underTest.hasKey(key)).isTrue();
+  }
+
+  @Test
+  public void set_property_string_array_trims_key() {
+    String key = randomAlphanumeric(3);
+
+    Settings underTest = new MapSettings(new PropertyDefinitions(singletonList(PropertyDefinition.builder(key).multiValues(true).build())));
+
+    Random random = new Random();
+    String blankBefore = blank(random);
+    String blankAfter = blank(random);
+
+    underTest.setProperty(blankBefore + key + blankAfter, new String[] {"1", "2"});
+
+    assertThat(underTest.hasKey(key)).isTrue();
+  }
+
+  private static String blank(Random random) {
+    StringBuilder b = new StringBuilder();
+    IntStream.range(0, random.nextInt(3)).mapToObj(s -> " ").forEach(b::append);
+    return b.toString();
+  }
+
+  @DataProvider
+  public static Object[][] setPropertyCalls() {
+    List<BiConsumer<Settings, String>> callers = Arrays.asList(
+      (settings, key) -> settings.setProperty(key, 123),
+      (settings, key) -> settings.setProperty(key, 123L),
+      (settings, key) -> settings.setProperty(key, 123.2F),
+      (settings, key) -> settings.setProperty(key, 123.2D),
+      (settings, key) -> settings.setProperty(key, false),
+      (settings, key) -> settings.setProperty(key, new Date()),
+      (settings, key) -> settings.setProperty(key, new Date(), true));
+
+    return callers.stream().map(t -> new Object[] {t}).toArray(Object[][]::new);
+  }
+
+  @Test
+  public void setProperty_methods_trims_value() {
+    Settings underTest = new MapSettings();
+
+    Random random = new Random();
+    String blankBefore = blank(random);
+    String blankAfter = blank(random);
+    String key = randomAlphanumeric(3);
+    String value = randomAlphanumeric(3);
+
+    underTest.setProperty(key, blankBefore + value + blankAfter);
+
+    assertThat(underTest.getString(key)).isEqualTo(value);
+  }
+
+  @Test
+  public void set_property_int() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", 123);
+    assertThat(settings.getInt("foo")).isEqualTo(123);
+    assertThat(settings.getString("foo")).isEqualTo("123");
+    assertThat(settings.getBoolean("foo")).isFalse();
+  }
+
+  @Test
+  public void default_number_values_are_zero() {
+    Settings settings = new MapSettings();
+    assertThat(settings.getInt("foo")).isEqualTo(0);
+    assertThat(settings.getLong("foo")).isEqualTo(0L);
+  }
+
+  @Test
+  public void getInt_value_must_be_valid() {
+    thrown.expect(NumberFormatException.class);
+
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "not a number");
+    settings.getInt("foo");
+  }
+
+  @Test
+  public void all_values_should_be_trimmed_set_property() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "   FOO ");
+    assertThat(settings.getString("foo")).isEqualTo("FOO");
+  }
+
+  @Test
+  public void test_get_default_value() {
+    Settings settings = new MapSettings(definitions);
+    assertThat(settings.getDefaultValue("unknown")).isNull();
+  }
+
+  @Test
+  public void test_get_string() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("hello", "Russia");
+    assertThat(settings.getString("hello")).isEqualTo("Russia");
+  }
+
+  @Test
+  public void setProperty_date() {
+    Settings settings = new MapSettings();
+    Date date = DateUtils.parseDateTime("2010-05-18T15:50:45+0100");
+    settings.setProperty("aDate", date);
+    settings.setProperty("aDateTime", date, true);
+
+    assertThat(settings.getString("aDate")).isEqualTo("2010-05-18");
+    assertThat(settings.getString("aDateTime")).startsWith("2010-05-18T");
+  }
+
+  @Test
+  public void test_get_date() {
+    Settings settings = new MapSettings(definitions);
+    assertThat(settings.getDate("unknown")).isNull();
+    assertThat(settings.getDate("date").getDate()).isEqualTo(18);
+    assertThat(settings.getDate("date").getMonth()).isEqualTo(4);
+  }
+
+  @Test
+  public void test_get_date_not_found() {
+    Settings settings = new MapSettings(definitions);
+    assertThat(settings.getDate("unknown")).isNull();
+  }
+
+  @Test
+  public void test_get_datetime() {
+    Settings settings = new MapSettings(definitions);
+    assertThat(settings.getDateTime("unknown")).isNull();
+    assertThat(settings.getDateTime("datetime").getDate()).isEqualTo(18);
+    assertThat(settings.getDateTime("datetime").getMonth()).isEqualTo(4);
+    assertThat(settings.getDateTime("datetime").getMinutes()).isEqualTo(50);
+  }
+
+  @Test
+  public void test_get_double() {
+    Settings settings = new MapSettings();
+    settings.setProperty("from_double", 3.14159);
+    settings.setProperty("from_string", "3.14159");
+    assertThat(settings.getDouble("from_double")).isEqualTo(3.14159, Offset.offset(0.00001));
+    assertThat(settings.getDouble("from_string")).isEqualTo(3.14159, Offset.offset(0.00001));
+    assertThat(settings.getDouble("unknown")).isNull();
+  }
+
+  @Test
+  public void test_get_float() {
+    Settings settings = new MapSettings();
+    settings.setProperty("from_float", 3.14159f);
+    settings.setProperty("from_string", "3.14159");
+    assertThat(settings.getDouble("from_float")).isEqualTo(3.14159f, Offset.offset(0.00001));
+    assertThat(settings.getDouble("from_string")).isEqualTo(3.14159f, Offset.offset(0.00001));
+    assertThat(settings.getDouble("unknown")).isNull();
+  }
+
+  @Test
+  public void test_get_bad_float() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "bar");
+
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("The property 'foo' is not a float value");
+    settings.getFloat("foo");
+  }
+
+  @Test
+  public void test_get_bad_double() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "bar");
+
+    thrown.expect(IllegalStateException.class);
+    thrown.expectMessage("The property 'foo' is not a double value");
+    settings.getDouble("foo");
+  }
+
+  @Test
+  public void testSetNullFloat() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", (Float) null);
+    assertThat(settings.getFloat("foo")).isNull();
+  }
+
+  @Test
+  public void testSetNullDouble() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", (Double) null);
+    assertThat(settings.getDouble("foo")).isNull();
+  }
+
+  @Test
+  public void getStringArray() {
+    Settings settings = new MapSettings(definitions);
+    String[] array = settings.getStringArray("array");
+    assertThat(array).isEqualTo(new String[] {"one", "two", "three"});
+  }
+
+  @Test
+  public void setStringArray() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("multi_values", new String[] {"A", "B"});
+    String[] array = settings.getStringArray("multi_values");
+    assertThat(array).isEqualTo(new String[] {"A", "B"});
+  }
+
+  @Test
+  public void setStringArrayTrimValues() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("multi_values", new String[] {" A ", " B "});
+    String[] array = settings.getStringArray("multi_values");
+    assertThat(array).isEqualTo(new String[] {"A", "B"});
+  }
+
+  @Test
+  public void setStringArrayEscapeCommas() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("multi_values", new String[] {"A,B", "C,D"});
+    String[] array = settings.getStringArray("multi_values");
+    assertThat(array).isEqualTo(new String[] {"A,B", "C,D"});
+  }
+
+  @Test
+  public void setStringArrayWithEmptyValues() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("multi_values", new String[] {"A,B", "", "C,D"});
+    String[] array = settings.getStringArray("multi_values");
+    assertThat(array).isEqualTo(new String[] {"A,B", "", "C,D"});
+  }
+
+  @Test
+  public void setStringArrayWithNullValues() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("multi_values", new String[] {"A,B", null, "C,D"});
+    String[] array = settings.getStringArray("multi_values");
+    assertThat(array).isEqualTo(new String[] {"A,B", "", "C,D"});
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void shouldFailToSetArrayValueOnSingleValueProperty() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("array", new String[] {"A", "B", "C"});
+  }
+
+  @Test
+  public void getStringArray_no_value() {
+    Settings settings = new MapSettings();
+    String[] array = settings.getStringArray("array");
+    assertThat(array).isEmpty();
+  }
+
+  @Test
+  public void shouldTrimArray() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "  one,  two, three  ");
+    String[] array = settings.getStringArray("foo");
+    assertThat(array).isEqualTo(new String[] {"one", "two", "three"});
+  }
+
+  @Test
+  public void shouldKeepEmptyValuesWhenSplitting() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "  one,  , two");
+    String[] array = settings.getStringArray("foo");
+    assertThat(array).isEqualTo(new String[] {"one", "", "two"});
+  }
+
+  @Test
+  public void testDefaultValueOfGetString() {
+    Settings settings = new MapSettings(definitions);
+    assertThat(settings.getString("hello")).isEqualTo("world");
+  }
+
+  @Test
+  public void set_property_boolean() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", true);
+    settings.setProperty("bar", false);
+    assertThat(settings.getBoolean("foo")).isTrue();
+    assertThat(settings.getBoolean("bar")).isFalse();
+    assertThat(settings.getString("foo")).isEqualTo("true");
+    assertThat(settings.getString("bar")).isEqualTo("false");
+  }
+
+  @Test
+  public void ignore_case_of_boolean_values() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "true");
+    settings.setProperty("bar", "TRUE");
+    // labels in UI
+    settings.setProperty("baz", "True");
+
+    assertThat(settings.getBoolean("foo")).isTrue();
+    assertThat(settings.getBoolean("bar")).isTrue();
+    assertThat(settings.getBoolean("baz")).isTrue();
+  }
+
+  @Test
+  public void get_boolean() {
+    Settings settings = new MapSettings(definitions);
+    assertThat(settings.getBoolean("boolean")).isTrue();
+    assertThat(settings.getBoolean("falseboolean")).isFalse();
+    assertThat(settings.getBoolean("unknown")).isFalse();
+    assertThat(settings.getBoolean("hello")).isFalse();
+  }
+
+  @Test
+  public void shouldCreateByIntrospectingComponent() {
+    Settings settings = new MapSettings();
+    settings.getDefinitions().addComponent(MyComponent.class);
+
+    // property definition has been loaded, ie for default value
+    assertThat(settings.getDefaultValue("foo")).isEqualTo("bar");
+  }
+
+  @Property(key = "foo", name = "Foo", defaultValue = "bar")
+  public static class MyComponent {
+
+  }
+
+  @Test
+  public void getStringLines_no_value() {
+    Assertions.assertThat(new MapSettings().getStringLines("foo")).hasSize(0);
+  }
+
+  @Test
+  public void getStringLines_single_line() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "the line");
+    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"the line"});
+  }
+
+  @Test
+  public void getStringLines_linux() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "one\ntwo");
+    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
+
+    settings.setProperty("foo", "one\ntwo\n");
+    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
+  }
+
+  @Test
+  public void getStringLines_windows() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "one\r\ntwo");
+    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
+
+    settings.setProperty("foo", "one\r\ntwo\r\n");
+    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
+  }
+
+  @Test
+  public void getStringLines_mix() {
+    Settings settings = new MapSettings();
+    settings.setProperty("foo", "one\r\ntwo\nthree");
+    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two", "three"});
+  }
+
+  @Test
+  public void getKeysStartingWith() {
+    Settings settings = new MapSettings();
+    settings.setProperty("sonar.jdbc.url", "foo");
+    settings.setProperty("sonar.jdbc.username", "bar");
+    settings.setProperty("sonar.security", "admin");
+
+    assertThat(settings.getKeysStartingWith("sonar")).containsOnly("sonar.jdbc.url", "sonar.jdbc.username", "sonar.security");
+    assertThat(settings.getKeysStartingWith("sonar.jdbc")).containsOnly("sonar.jdbc.url", "sonar.jdbc.username");
+    assertThat(settings.getKeysStartingWith("other")).hasSize(0);
+  }
+
+  @Test
+  public void should_fallback_deprecated_key_to_default_value_of_new_key() {
+    Settings settings = new MapSettings(definitions);
+
+    assertThat(settings.getString("newKeyWithDefaultValue")).isEqualTo("default_value");
+    assertThat(settings.getString("oldKeyWithDefaultValue")).isEqualTo("default_value");
+  }
+
+  @Test
+  public void should_fallback_deprecated_key_to_new_key() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("newKey", "value of newKey");
+
+    assertThat(settings.getString("newKey")).isEqualTo("value of newKey");
+    assertThat(settings.getString("oldKey")).isEqualTo("value of newKey");
+  }
+
+  @Test
+  public void should_load_value_of_deprecated_key() {
+    // it's used for example when deprecated settings are set through command-line
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("oldKey", "value of oldKey");
+
+    assertThat(settings.getString("newKey")).isEqualTo("value of oldKey");
+    assertThat(settings.getString("oldKey")).isEqualTo("value of oldKey");
+  }
+
+  @Test
+  public void should_load_values_of_deprecated_key() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("oldKey", "a,b");
+
+    assertThat(settings.getStringArray("newKey")).containsOnly("a", "b");
+    assertThat(settings.getStringArray("oldKey")).containsOnly("a", "b");
+  }
+
+  @Test
+  public void should_support_deprecated_props_with_multi_values() {
+    Settings settings = new MapSettings(definitions);
+    settings.setProperty("new_multi_values", new String[] {" A ", " B "});
+    assertThat(settings.getStringArray("new_multi_values")).isEqualTo(new String[] {"A", "B"});
+    assertThat(settings.getStringArray("old_multi_values")).isEqualTo(new String[] {"A", "B"});
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/config/internal/MultivaluePropertyTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/config/internal/MultivaluePropertyTest.java
new file mode 100644 (file)
index 0000000..bd50d94
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.config.internal;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Random;
+import java.util.function.Function;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
+import static org.sonar.api.config.internal.MultivalueProperty.trimFieldsAndRemoveEmptyFields;
+
+@RunWith(DataProviderRunner.class)
+public class MultivaluePropertyTest {
+  private static final String[] EMPTY_STRING_ARRAY = {};
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  @UseDataProvider("testParseAsCsv")
+  public void parseAsCsv_for_coverage(String value, String[] expected) {
+    // parseAsCsv is extensively tested in org.sonar.server.config.ConfigurationProviderTest
+    assertThat(parseAsCsv("key", value))
+      .isEqualTo(parseAsCsv("key", value, Function.identity()))
+      .isEqualTo(expected);
+  }
+
+  @Test
+  public void parseAsCsv_fails_with_ISE_if_value_can_not_be_parsed() {
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Property: 'multi' doesn't contain a valid CSV value: '\"a ,b'");
+
+    parseAsCsv("multi", "\"a ,b");
+  }
+
+  @DataProvider
+  public static Object[][] testParseAsCsv() {
+    return new Object[][] {
+      {"a", arrayOf("a")},
+      {" a", arrayOf("a")},
+      {"a ", arrayOf("a")},
+      {" a, b", arrayOf("a", "b")},
+      {"a,b ", arrayOf("a", "b")},
+      {"a,,,b,c,,d", arrayOf("a", "b", "c", "d")},
+      {" , \n ,, \t", EMPTY_STRING_ARRAY},
+      {"\" a\"", arrayOf(" a")},
+      {"\",\"", arrayOf(",")},
+      // escaped quote in quoted field
+      {"\"\"\"\"", arrayOf("\"")}
+    };
+  }
+
+  private static String[] arrayOf(String... strs) {
+    return strs;
+  }
+
+  @Test
+  public void trimFieldsAndRemoveEmptyFields_throws_NPE_if_arg_is_null() {
+    expectedException.expect(NullPointerException.class);
+
+    trimFieldsAndRemoveEmptyFields(null);
+  }
+
+  @Test
+  @UseDataProvider("plains")
+  public void trimFieldsAndRemoveEmptyFields_ignores_EmptyFields(String str) {
+    assertThat(trimFieldsAndRemoveEmptyFields("")).isEqualTo("");
+    assertThat(trimFieldsAndRemoveEmptyFields(str)).isEqualTo(str);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(',' + str)).isEqualTo(str);
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ',')).isEqualTo(str);
+    assertThat(trimFieldsAndRemoveEmptyFields(",,," + str)).isEqualTo(str);
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,,")).isEqualTo(str);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str)).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,," + str)).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ',' + str)).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields("," + str + ",,," + str)).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(",,," + str + ",,," + str)).isEqualTo(str + ',' + str);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str + ',')).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,," + str + ",")).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,," + str + ",,")).isEqualTo(str + ',' + str);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ',' + str + ',')).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(",," + str + ',' + str + ',')).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ",," + str + ',')).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ',' + str + ",,")).isEqualTo(str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(",,," + str + ",,," + str + ",,")).isEqualTo(str + ',' + str);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str + ',' + str)).isEqualTo(str + ',' + str + ',' + str);
+    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str + ',' + str)).isEqualTo(str + ',' + str + ',' + str);
+  }
+
+  @DataProvider
+  public static Object[][] plains() {
+    return new Object[][] {
+      {randomAlphanumeric(1)},
+      {randomAlphanumeric(2)},
+      {randomAlphanumeric(3 + new Random().nextInt(5))}
+    };
+  }
+
+  @Test
+  @UseDataProvider("emptyAndtrimmable")
+  public void trimFieldsAndRemoveEmptyFields_ignores_empty_fields_and_trims_fields(String empty, String trimmable) {
+    String expected = trimmable.trim();
+    assertThat(empty.trim()).isEmpty();
+
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + empty)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ",," + empty)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(empty + ',' + trimmable)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(empty + ",," + trimmable)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(empty + ',' + trimmable + ',' + empty)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(empty + ",," + trimmable + ",,," + empty)).isEqualTo(expected);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + empty + ',' + empty)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ",," + empty + ",,," + empty)).isEqualTo(expected);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(empty + ',' + empty + ',' + trimmable)).isEqualTo(expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(empty + ",,,," + empty + ",," + trimmable)).isEqualTo(expected);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + trimmable)).isEqualTo(expected + ',' + expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + trimmable + ',' + trimmable)).isEqualTo(expected + ',' + expected + ',' + expected);
+    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + "," + trimmable + ',' + trimmable)).isEqualTo(expected + ',' + expected + ',' + expected);
+  }
+
+  @Test
+  public void trimAccordingToStringTrim() {
+    String str = randomAlphanumeric(4);
+    for (int i = 0; i <= ' '; i++) {
+      String prefixed = (char) i + str;
+      String suffixed = (char) i + str;
+      String both = (char) i + str + (char) i;
+      assertThat(trimFieldsAndRemoveEmptyFields(prefixed)).isEqualTo(prefixed.trim());
+      assertThat(trimFieldsAndRemoveEmptyFields(suffixed)).isEqualTo(suffixed.trim());
+      assertThat(trimFieldsAndRemoveEmptyFields(both)).isEqualTo(both.trim());
+    }
+  }
+
+  @DataProvider
+  public static Object[][] emptyAndtrimmable() {
+    Random random = new Random();
+    String oneEmpty = randomTrimmedChars(1, random);
+    String twoEmpty = randomTrimmedChars(2, random);
+    String threePlusEmpty = randomTrimmedChars(3 + random.nextInt(5), random);
+    String onePlusEmpty = randomTrimmedChars(1 + random.nextInt(5), random);
+
+    String plain = randomAlphanumeric(1);
+    String plainWithtrimmable = randomAlphanumeric(2) + onePlusEmpty + randomAlphanumeric(3);
+    String quotedWithSeparator = '"' + randomAlphanumeric(3) + ',' + randomAlphanumeric(2) + '"';
+    String quotedWithDoubleSeparator = '"' + randomAlphanumeric(3) + ",," + randomAlphanumeric(2) + '"';
+    String quotedWithtrimmable = '"' + randomAlphanumeric(3) + onePlusEmpty + randomAlphanumeric(2) + '"';
+
+    String[] empties = {oneEmpty, twoEmpty, threePlusEmpty};
+    String[] strings = {plain, plainWithtrimmable,
+      onePlusEmpty + plain, plain + onePlusEmpty, onePlusEmpty + plain + onePlusEmpty,
+      onePlusEmpty + plainWithtrimmable, plainWithtrimmable + onePlusEmpty, onePlusEmpty + plainWithtrimmable + onePlusEmpty,
+      onePlusEmpty + quotedWithSeparator, quotedWithSeparator + onePlusEmpty, onePlusEmpty + quotedWithSeparator + onePlusEmpty,
+      onePlusEmpty + quotedWithDoubleSeparator, quotedWithDoubleSeparator + onePlusEmpty, onePlusEmpty + quotedWithDoubleSeparator + onePlusEmpty,
+      onePlusEmpty + quotedWithtrimmable, quotedWithtrimmable + onePlusEmpty, onePlusEmpty + quotedWithtrimmable + onePlusEmpty
+    };
+
+    Object[][] res = new Object[empties.length * strings.length][2];
+    int i = 0;
+    for (String empty : empties) {
+      for (String string : strings) {
+        res[i][0] = empty;
+        res[i][1] = string;
+        i++;
+      }
+    }
+    return res;
+  }
+
+  @Test
+  @UseDataProvider("emptys")
+  public void trimFieldsAndRemoveEmptyFields_quotes_allow_to_preserve_fields(String empty) {
+    String quotedEmpty = '"' + empty + '"';
+
+    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty)).isEqualTo(quotedEmpty);
+    assertThat(trimFieldsAndRemoveEmptyFields(',' + quotedEmpty)).isEqualTo(quotedEmpty);
+    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ',')).isEqualTo(quotedEmpty);
+    assertThat(trimFieldsAndRemoveEmptyFields(',' + quotedEmpty + ',')).isEqualTo(quotedEmpty);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ',' + quotedEmpty)).isEqualTo(quotedEmpty + ',' + quotedEmpty);
+    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ",," + quotedEmpty)).isEqualTo(quotedEmpty + ',' + quotedEmpty);
+
+    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ',' + quotedEmpty + ',' + quotedEmpty)).isEqualTo(quotedEmpty + ',' + quotedEmpty + ',' + quotedEmpty);
+  }
+
+  @DataProvider
+  public static Object[][] emptys() {
+    Random random = new Random();
+    return new Object[][] {
+      {randomTrimmedChars(1, random)},
+      {randomTrimmedChars(2, random)},
+      {randomTrimmedChars(3 + random.nextInt(5), random)}
+    };
+  }
+
+  @Test
+  public void trimFieldsAndRemoveEmptyFields_supports_escaped_quote_in_quotes() {
+    assertThat(trimFieldsAndRemoveEmptyFields("\"f\"\"oo\"")).isEqualTo("\"f\"\"oo\"");
+    assertThat(trimFieldsAndRemoveEmptyFields("\"f\"\"oo\",\"bar\"\"\"")).isEqualTo("\"f\"\"oo\",\"bar\"\"\"");
+  }
+
+  @Test
+  public void trimFieldsAndRemoveEmptyFields_does_not_fail_on_unbalanced_quotes() {
+    assertThat(trimFieldsAndRemoveEmptyFields("\"")).isEqualTo("\"");
+    assertThat(trimFieldsAndRemoveEmptyFields("\"foo")).isEqualTo("\"foo");
+    assertThat(trimFieldsAndRemoveEmptyFields("foo\"")).isEqualTo("foo\"");
+
+    assertThat(trimFieldsAndRemoveEmptyFields("\"foo\",\"")).isEqualTo("\"foo\",\"");
+    assertThat(trimFieldsAndRemoveEmptyFields("\",\"foo\"")).isEqualTo("\",\"foo\"");
+
+    assertThat(trimFieldsAndRemoveEmptyFields("\"foo\",\",  ")).isEqualTo("\"foo\",\",  ");
+
+    assertThat(trimFieldsAndRemoveEmptyFields(" a ,,b , c,  \"foo\",\"  ")).isEqualTo("a,b,c,\"foo\",\"  ");
+    assertThat(trimFieldsAndRemoveEmptyFields("\" a ,,b , c,  ")).isEqualTo("\" a ,,b , c,  ");
+  }
+
+  private static final char[] SOME_PRINTABLE_TRIMMABLE_CHARS = {
+    ' ', '\t', '\n', '\r'
+  };
+
+  /**
+   * Result of randomTrimmedChars being used as arguments to JUnit test method through the DataProvider feature, they
+   * are printed to surefire report. Some of those chars breaks the parsing of the surefire report during sonar analysis.
+   * Therefor, we only use a subset of the trimmable chars.
+   */
+  private static String randomTrimmedChars(int length, Random random) {
+    char[] chars = new char[length];
+    for (int i = 0; i < chars.length; i++) {
+      chars[i] = SOME_PRINTABLE_TRIMMABLE_CHARS[random.nextInt(SOME_PRINTABLE_TRIMMABLE_CHARS.length)];
+    }
+    return new String(chars);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MapSettingsTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MapSettingsTest.java
deleted file mode 100644 (file)
index 922d767..0000000
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.config;
-
-import com.tngtech.java.junit.dataprovider.DataProvider;
-import com.tngtech.java.junit.dataprovider.DataProviderRunner;
-import com.tngtech.java.junit.dataprovider.UseDataProvider;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import java.util.function.BiConsumer;
-import java.util.stream.IntStream;
-import org.assertj.core.data.Offset;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.sonar.api.Properties;
-import org.sonar.api.Property;
-import org.sonar.api.PropertyType;
-import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.utils.DateUtils;
-
-import static java.util.Collections.singletonList;
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
-import static org.assertj.core.api.Assertions.assertThat;
-
-@RunWith(DataProviderRunner.class)
-public class MapSettingsTest {
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  private PropertyDefinitions definitions;
-
-  @Properties({
-    @Property(key = "hello", name = "Hello", defaultValue = "world"),
-    @Property(key = "date", name = "Date", defaultValue = "2010-05-18"),
-    @Property(key = "datetime", name = "DateTime", defaultValue = "2010-05-18T15:50:45+0100"),
-    @Property(key = "boolean", name = "Boolean", defaultValue = "true"),
-    @Property(key = "falseboolean", name = "False Boolean", defaultValue = "false"),
-    @Property(key = "integer", name = "Integer", defaultValue = "12345"),
-    @Property(key = "array", name = "Array", defaultValue = "one,two,three"),
-    @Property(key = "multi_values", name = "Array", defaultValue = "1,2,3", multiValues = true),
-    @Property(key = "sonar.jira", name = "Jira Server", type = PropertyType.PROPERTY_SET, propertySetKey = "jira"),
-    @Property(key = "newKey", name = "New key", deprecatedKey = "oldKey"),
-    @Property(key = "newKeyWithDefaultValue", name = "New key with default value", deprecatedKey = "oldKeyWithDefaultValue", defaultValue = "default_value"),
-    @Property(key = "new_multi_values", name = "New multi values", defaultValue = "1,2,3", multiValues = true, deprecatedKey = "old_multi_values")
-  })
-  private static class Init {
-  }
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Before
-  public void init_definitions() {
-    definitions = new PropertyDefinitions();
-    definitions.addComponent(Init.class);
-  }
-
-  @Test
-  public void set_throws_NPE_if_key_is_null() {
-    org.sonar.api.impl.config.MapSettings underTest = new org.sonar.api.impl.config.MapSettings();
-
-    expectKeyNullNPE();
-
-    underTest.set(null, randomAlphanumeric(3));
-  }
-
-  @Test
-  public void set_throws_NPE_if_value_is_null() {
-    org.sonar.api.impl.config.MapSettings underTest = new org.sonar.api.impl.config.MapSettings();
-
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("value can't be null");
-
-    underTest.set(randomAlphanumeric(3), null);
-  }
-
-  @Test
-  public void set_accepts_empty_value_and_trims_it() {
-    org.sonar.api.impl.config.MapSettings underTest = new org.sonar.api.impl.config.MapSettings();
-    Random random = new Random();
-    String key = randomAlphanumeric(3);
-
-    underTest.set(key, blank(random));
-
-    assertThat(underTest.getString(key)).isEmpty();
-  }
-
-  @Test
-  public void default_values_should_be_loaded_from_definitions() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    assertThat(settings.getDefaultValue("hello")).isEqualTo("world");
-  }
-
-  @Test
-  @UseDataProvider("setPropertyCalls")
-  public void all_setProperty_methods_throws_NPE_if_key_is_null(BiConsumer<Settings, String> setPropertyCaller) {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-
-    expectKeyNullNPE();
-
-    setPropertyCaller.accept(settings, null);
-  }
-
-  @Test
-  public void set_property_string_throws_NPE_if_key_is_null() {
-    String key = randomAlphanumeric(3);
-
-    Settings underTest = new org.sonar.api.impl.config.MapSettings(new PropertyDefinitions(singletonList(PropertyDefinition.builder(key).multiValues(true).build())));
-
-    expectKeyNullNPE();
-
-    underTest.setProperty(null, new String[] {"1", "2"});
-  }
-
-  private void expectKeyNullNPE() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("key can't be null");
-  }
-
-  @Test
-  @UseDataProvider("setPropertyCalls")
-  public void all_set_property_methods_trims_key(BiConsumer<Settings, String> setPropertyCaller) {
-    Settings underTest = new org.sonar.api.impl.config.MapSettings();
-
-    Random random = new Random();
-    String blankBefore = blank(random);
-    String blankAfter = blank(random);
-    String key = randomAlphanumeric(3);
-
-    setPropertyCaller.accept(underTest, blankBefore + key + blankAfter);
-
-    assertThat(underTest.hasKey(key)).isTrue();
-  }
-
-  @Test
-  public void set_property_string_array_trims_key() {
-    String key = randomAlphanumeric(3);
-
-    Settings underTest = new org.sonar.api.impl.config.MapSettings(new PropertyDefinitions(singletonList(PropertyDefinition.builder(key).multiValues(true).build())));
-
-    Random random = new Random();
-    String blankBefore = blank(random);
-    String blankAfter = blank(random);
-
-    underTest.setProperty(blankBefore + key + blankAfter, new String[] {"1", "2"});
-
-    assertThat(underTest.hasKey(key)).isTrue();
-  }
-
-  private static String blank(Random random) {
-    StringBuilder b = new StringBuilder();
-    IntStream.range(0, random.nextInt(3)).mapToObj(s -> " ").forEach(b::append);
-    return b.toString();
-  }
-
-  @DataProvider
-  public static Object[][] setPropertyCalls() {
-    List<BiConsumer<Settings, String>> callers = Arrays.asList(
-      (settings, key) -> settings.setProperty(key, 123),
-      (settings, key) -> settings.setProperty(key, 123L),
-      (settings, key) -> settings.setProperty(key, 123.2F),
-      (settings, key) -> settings.setProperty(key, 123.2D),
-      (settings, key) -> settings.setProperty(key, false),
-      (settings, key) -> settings.setProperty(key, new Date()),
-      (settings, key) -> settings.setProperty(key, new Date(), true));
-
-    return callers.stream().map(t -> new Object[] {t}).toArray(Object[][]::new);
-  }
-
-  @Test
-  public void setProperty_methods_trims_value() {
-    Settings underTest = new org.sonar.api.impl.config.MapSettings();
-
-    Random random = new Random();
-    String blankBefore = blank(random);
-    String blankAfter = blank(random);
-    String key = randomAlphanumeric(3);
-    String value = randomAlphanumeric(3);
-
-    underTest.setProperty(key, blankBefore + value + blankAfter);
-
-    assertThat(underTest.getString(key)).isEqualTo(value);
-  }
-
-  @Test
-  public void set_property_int() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", 123);
-    assertThat(settings.getInt("foo")).isEqualTo(123);
-    assertThat(settings.getString("foo")).isEqualTo("123");
-    assertThat(settings.getBoolean("foo")).isFalse();
-  }
-
-  @Test
-  public void default_number_values_are_zero() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    assertThat(settings.getInt("foo")).isEqualTo(0);
-    assertThat(settings.getLong("foo")).isEqualTo(0L);
-  }
-
-  @Test
-  public void getInt_value_must_be_valid() {
-    thrown.expect(NumberFormatException.class);
-
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "not a number");
-    settings.getInt("foo");
-  }
-
-  @Test
-  public void all_values_should_be_trimmed_set_property() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "   FOO ");
-    assertThat(settings.getString("foo")).isEqualTo("FOO");
-  }
-
-  @Test
-  public void test_get_default_value() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    assertThat(settings.getDefaultValue("unknown")).isNull();
-  }
-
-  @Test
-  public void test_get_string() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("hello", "Russia");
-    assertThat(settings.getString("hello")).isEqualTo("Russia");
-  }
-
-  @Test
-  public void setProperty_date() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    Date date = DateUtils.parseDateTime("2010-05-18T15:50:45+0100");
-    settings.setProperty("aDate", date);
-    settings.setProperty("aDateTime", date, true);
-
-    assertThat(settings.getString("aDate")).isEqualTo("2010-05-18");
-    assertThat(settings.getString("aDateTime")).startsWith("2010-05-18T");
-  }
-
-  @Test
-  public void test_get_date() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    assertThat(settings.getDate("unknown")).isNull();
-    assertThat(settings.getDate("date").getDate()).isEqualTo(18);
-    assertThat(settings.getDate("date").getMonth()).isEqualTo(4);
-  }
-
-  @Test
-  public void test_get_date_not_found() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    assertThat(settings.getDate("unknown")).isNull();
-  }
-
-  @Test
-  public void test_get_datetime() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    assertThat(settings.getDateTime("unknown")).isNull();
-    assertThat(settings.getDateTime("datetime").getDate()).isEqualTo(18);
-    assertThat(settings.getDateTime("datetime").getMonth()).isEqualTo(4);
-    assertThat(settings.getDateTime("datetime").getMinutes()).isEqualTo(50);
-  }
-
-  @Test
-  public void test_get_double() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("from_double", 3.14159);
-    settings.setProperty("from_string", "3.14159");
-    assertThat(settings.getDouble("from_double")).isEqualTo(3.14159, Offset.offset(0.00001));
-    assertThat(settings.getDouble("from_string")).isEqualTo(3.14159, Offset.offset(0.00001));
-    assertThat(settings.getDouble("unknown")).isNull();
-  }
-
-  @Test
-  public void test_get_float() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("from_float", 3.14159f);
-    settings.setProperty("from_string", "3.14159");
-    assertThat(settings.getDouble("from_float")).isEqualTo(3.14159f, Offset.offset(0.00001));
-    assertThat(settings.getDouble("from_string")).isEqualTo(3.14159f, Offset.offset(0.00001));
-    assertThat(settings.getDouble("unknown")).isNull();
-  }
-
-  @Test
-  public void test_get_bad_float() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "bar");
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("The property 'foo' is not a float value");
-    settings.getFloat("foo");
-  }
-
-  @Test
-  public void test_get_bad_double() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "bar");
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("The property 'foo' is not a double value");
-    settings.getDouble("foo");
-  }
-
-  @Test
-  public void testSetNullFloat() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", (Float) null);
-    assertThat(settings.getFloat("foo")).isNull();
-  }
-
-  @Test
-  public void testSetNullDouble() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", (Double) null);
-    assertThat(settings.getDouble("foo")).isNull();
-  }
-
-  @Test
-  public void getStringArray() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    String[] array = settings.getStringArray("array");
-    assertThat(array).isEqualTo(new String[] {"one", "two", "three"});
-  }
-
-  @Test
-  public void setStringArray() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("multi_values", new String[] {"A", "B"});
-    String[] array = settings.getStringArray("multi_values");
-    assertThat(array).isEqualTo(new String[] {"A", "B"});
-  }
-
-  @Test
-  public void setStringArrayTrimValues() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("multi_values", new String[] {" A ", " B "});
-    String[] array = settings.getStringArray("multi_values");
-    assertThat(array).isEqualTo(new String[] {"A", "B"});
-  }
-
-  @Test
-  public void setStringArrayEscapeCommas() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("multi_values", new String[] {"A,B", "C,D"});
-    String[] array = settings.getStringArray("multi_values");
-    assertThat(array).isEqualTo(new String[] {"A,B", "C,D"});
-  }
-
-  @Test
-  public void setStringArrayWithEmptyValues() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("multi_values", new String[] {"A,B", "", "C,D"});
-    String[] array = settings.getStringArray("multi_values");
-    assertThat(array).isEqualTo(new String[] {"A,B", "", "C,D"});
-  }
-
-  @Test
-  public void setStringArrayWithNullValues() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("multi_values", new String[] {"A,B", null, "C,D"});
-    String[] array = settings.getStringArray("multi_values");
-    assertThat(array).isEqualTo(new String[] {"A,B", "", "C,D"});
-  }
-
-  @Test(expected = IllegalStateException.class)
-  public void shouldFailToSetArrayValueOnSingleValueProperty() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("array", new String[] {"A", "B", "C"});
-  }
-
-  @Test
-  public void getStringArray_no_value() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    String[] array = settings.getStringArray("array");
-    assertThat(array).isEmpty();
-  }
-
-  @Test
-  public void shouldTrimArray() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "  one,  two, three  ");
-    String[] array = settings.getStringArray("foo");
-    assertThat(array).isEqualTo(new String[] {"one", "two", "three"});
-  }
-
-  @Test
-  public void shouldKeepEmptyValuesWhenSplitting() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "  one,  , two");
-    String[] array = settings.getStringArray("foo");
-    assertThat(array).isEqualTo(new String[] {"one", "", "two"});
-  }
-
-  @Test
-  public void testDefaultValueOfGetString() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    assertThat(settings.getString("hello")).isEqualTo("world");
-  }
-
-  @Test
-  public void set_property_boolean() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", true);
-    settings.setProperty("bar", false);
-    assertThat(settings.getBoolean("foo")).isTrue();
-    assertThat(settings.getBoolean("bar")).isFalse();
-    assertThat(settings.getString("foo")).isEqualTo("true");
-    assertThat(settings.getString("bar")).isEqualTo("false");
-  }
-
-  @Test
-  public void ignore_case_of_boolean_values() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "true");
-    settings.setProperty("bar", "TRUE");
-    // labels in UI
-    settings.setProperty("baz", "True");
-
-    assertThat(settings.getBoolean("foo")).isTrue();
-    assertThat(settings.getBoolean("bar")).isTrue();
-    assertThat(settings.getBoolean("baz")).isTrue();
-  }
-
-  @Test
-  public void get_boolean() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    assertThat(settings.getBoolean("boolean")).isTrue();
-    assertThat(settings.getBoolean("falseboolean")).isFalse();
-    assertThat(settings.getBoolean("unknown")).isFalse();
-    assertThat(settings.getBoolean("hello")).isFalse();
-  }
-
-  @Test
-  public void shouldCreateByIntrospectingComponent() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.getDefinitions().addComponent(MyComponent.class);
-
-    // property definition has been loaded, ie for default value
-    assertThat(settings.getDefaultValue("foo")).isEqualTo("bar");
-  }
-
-  @Property(key = "foo", name = "Foo", defaultValue = "bar")
-  public static class MyComponent {
-
-  }
-
-  @Test
-  public void getStringLines_no_value() {
-    assertThat(new org.sonar.api.impl.config.MapSettings().getStringLines("foo")).hasSize(0);
-  }
-
-  @Test
-  public void getStringLines_single_line() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "the line");
-    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"the line"});
-  }
-
-  @Test
-  public void getStringLines_linux() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "one\ntwo");
-    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
-
-    settings.setProperty("foo", "one\ntwo\n");
-    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
-  }
-
-  @Test
-  public void getStringLines_windows() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "one\r\ntwo");
-    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
-
-    settings.setProperty("foo", "one\r\ntwo\r\n");
-    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two"});
-  }
-
-  @Test
-  public void getStringLines_mix() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("foo", "one\r\ntwo\nthree");
-    assertThat(settings.getStringLines("foo")).isEqualTo(new String[] {"one", "two", "three"});
-  }
-
-  @Test
-  public void getKeysStartingWith() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings();
-    settings.setProperty("sonar.jdbc.url", "foo");
-    settings.setProperty("sonar.jdbc.username", "bar");
-    settings.setProperty("sonar.security", "admin");
-
-    assertThat(settings.getKeysStartingWith("sonar")).containsOnly("sonar.jdbc.url", "sonar.jdbc.username", "sonar.security");
-    assertThat(settings.getKeysStartingWith("sonar.jdbc")).containsOnly("sonar.jdbc.url", "sonar.jdbc.username");
-    assertThat(settings.getKeysStartingWith("other")).hasSize(0);
-  }
-
-  @Test
-  public void should_fallback_deprecated_key_to_default_value_of_new_key() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-
-    assertThat(settings.getString("newKeyWithDefaultValue")).isEqualTo("default_value");
-    assertThat(settings.getString("oldKeyWithDefaultValue")).isEqualTo("default_value");
-  }
-
-  @Test
-  public void should_fallback_deprecated_key_to_new_key() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("newKey", "value of newKey");
-
-    assertThat(settings.getString("newKey")).isEqualTo("value of newKey");
-    assertThat(settings.getString("oldKey")).isEqualTo("value of newKey");
-  }
-
-  @Test
-  public void should_load_value_of_deprecated_key() {
-    // it's used for example when deprecated settings are set through command-line
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("oldKey", "value of oldKey");
-
-    assertThat(settings.getString("newKey")).isEqualTo("value of oldKey");
-    assertThat(settings.getString("oldKey")).isEqualTo("value of oldKey");
-  }
-
-  @Test
-  public void should_load_values_of_deprecated_key() {
-    Settings settings = new org.sonar.api.impl.config.MapSettings(definitions);
-    settings.setProperty("oldKey", "a,b");
-
-    assertThat(settings.getStringArray("newKey")).containsOnly("a", "b");
-    assertThat(settings.getStringArray("oldKey")).containsOnly("a", "b");
-  }
-
-  @Test
-  public void should_support_deprecated_props_with_multi_values() {
-    Settings settings = new MapSettings(definitions);
-    settings.setProperty("new_multi_values", new String[] {" A ", " B "});
-    assertThat(settings.getStringArray("new_multi_values")).isEqualTo(new String[] {"A", "B"});
-    assertThat(settings.getStringArray("old_multi_values")).isEqualTo(new String[] {"A", "B"});
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MultivaluePropertyTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MultivaluePropertyTest.java
deleted file mode 100644 (file)
index 63e3c44..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.config;
-
-import com.tngtech.java.junit.dataprovider.DataProvider;
-import com.tngtech.java.junit.dataprovider.DataProviderRunner;
-import com.tngtech.java.junit.dataprovider.UseDataProvider;
-import java.util.Random;
-import java.util.function.Function;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
-import static org.sonar.api.impl.config.MultivalueProperty.trimFieldsAndRemoveEmptyFields;
-
-@RunWith(DataProviderRunner.class)
-public class MultivaluePropertyTest {
-  private static final String[] EMPTY_STRING_ARRAY = {};
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  @UseDataProvider("testParseAsCsv")
-  public void parseAsCsv_for_coverage(String value, String[] expected) {
-    // parseAsCsv is extensively tested in org.sonar.server.config.ConfigurationProviderTest
-    assertThat(parseAsCsv("key", value))
-      .isEqualTo(parseAsCsv("key", value, Function.identity()))
-      .isEqualTo(expected);
-  }
-
-  @Test
-  public void parseAsCsv_fails_with_ISE_if_value_can_not_be_parsed() {
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Property: 'multi' doesn't contain a valid CSV value: '\"a ,b'");
-
-    parseAsCsv("multi", "\"a ,b");
-  }
-
-  @DataProvider
-  public static Object[][] testParseAsCsv() {
-    return new Object[][] {
-      {"a", arrayOf("a")},
-      {" a", arrayOf("a")},
-      {"a ", arrayOf("a")},
-      {" a, b", arrayOf("a", "b")},
-      {"a,b ", arrayOf("a", "b")},
-      {"a,,,b,c,,d", arrayOf("a", "b", "c", "d")},
-      {" , \n ,, \t", EMPTY_STRING_ARRAY},
-      {"\" a\"", arrayOf(" a")},
-      {"\",\"", arrayOf(",")},
-      // escaped quote in quoted field
-      {"\"\"\"\"", arrayOf("\"")}
-    };
-  }
-
-  private static String[] arrayOf(String... strs) {
-    return strs;
-  }
-
-  @Test
-  public void trimFieldsAndRemoveEmptyFields_throws_NPE_if_arg_is_null() {
-    expectedException.expect(NullPointerException.class);
-
-    trimFieldsAndRemoveEmptyFields(null);
-  }
-
-  @Test
-  @UseDataProvider("plains")
-  public void trimFieldsAndRemoveEmptyFields_ignores_EmptyFields(String str) {
-    assertThat(trimFieldsAndRemoveEmptyFields("")).isEqualTo("");
-    assertThat(trimFieldsAndRemoveEmptyFields(str)).isEqualTo(str);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(',' + str)).isEqualTo(str);
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ',')).isEqualTo(str);
-    assertThat(trimFieldsAndRemoveEmptyFields(",,," + str)).isEqualTo(str);
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,,")).isEqualTo(str);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str)).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,," + str)).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ',' + str)).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields("," + str + ",,," + str)).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(",,," + str + ",,," + str)).isEqualTo(str + ',' + str);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str + ',')).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,," + str + ",")).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ",,," + str + ",,")).isEqualTo(str + ',' + str);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ',' + str + ',')).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(",," + str + ',' + str + ',')).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ",," + str + ',')).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(',' + str + ',' + str + ",,")).isEqualTo(str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(",,," + str + ",,," + str + ",,")).isEqualTo(str + ',' + str);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str + ',' + str)).isEqualTo(str + ',' + str + ',' + str);
-    assertThat(trimFieldsAndRemoveEmptyFields(str + ',' + str + ',' + str)).isEqualTo(str + ',' + str + ',' + str);
-  }
-
-  @DataProvider
-  public static Object[][] plains() {
-    return new Object[][] {
-      {randomAlphanumeric(1)},
-      {randomAlphanumeric(2)},
-      {randomAlphanumeric(3 + new Random().nextInt(5))}
-    };
-  }
-
-  @Test
-  @UseDataProvider("emptyAndtrimmable")
-  public void trimFieldsAndRemoveEmptyFields_ignores_empty_fields_and_trims_fields(String empty, String trimmable) {
-    String expected = trimmable.trim();
-    assertThat(empty.trim()).isEmpty();
-
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + empty)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ",," + empty)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(empty + ',' + trimmable)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(empty + ",," + trimmable)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(empty + ',' + trimmable + ',' + empty)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(empty + ",," + trimmable + ",,," + empty)).isEqualTo(expected);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + empty + ',' + empty)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ",," + empty + ",,," + empty)).isEqualTo(expected);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(empty + ',' + empty + ',' + trimmable)).isEqualTo(expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(empty + ",,,," + empty + ",," + trimmable)).isEqualTo(expected);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + trimmable)).isEqualTo(expected + ',' + expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + ',' + trimmable + ',' + trimmable)).isEqualTo(expected + ',' + expected + ',' + expected);
-    assertThat(trimFieldsAndRemoveEmptyFields(trimmable + "," + trimmable + ',' + trimmable)).isEqualTo(expected + ',' + expected + ',' + expected);
-  }
-
-  @Test
-  public void trimAccordingToStringTrim() {
-    String str = randomAlphanumeric(4);
-    for (int i = 0; i <= ' '; i++) {
-      String prefixed = (char) i + str;
-      String suffixed = (char) i + str;
-      String both = (char) i + str + (char) i;
-      assertThat(trimFieldsAndRemoveEmptyFields(prefixed)).isEqualTo(prefixed.trim());
-      assertThat(trimFieldsAndRemoveEmptyFields(suffixed)).isEqualTo(suffixed.trim());
-      assertThat(trimFieldsAndRemoveEmptyFields(both)).isEqualTo(both.trim());
-    }
-  }
-
-  @DataProvider
-  public static Object[][] emptyAndtrimmable() {
-    Random random = new Random();
-    String oneEmpty = randomTrimmedChars(1, random);
-    String twoEmpty = randomTrimmedChars(2, random);
-    String threePlusEmpty = randomTrimmedChars(3 + random.nextInt(5), random);
-    String onePlusEmpty = randomTrimmedChars(1 + random.nextInt(5), random);
-
-    String plain = randomAlphanumeric(1);
-    String plainWithtrimmable = randomAlphanumeric(2) + onePlusEmpty + randomAlphanumeric(3);
-    String quotedWithSeparator = '"' + randomAlphanumeric(3) + ',' + randomAlphanumeric(2) + '"';
-    String quotedWithDoubleSeparator = '"' + randomAlphanumeric(3) + ",," + randomAlphanumeric(2) + '"';
-    String quotedWithtrimmable = '"' + randomAlphanumeric(3) + onePlusEmpty + randomAlphanumeric(2) + '"';
-
-    String[] empties = {oneEmpty, twoEmpty, threePlusEmpty};
-    String[] strings = {plain, plainWithtrimmable,
-      onePlusEmpty + plain, plain + onePlusEmpty, onePlusEmpty + plain + onePlusEmpty,
-      onePlusEmpty + plainWithtrimmable, plainWithtrimmable + onePlusEmpty, onePlusEmpty + plainWithtrimmable + onePlusEmpty,
-      onePlusEmpty + quotedWithSeparator, quotedWithSeparator + onePlusEmpty, onePlusEmpty + quotedWithSeparator + onePlusEmpty,
-      onePlusEmpty + quotedWithDoubleSeparator, quotedWithDoubleSeparator + onePlusEmpty, onePlusEmpty + quotedWithDoubleSeparator + onePlusEmpty,
-      onePlusEmpty + quotedWithtrimmable, quotedWithtrimmable + onePlusEmpty, onePlusEmpty + quotedWithtrimmable + onePlusEmpty
-    };
-
-    Object[][] res = new Object[empties.length * strings.length][2];
-    int i = 0;
-    for (String empty : empties) {
-      for (String string : strings) {
-        res[i][0] = empty;
-        res[i][1] = string;
-        i++;
-      }
-    }
-    return res;
-  }
-
-  @Test
-  @UseDataProvider("emptys")
-  public void trimFieldsAndRemoveEmptyFields_quotes_allow_to_preserve_fields(String empty) {
-    String quotedEmpty = '"' + empty + '"';
-
-    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty)).isEqualTo(quotedEmpty);
-    assertThat(trimFieldsAndRemoveEmptyFields(',' + quotedEmpty)).isEqualTo(quotedEmpty);
-    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ',')).isEqualTo(quotedEmpty);
-    assertThat(trimFieldsAndRemoveEmptyFields(',' + quotedEmpty + ',')).isEqualTo(quotedEmpty);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ',' + quotedEmpty)).isEqualTo(quotedEmpty + ',' + quotedEmpty);
-    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ",," + quotedEmpty)).isEqualTo(quotedEmpty + ',' + quotedEmpty);
-
-    assertThat(trimFieldsAndRemoveEmptyFields(quotedEmpty + ',' + quotedEmpty + ',' + quotedEmpty)).isEqualTo(quotedEmpty + ',' + quotedEmpty + ',' + quotedEmpty);
-  }
-
-  @DataProvider
-  public static Object[][] emptys() {
-    Random random = new Random();
-    return new Object[][] {
-      {randomTrimmedChars(1, random)},
-      {randomTrimmedChars(2, random)},
-      {randomTrimmedChars(3 + random.nextInt(5), random)}
-    };
-  }
-
-  @Test
-  public void trimFieldsAndRemoveEmptyFields_supports_escaped_quote_in_quotes() {
-    assertThat(trimFieldsAndRemoveEmptyFields("\"f\"\"oo\"")).isEqualTo("\"f\"\"oo\"");
-    assertThat(trimFieldsAndRemoveEmptyFields("\"f\"\"oo\",\"bar\"\"\"")).isEqualTo("\"f\"\"oo\",\"bar\"\"\"");
-  }
-
-  @Test
-  public void trimFieldsAndRemoveEmptyFields_does_not_fail_on_unbalanced_quotes() {
-    assertThat(trimFieldsAndRemoveEmptyFields("\"")).isEqualTo("\"");
-    assertThat(trimFieldsAndRemoveEmptyFields("\"foo")).isEqualTo("\"foo");
-    assertThat(trimFieldsAndRemoveEmptyFields("foo\"")).isEqualTo("foo\"");
-
-    assertThat(trimFieldsAndRemoveEmptyFields("\"foo\",\"")).isEqualTo("\"foo\",\"");
-    assertThat(trimFieldsAndRemoveEmptyFields("\",\"foo\"")).isEqualTo("\",\"foo\"");
-
-    assertThat(trimFieldsAndRemoveEmptyFields("\"foo\",\",  ")).isEqualTo("\"foo\",\",  ");
-
-    assertThat(trimFieldsAndRemoveEmptyFields(" a ,,b , c,  \"foo\",\"  ")).isEqualTo("a,b,c,\"foo\",\"  ");
-    assertThat(trimFieldsAndRemoveEmptyFields("\" a ,,b , c,  ")).isEqualTo("\" a ,,b , c,  ");
-  }
-
-  private static final char[] SOME_PRINTABLE_TRIMMABLE_CHARS = {
-    ' ', '\t', '\n', '\r'
-  };
-
-  /**
-   * Result of randomTrimmedChars being used as arguments to JUnit test method through the DataProvider feature, they
-   * are printed to surefire report. Some of those chars breaks the parsing of the surefire report during sonar analysis.
-   * Therefor, we only use a subset of the trimmable chars.
-   */
-  private static String randomTrimmedChars(int length, Random random) {
-    char[] chars = new char[length];
-    for (int i = 0; i < chars.length; i++) {
-      chars[i] = SOME_PRINTABLE_TRIMMABLE_CHARS[random.nextInt(SOME_PRINTABLE_TRIMMABLE_CHARS.length)];
-    }
-    return new String(chars);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/MetadataLoaderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/MetadataLoaderTest.java
deleted file mode 100644 (file)
index e6106a3..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.context;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import org.sonar.api.SonarEdition;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.context.MetadataLoader;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.Version;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class MetadataLoaderTest {
-  private System2 system = mock(System2.class);
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void load_version_from_file_in_classpath() {
-    Version version = org.sonar.api.impl.context.MetadataLoader.loadVersion(System2.INSTANCE);
-    assertThat(version).isNotNull();
-    assertThat(version.major()).isGreaterThanOrEqualTo(5);
-  }
-
-  @Test
-  public void load_edition_from_file_in_classpath() {
-    SonarEdition edition = org.sonar.api.impl.context.MetadataLoader.loadEdition(System2.INSTANCE);
-    assertThat(edition).isNotNull();
-  }
-
-  @Test
-  public void load_edition_defaults_to_community_if_file_not_found() throws MalformedURLException {
-    when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL());
-    SonarEdition edition = org.sonar.api.impl.context.MetadataLoader.loadEdition(System2.INSTANCE);
-    assertThat(edition).isEqualTo(SonarEdition.COMMUNITY);
-  }
-
-  @Test
-  public void throw_ISE_if_edition_is_invalid() {
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Invalid edition found in '/sonar-edition.txt': 'TRASH'");
-
-    org.sonar.api.impl.context.MetadataLoader.parseEdition("trash");
-  }
-
-  @Test
-  public void throw_ISE_if_fail_to_load_version() throws Exception {
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Can not load /sonar-api-version.txt from classpath");
-
-    when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL());
-    MetadataLoader.loadVersion(system);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/SonarRuntimeImplTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/SonarRuntimeImplTest.java
deleted file mode 100644 (file)
index 617dbaf..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.context;
-
-import org.sonar.api.SonarEdition;
-import org.assertj.core.api.Assertions;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.SonarProduct;
-import org.sonar.api.SonarQubeSide;
-import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
-import org.sonar.api.utils.Version;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class SonarRuntimeImplTest {
-
-  private static final Version A_VERSION = Version.parse("6.0");
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void sonarQube_environment() {
-    SonarRuntime apiVersion = org.sonar.api.impl.context.SonarRuntimeImpl.forSonarQube(A_VERSION, SonarQubeSide.SCANNER, SonarEdition.COMMUNITY);
-    assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION);
-    assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARQUBE);
-    assertThat(apiVersion.getSonarQubeSide()).isEqualTo(SonarQubeSide.SCANNER);
-  }
-
-  @Test
-  public void sonarLint_environment() {
-    SonarRuntime apiVersion = org.sonar.api.impl.context.SonarRuntimeImpl.forSonarLint(A_VERSION);
-    assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION);
-    assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARLINT);
-    try {
-      apiVersion.getSonarQubeSide();
-      Assertions.fail("Expected exception");
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(UnsupportedOperationException.class);
-    }
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void sonarqube_requires_side() {
-    SonarRuntimeImpl.forSonarQube(A_VERSION, null, null);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultFileSystemTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultFileSystemTest.java
deleted file mode 100644 (file)
index 552387c..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.nio.charset.Charset;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultFileSystemTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private DefaultFileSystem fs;
-
-  private File basedir;
-
-  @Before
-  public void prepare() throws Exception {
-    basedir = temp.newFolder();
-    fs = new DefaultFileSystem(basedir.toPath());
-  }
-
-  @Test
-  public void test_directories() throws Exception {
-    assertThat(fs.baseDir()).isAbsolute().isDirectory().exists();
-    assertThat(fs.baseDir().getCanonicalPath()).isEqualTo(basedir.getCanonicalPath());
-
-    File workdir = temp.newFolder();
-    fs.setWorkDir(workdir.toPath());
-    assertThat(fs.workDir()).isAbsolute().isDirectory().exists();
-    assertThat(fs.workDir().getCanonicalPath()).isEqualTo(workdir.getCanonicalPath());
-  }
-
-  @Test
-  public void test_encoding() throws Exception {
-    fs.setEncoding(Charset.forName("ISO-8859-1"));
-    assertThat(fs.encoding()).isEqualTo(Charset.forName("ISO-8859-1"));
-  }
-
-  @Test
-  public void add_languages() {
-    assertThat(fs.languages()).isEmpty();
-
-    fs.add(new TestInputFileBuilder("foo", "src/Foo.php").setLanguage("php").build());
-    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
-
-    assertThat(fs.languages()).containsOnly("java", "php");
-  }
-
-  @Test
-  public void files() {
-    assertThat(fs.inputFiles(fs.predicates().all())).isEmpty();
-
-    fs.add(new TestInputFileBuilder("foo", "src/Foo.php").setLanguage("php").build());
-    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
-    fs.add(new TestInputFileBuilder("foo", "src/Baz.java").setLanguage("java").build());
-
-    // no language
-    fs.add(new TestInputFileBuilder("foo", "src/readme.txt").build());
-
-    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNotNull();
-    assertThat(fs.inputFile(fs.predicates().hasRelativePath("does/not/exist"))).isNull();
-
-    assertThat(fs.inputFile(fs.predicates().hasAbsolutePath(new File(basedir, "src/Bar.java").getAbsolutePath()))).isNotNull();
-    assertThat(fs.inputFile(fs.predicates().hasAbsolutePath(new File(basedir, "does/not/exist").getAbsolutePath()))).isNull();
-    assertThat(fs.inputFile(fs.predicates().hasAbsolutePath(new File(basedir, "../src/Bar.java").getAbsolutePath()))).isNull();
-
-    assertThat(fs.inputFile(fs.predicates().hasURI(new File(basedir, "src/Bar.java").toURI()))).isNotNull();
-    assertThat(fs.inputFile(fs.predicates().hasURI(new File(basedir, "does/not/exist").toURI()))).isNull();
-    assertThat(fs.inputFile(fs.predicates().hasURI(new File(basedir, "../src/Bar.java").toURI()))).isNull();
-
-    assertThat(fs.files(fs.predicates().all())).hasSize(4);
-    assertThat(fs.files(fs.predicates().hasLanguage("java"))).hasSize(2);
-    assertThat(fs.files(fs.predicates().hasLanguage("cobol"))).isEmpty();
-
-    assertThat(fs.hasFiles(fs.predicates().all())).isTrue();
-    assertThat(fs.hasFiles(fs.predicates().hasLanguage("java"))).isTrue();
-    assertThat(fs.hasFiles(fs.predicates().hasLanguage("cobol"))).isFalse();
-
-    assertThat(fs.inputFiles(fs.predicates().all())).hasSize(4);
-    assertThat(fs.inputFiles(fs.predicates().hasLanguage("php"))).hasSize(1);
-    assertThat(fs.inputFiles(fs.predicates().hasLanguage("java"))).hasSize(2);
-    assertThat(fs.inputFiles(fs.predicates().hasLanguage("cobol"))).isEmpty();
-
-    assertThat(fs.languages()).containsOnly("java", "php");
-  }
-
-  @Test
-  public void input_file_returns_null_if_file_not_found() {
-    assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNull();
-    assertThat(fs.inputFile(fs.predicates().hasLanguage("cobol"))).isNull();
-  }
-
-  @Test
-  public void input_file_fails_if_too_many_results() {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage("expected one element");
-
-    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
-    fs.add(new TestInputFileBuilder("foo", "src/Baz.java").setLanguage("java").build());
-
-    fs.inputFile(fs.predicates().all());
-  }
-
-  @Test
-  public void input_file_supports_non_indexed_predicates() {
-    fs.add(new TestInputFileBuilder("foo", "src/Bar.java").setLanguage("java").build());
-
-    // it would fail if more than one java file
-    assertThat(fs.inputFile(fs.predicates().hasLanguage("java"))).isNotNull();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputDirTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputDirTest.java
deleted file mode 100644 (file)
index 263032b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultInputDirTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void test() throws Exception {
-    File baseDir = temp.newFolder();
-    DefaultInputDir inputDir = new DefaultInputDir("ABCDE", "src")
-      .setModuleBaseDir(baseDir.toPath());
-
-    assertThat(inputDir.key()).isEqualTo("ABCDE:src");
-    assertThat(inputDir.file().getAbsolutePath()).isEqualTo(new File(baseDir, "src").getAbsolutePath());
-    assertThat(inputDir.relativePath()).isEqualTo("src");
-    assertThat(new File(inputDir.relativePath())).isRelative();
-    assertThat(inputDir.absolutePath()).endsWith("src");
-    assertThat(new File(inputDir.absolutePath())).isAbsolute();
-  }
-
-  @Test
-  public void testEqualsAndHashCode() throws Exception {
-    DefaultInputDir inputDir1 = new DefaultInputDir("ABCDE", "src");
-
-    DefaultInputDir inputDir2 = new DefaultInputDir("ABCDE", "src");
-
-    assertThat(inputDir1.equals(inputDir1)).isTrue();
-    assertThat(inputDir1.equals(inputDir2)).isTrue();
-    assertThat(inputDir1.equals("foo")).isFalse();
-
-    assertThat(inputDir1.hashCode()).isEqualTo(63545559);
-
-    assertThat(inputDir1.toString()).contains("[moduleKey=ABCDE, relative=src, basedir=null");
-
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputFileTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputFileTest.java
deleted file mode 100644 (file)
index 7e22203..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.stream.Collectors;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-
-public class DefaultInputFileTest {
-
-  private static final String PROJECT_RELATIVE_PATH = "module1/src/Foo.php";
-  private static final String MODULE_RELATIVE_PATH = "src/Foo.php";
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private DefaultIndexedFile indexedFile;
-
-  private Path baseDir;
-  private SensorStrategy sensorStrategy;
-
-  @Before
-  public void prepare() throws IOException {
-    baseDir = temp.newFolder().toPath();
-    sensorStrategy = new SensorStrategy();
-    indexedFile = new DefaultIndexedFile(baseDir.resolve(PROJECT_RELATIVE_PATH), "ABCDE", PROJECT_RELATIVE_PATH, MODULE_RELATIVE_PATH, InputFile.Type.TEST, "php", 0,
-      sensorStrategy);
-  }
-
-  @Test
-  public void test() throws Exception {
-
-    Metadata metadata = new Metadata(42, 42, "", new int[0], new int[0], 10);
-    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, (f) -> f.setMetadata(metadata))
-      .setStatus(InputFile.Status.ADDED)
-      .setCharset(StandardCharsets.ISO_8859_1);
-
-    assertThat(inputFile.absolutePath()).endsWith("Foo.php");
-    assertThat(inputFile.filename()).isEqualTo("Foo.php");
-    assertThat(inputFile.uri()).hasPath(baseDir.resolve(PROJECT_RELATIVE_PATH).toUri().getPath());
-    assertThat(new File(inputFile.absolutePath())).isAbsolute();
-    assertThat(inputFile.language()).isEqualTo("php");
-    assertThat(inputFile.status()).isEqualTo(InputFile.Status.ADDED);
-    assertThat(inputFile.type()).isEqualTo(InputFile.Type.TEST);
-    assertThat(inputFile.lines()).isEqualTo(42);
-    assertThat(inputFile.charset()).isEqualTo(StandardCharsets.ISO_8859_1);
-
-    assertThat(inputFile.getModuleRelativePath()).isEqualTo(MODULE_RELATIVE_PATH);
-    assertThat(inputFile.getProjectRelativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
-
-    sensorStrategy.setGlobal(false);
-    assertThat(inputFile.relativePath()).isEqualTo(MODULE_RELATIVE_PATH);
-    assertThat(new File(inputFile.relativePath())).isRelative();
-    sensorStrategy.setGlobal(true);
-    assertThat(inputFile.relativePath()).isEqualTo(PROJECT_RELATIVE_PATH);
-    assertThat(new File(inputFile.relativePath())).isRelative();
-  }
-
-  @Test
-  public void test_content() throws IOException {
-    Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
-    Files.createDirectories(testFile.getParent());
-    String content = "test Ã© string";
-    Files.write(testFile, content.getBytes(StandardCharsets.ISO_8859_1));
-
-    assertThat(Files.readAllLines(testFile, StandardCharsets.ISO_8859_1).get(0)).hasSize(content.length());
-
-    Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
-
-    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
-      .setStatus(InputFile.Status.ADDED)
-      .setCharset(StandardCharsets.ISO_8859_1);
-
-    assertThat(inputFile.contents()).isEqualTo(content);
-    try (InputStream inputStream = inputFile.inputStream()) {
-      String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
-      assertThat(result).isEqualTo(content);
-    }
-
-  }
-
-  @Test
-  public void test_content_exclude_bom() throws IOException {
-    Path testFile = baseDir.resolve(PROJECT_RELATIVE_PATH);
-    Files.createDirectories(testFile.getParent());
-    try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(testFile.toFile()), StandardCharsets.UTF_8))) {
-      out.write('\ufeff');
-    }
-    String content = "test Ã© string â‚¬";
-    Files.write(testFile, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
-
-    assertThat(Files.readAllLines(testFile, StandardCharsets.UTF_8).get(0)).hasSize(content.length() + 1);
-
-    Metadata metadata = new Metadata(42, 30, "", new int[0], new int[0], 10);
-
-    DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> f.setMetadata(metadata))
-      .setStatus(InputFile.Status.ADDED)
-      .setCharset(StandardCharsets.UTF_8);
-
-    assertThat(inputFile.contents()).isEqualTo(content);
-    try (InputStream inputStream = inputFile.inputStream()) {
-      String result = new BufferedReader(new InputStreamReader(inputStream, inputFile.charset())).lines().collect(Collectors.joining());
-      assertThat(result).isEqualTo(content);
-    }
-
-  }
-
-  @Test
-  public void test_equals_and_hashcode() throws Exception {
-    DefaultInputFile f1 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
-    DefaultInputFile f1a = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
-    DefaultInputFile f2 = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), "src/Bar.php", null), (f) -> mock(Metadata.class));
-
-    assertThat(f1).isEqualTo(f1);
-    assertThat(f1).isEqualTo(f1a);
-    assertThat(f1).isNotEqualTo(f2);
-    assertThat(f1.equals("foo")).isFalse();
-    assertThat(f1.equals(null)).isFalse();
-
-    assertThat(f1.hashCode()).isEqualTo(f1.hashCode());
-    assertThat(f1.hashCode()).isEqualTo(f1a.hashCode());
-  }
-
-  @Test
-  public void test_toString() throws Exception {
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), (f) -> mock(Metadata.class));
-    assertThat(file.toString()).isEqualTo(MODULE_RELATIVE_PATH);
-  }
-
-  @Test
-  public void checkValidPointer() {
-    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-    assertThat(file.newPointer(1, 0).line()).isEqualTo(1);
-    assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0);
-    // Don't fail
-    file.newPointer(1, 9);
-    file.newPointer(2, 0);
-    file.newPointer(2, 5);
-
-    try {
-      file.newPointer(0, 1);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("0 is not a valid line for a file");
-    }
-    try {
-      file.newPointer(3, 1);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("3 is not a valid line for pointer. File src/Foo.php has 2 line(s)");
-    }
-    try {
-      file.newPointer(1, -1);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("-1 is not a valid line offset for a file");
-    }
-    try {
-      file.newPointer(1, 10);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
-    }
-  }
-
-  @Test
-  public void checkValidPointerUsingGlobalOffset() {
-    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {8, 15}, 16);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-    assertThat(file.newPointer(0).line()).isEqualTo(1);
-    assertThat(file.newPointer(0).lineOffset()).isEqualTo(0);
-
-    assertThat(file.newPointer(9).line()).isEqualTo(1);
-    // Ignore eol characters
-    assertThat(file.newPointer(9).lineOffset()).isEqualTo(8);
-
-    assertThat(file.newPointer(10).line()).isEqualTo(2);
-    assertThat(file.newPointer(10).lineOffset()).isEqualTo(0);
-
-    assertThat(file.newPointer(15).line()).isEqualTo(2);
-    assertThat(file.newPointer(15).lineOffset()).isEqualTo(5);
-
-    assertThat(file.newPointer(16).line()).isEqualTo(2);
-    // Ignore eol characters
-    assertThat(file.newPointer(16).lineOffset()).isEqualTo(5);
-
-    try {
-      file.newPointer(-1);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("-1 is not a valid offset for a file");
-    }
-
-    try {
-      file.newPointer(17);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("17 is not a valid offset for file src/Foo.php. Max offset is 16");
-    }
-  }
-
-  @Test
-  public void checkValidRange() {
-    Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde"));
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-
-    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1);
-    // Don't fail
-    file.newRange(file.newPointer(1, 0), file.newPointer(1, 1));
-    file.newRange(file.newPointer(1, 0), file.newPointer(1, 9));
-    file.newRange(file.newPointer(1, 0), file.newPointer(2, 0));
-    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 5))).isEqualTo(file.newRange(0, 15));
-
-    try {
-      file.newRange(file.newPointer(1, 0), file.newPointer(1, 0));
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("Start pointer [line=1, lineOffset=0] should be before end pointer [line=1, lineOffset=0]");
-    }
-    try {
-      file.newRange(file.newPointer(1, 0), file.newPointer(1, 10));
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("10 is not a valid line offset for pointer. File src/Foo.php has 9 character(s) at line 1");
-    }
-  }
-
-  @Test
-  public void selectLine() {
-    Metadata metadata = new FileMetadata().readMetadata(new StringReader("bla bla a\nabcde\n\nabc"));
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-
-    assertThat(file.selectLine(1).start().line()).isEqualTo(1);
-    assertThat(file.selectLine(1).start().lineOffset()).isEqualTo(0);
-    assertThat(file.selectLine(1).end().line()).isEqualTo(1);
-    assertThat(file.selectLine(1).end().lineOffset()).isEqualTo(9);
-
-    // Don't fail when selecting empty line
-    assertThat(file.selectLine(3).start().line()).isEqualTo(3);
-    assertThat(file.selectLine(3).start().lineOffset()).isEqualTo(0);
-    assertThat(file.selectLine(3).end().line()).isEqualTo(3);
-    assertThat(file.selectLine(3).end().lineOffset()).isEqualTo(0);
-
-    try {
-      file.selectLine(5);
-      fail();
-    } catch (Exception e) {
-      assertThat(e).hasMessage("5 is not a valid line for pointer. File src/Foo.php has 4 line(s)");
-    }
-  }
-
-  @Test
-  public void checkValidRangeUsingGlobalOffset() {
-    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-    TextRange newRange = file.newRange(10, 13);
-    assertThat(newRange.start().line()).isEqualTo(2);
-    assertThat(newRange.start().lineOffset()).isEqualTo(0);
-    assertThat(newRange.end().line()).isEqualTo(2);
-    assertThat(newRange.end().lineOffset()).isEqualTo(3);
-  }
-
-  @Test
-  public void testRangeOverlap() {
-    Metadata metadata = new Metadata(2, 2, "", new int[] {0, 10}, new int[] {9, 15}, 16);
-    DefaultInputFile file = new DefaultInputFile(new DefaultIndexedFile("ABCDE", Paths.get("module"), MODULE_RELATIVE_PATH, null), f -> f.setMetadata(metadata));
-    // Don't fail
-    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)))).isTrue();
-    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isTrue();
-    assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 1), file.newPointer(1, 2)))).isFalse();
-    assertThat(file.newRange(file.newPointer(1, 2), file.newPointer(1, 3)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isFalse();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputModuleTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputModuleTest.java
deleted file mode 100644 (file)
index ac1a2c4..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultInputModuleTest {
-
-  private static final String FILE_1 = "file1";
-  private static final String TEST_1 = "test1";
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void check_getters() throws IOException {
-    ProjectDefinition def = ProjectDefinition.create();
-    def.setKey("moduleKey");
-    File baseDir = temp.newFolder();
-    Path src = baseDir.toPath().resolve(FILE_1);
-    Files.createFile(src);
-    Path test = baseDir.toPath().resolve(TEST_1);
-    Files.createFile(test);
-    def.setBaseDir(baseDir);
-    File workDir = temp.newFolder();
-    def.setWorkDir(workDir);
-    def.setSources(FILE_1);
-    def.setTests(TEST_1);
-    DefaultInputModule module = new DefaultInputModule(def);
-
-    assertThat(module.key()).isEqualTo("moduleKey");
-    assertThat(module.definition()).isEqualTo(def);
-    assertThat(module.getBranch()).isNull();
-    assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
-    assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
-    assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
-    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
-    assertThat(module.getSourceDirsOrFiles().get()).containsExactlyInAnyOrder(src);
-    assertThat(module.getTestDirsOrFiles().get()).containsExactlyInAnyOrder(test);
-    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
-
-    assertThat(module.isFile()).isFalse();
-  }
-
-  @Test
-  public void no_sources() throws IOException {
-    ProjectDefinition def = ProjectDefinition.create();
-    def.setKey("moduleKey");
-    File baseDir = temp.newFolder();
-    Path src = baseDir.toPath().resolve(FILE_1);
-    Files.createFile(src);
-    Path test = baseDir.toPath().resolve(TEST_1);
-    Files.createFile(test);
-    def.setBaseDir(baseDir);
-    File workDir = temp.newFolder();
-    def.setWorkDir(workDir);
-    DefaultInputModule module = new DefaultInputModule(def);
-
-    assertThat(module.key()).isEqualTo("moduleKey");
-    assertThat(module.definition()).isEqualTo(def);
-    assertThat(module.getBranch()).isNull();
-    assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
-    assertThat(module.getKeyWithBranch()).isEqualTo("moduleKey");
-    assertThat(module.getWorkDir()).isEqualTo(workDir.toPath());
-    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
-    assertThat(module.getSourceDirsOrFiles()).isNotPresent();
-    assertThat(module.getTestDirsOrFiles()).isNotPresent();
-    assertThat(module.getEncoding()).isEqualTo(Charset.defaultCharset());
-
-    assertThat(module.isFile()).isFalse();
-  }
-
-  @Test
-  public void working_directory_should_be_hidden() throws IOException {
-    ProjectDefinition def = ProjectDefinition.create();
-    File workDir = temp.newFolder(".sonar");
-    def.setWorkDir(workDir);
-    File baseDir = temp.newFolder();
-    def.setBaseDir(baseDir);
-    DefaultInputModule module = new DefaultInputModule(def);
-    assertThat(workDir.isHidden()).isTrue();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputProjectTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputProjectTest.java
deleted file mode 100644 (file)
index bd3f493..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultInputProjectTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void testGetters() throws IOException {
-    ProjectDefinition def = ProjectDefinition.create();
-    def.setKey("projectKey");
-    def.setName("projectName");
-    File baseDir = temp.newFolder();
-    def.setBaseDir(baseDir);
-    def.setDescription("desc");
-    File workDir = temp.newFolder();
-    def.setWorkDir(workDir);
-    def.setSources("file1");
-    def.setTests("test1");
-    AbstractProjectOrModule project = new DefaultInputProject(def);
-
-    assertThat(project.key()).isEqualTo("projectKey");
-    assertThat(project.getName()).isEqualTo("projectName");
-    assertThat(project.getOriginalName()).isEqualTo("projectName");
-    assertThat(project.definition()).isEqualTo(def);
-    assertThat(project.getBranch()).isNull();
-    assertThat(project.getBaseDir()).isEqualTo(baseDir.toPath());
-    assertThat(project.getKeyWithBranch()).isEqualTo("projectKey");
-    assertThat(project.getDescription()).isEqualTo("desc");
-    assertThat(project.getWorkDir()).isEqualTo(workDir.toPath());
-    assertThat(project.getEncoding()).isEqualTo(Charset.defaultCharset());
-
-    assertThat(project.properties()).hasSize(5);
-
-    assertThat(project.isFile()).isFalse();
-  }
-
-  @Test
-  public void testEncoding() throws IOException {
-    ProjectDefinition def = ProjectDefinition.create();
-    def.setKey("projectKey");
-    def.setName("projectName");
-    File baseDir = temp.newFolder();
-    def.setBaseDir(baseDir);
-    def.setProjectVersion("version");
-    def.setDescription("desc");
-    File workDir = temp.newFolder();
-    def.setWorkDir(workDir);
-    def.setSources("file1");
-    def.setProperty("sonar.sourceEncoding", "UTF-16");
-    AbstractProjectOrModule project = new DefaultInputProject(def);
-
-    assertThat(project.getEncoding()).isEqualTo(StandardCharsets.UTF_16);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/FileMetadataTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/FileMetadataTest.java
deleted file mode 100644 (file)
index 0f3f1d5..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import javax.annotation.Nullable;
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.io.FileUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-
-import static org.apache.commons.codec.digest.DigestUtils.md5Hex;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-
-public class FileMetadataTest {
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public LogTester logTester = new LogTester();
-
-  @Test
-  public void empty_file() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.touch(tempFile);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(1);
-    assertThat(metadata.nonBlankLines()).isEqualTo(0);
-    assertThat(metadata.hash()).isNotEmpty();
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(0);
-    assertThat(metadata.isEmpty()).isTrue();
-  }
-
-  @Test
-  public void windows_without_latest_eol() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\r\nbar\r\nbaz", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(3);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 5, 10);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 8, 13);
-    assertThat(metadata.isEmpty()).isFalse();
-  }
-
-  @Test
-  public void read_with_wrong_encoding() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "marker´s\n", Charset.forName("cp1252"));
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(2);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("marker\ufffds\n"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 9);
-  }
-
-  @Test
-  public void non_ascii_utf_8() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(4);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 5, 10, 18);
-  }
-
-  @Test
-  public void non_ascii_utf_16() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", StandardCharsets.UTF_16, true);
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_16, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(4);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n".getBytes(StandardCharsets.UTF_8)));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 5, 10, 18);
-  }
-
-  @Test
-  public void unix_without_latest_eol() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\nbar\nbaz", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(3);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11);
-    assertThat(metadata.isEmpty()).isFalse();
-  }
-
-  @Test
-  public void unix_with_latest_eol() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\nbar\nbaz\n", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(4);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8, 12);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11, 12);
-  }
-
-  @Test
-  public void mac_without_latest_eol() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\rbar\rbaz", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(3);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11);
-  }
-
-  @Test
-  public void mac_with_latest_eol() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\rbar\rbaz\r", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(4);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 8, 12);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 11, 12);
-  }
-
-  @Test
-  public void mix_of_newlines_with_latest_eol() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\nbar\r\nbaz\n", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(4);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 9, 13);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 12, 13);
-  }
-
-  @Test
-  public void several_new_lines() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\n\n\nbar", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(4);
-    assertThat(metadata.nonBlankLines()).isEqualTo(2);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\n\n\nbar"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 5, 6);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 4, 5, 9);
-  }
-
-  @Test
-  public void mix_of_newlines_without_latest_eol() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "foo\nbar\r\nbaz", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(3);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("foo\nbar\nbaz"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 4, 9);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(3, 7, 12);
-  }
-
-  @Test
-  public void start_with_newline() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "\nfoo\nbar\r\nbaz", StandardCharsets.UTF_8, true);
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(tempFile), StandardCharsets.UTF_8, tempFile.getName());
-    assertThat(metadata.lines()).isEqualTo(4);
-    assertThat(metadata.nonBlankLines()).isEqualTo(3);
-    assertThat(metadata.hash()).isEqualTo(md5Hex("\nfoo\nbar\nbaz"));
-    assertThat(metadata.originalLineStartOffsets()).containsOnly(0, 1, 5, 10);
-    assertThat(metadata.originalLineEndOffsets()).containsOnly(0, 4, 8, 13);
-  }
-
-  @Test
-  public void ignore_whitespace_when_computing_line_hashes() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, " foo\nb ar\r\nbaz \t", StandardCharsets.UTF_8, true);
-
-    DefaultInputFile f = new TestInputFileBuilder("foo", tempFile.getName())
-      .setModuleBaseDir(tempFile.getParentFile().toPath())
-      .setCharset(StandardCharsets.UTF_8)
-      .build();
-    FileMetadata.computeLineHashesForIssueTracking(f, new FileMetadata.LineHashConsumer() {
-
-      @Override
-      public void consume(int lineIdx, @Nullable byte[] hash) {
-        switch (lineIdx) {
-          case 1:
-            assertThat(Hex.encodeHexString(hash)).isEqualTo(md5Hex("foo"));
-            break;
-          case 2:
-            assertThat(Hex.encodeHexString(hash)).isEqualTo(md5Hex("bar"));
-            break;
-          case 3:
-            assertThat(Hex.encodeHexString(hash)).isEqualTo(md5Hex("baz"));
-            break;
-          default:
-            fail("Invalid line");
-        }
-      }
-    });
-  }
-
-  @Test
-  public void dont_fail_on_empty_file() throws Exception {
-    File tempFile = temp.newFile();
-    FileUtils.write(tempFile, "", StandardCharsets.UTF_8, true);
-
-    DefaultInputFile f = new TestInputFileBuilder("foo", tempFile.getName())
-      .setModuleBaseDir(tempFile.getParentFile().toPath())
-      .setCharset(StandardCharsets.UTF_8)
-      .build();
-    FileMetadata.computeLineHashesForIssueTracking(f, new FileMetadata.LineHashConsumer() {
-
-      @Override
-      public void consume(int lineIdx, @Nullable byte[] hash) {
-        switch (lineIdx) {
-          case 1:
-            assertThat(hash).isNull();
-            break;
-          default:
-            fail("Invalid line");
-        }
-      }
-    });
-  }
-
-  @Test
-  public void line_feed_is_included_into_hash() throws Exception {
-    File file1 = temp.newFile();
-    FileUtils.write(file1, "foo\nbar\n", StandardCharsets.UTF_8, true);
-
-    // same as file1, except an additional return carriage
-    File file1a = temp.newFile();
-    FileUtils.write(file1a, "foo\r\nbar\n", StandardCharsets.UTF_8, true);
-
-    File file2 = temp.newFile();
-    FileUtils.write(file2, "foo\nbar", StandardCharsets.UTF_8, true);
-
-    String hash1 = new FileMetadata().readMetadata(new FileInputStream(file1), StandardCharsets.UTF_8, file1.getName()).hash();
-    String hash1a = new FileMetadata().readMetadata(new FileInputStream(file1a), StandardCharsets.UTF_8, file1a.getName()).hash();
-    String hash2 = new FileMetadata().readMetadata(new FileInputStream(file2), StandardCharsets.UTF_8, file2.getName()).hash();
-
-    assertThat(hash1).isEqualTo(hash1a);
-    assertThat(hash1).isNotEqualTo(hash2);
-  }
-
-  @Test
-  public void binary_file_with_unmappable_character() throws Exception {
-    File woff = new File(this.getClass().getResource("glyphicons-halflings-regular.woff").toURI());
-
-    Metadata metadata = new FileMetadata().readMetadata(new FileInputStream(woff), StandardCharsets.UTF_8, woff.getAbsolutePath());
-
-    assertThat(metadata.lines()).isEqualTo(135);
-    assertThat(metadata.nonBlankLines()).isEqualTo(133);
-    assertThat(metadata.hash()).isNotEmpty();
-
-    assertThat(logTester.logs(LoggerLevel.WARN).get(0)).contains("Invalid character encountered in file");
-    assertThat(logTester.logs(LoggerLevel.WARN).get(0)).contains(
-      "glyphicons-halflings-regular.woff at line 1 for encoding UTF-8. Please fix file content or configure the encoding to be used using property 'sonar.sourceEncoding'.");
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/MetadataTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/MetadataTest.java
deleted file mode 100644 (file)
index 49ecf89..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.junit.Test;
-import org.sonar.api.impl.fs.Metadata;
-
-public class MetadataTest {
-  @Test
-  public void testRoundtrip() {
-    org.sonar.api.impl.fs.Metadata metadata = new Metadata(10, 20, "hash", new int[] {1, 3}, new int[] {2, 4}, 5);
-    assertThat(metadata.isEmpty()).isFalse();
-    assertThat(metadata.lines()).isEqualTo(10);
-    assertThat(metadata.nonBlankLines()).isEqualTo(20);
-    assertThat(metadata.originalLineStartOffsets()).isEqualTo(new int[] {1, 3});
-    assertThat(metadata.originalLineEndOffsets()).isEqualTo(new int[] {2, 4});
-    assertThat(metadata.lastValidOffset()).isEqualTo(5);
-    assertThat(metadata.hash()).isEqualTo("hash");
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/PathPatternTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/PathPatternTest.java
deleted file mode 100644 (file)
index c214469..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.IndexedFile;
-import org.sonar.api.impl.fs.DefaultIndexedFile;
-import org.sonar.api.impl.fs.PathPattern;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class PathPatternTest {
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-  private Path baseDir;
-
-  @Before
-  public void setUp() throws IOException {
-    baseDir = temp.newFolder().toPath();
-  }
-
-  @Test
-  public void match_relative_path() {
-    org.sonar.api.impl.fs.PathPattern pattern = org.sonar.api.impl.fs.PathPattern.create("**/*Foo.java");
-    assertThat(pattern.toString()).isEqualTo("**/*Foo.java");
-
-    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.java", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isTrue();
-
-    // case sensitive by default
-    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
-
-    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.java", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
-  }
-
-  @Test
-  public void match_relative_path_and_insensitive_file_extension() throws Exception {
-    org.sonar.api.impl.fs.PathPattern pattern = org.sonar.api.impl.fs.PathPattern.create("**/*Foo.java");
-
-    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isTrue();
-
-    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.java", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isFalse();
-  }
-
-  @Test
-  public void match_absolute_path() throws Exception {
-    org.sonar.api.impl.fs.PathPattern pattern = org.sonar.api.impl.fs.PathPattern.create("file:**/src/main/**Foo.java");
-    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
-
-    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.java", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isTrue();
-
-    // case sensitive by default
-    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
-
-    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.java", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()))).isFalse();
-  }
-
-  @Test
-  public void match_absolute_path_and_insensitive_file_extension() throws Exception {
-    org.sonar.api.impl.fs.PathPattern pattern = org.sonar.api.impl.fs.PathPattern.create("file:**/src/main/**Foo.java");
-    assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java");
-
-    IndexedFile indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/MyFoo.JAVA", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isTrue();
-
-    indexedFile = new DefaultIndexedFile("ABCDE", baseDir, "src/main/java/org/Other.JAVA", null);
-    assertThat(pattern.match(indexedFile.path(), Paths.get(indexedFile.relativePath()), false)).isFalse();
-  }
-
-  @Test
-  public void create_array_of_patterns() {
-    org.sonar.api.impl.fs.PathPattern[] patterns = PathPattern.create(new String[] {
-      "**/src/main/**Foo.java",
-      "file:**/src/main/**Bar.java"
-    });
-    assertThat(patterns).hasSize(2);
-    assertThat(patterns[0].toString()).isEqualTo("**/src/main/**Foo.java");
-    assertThat(patterns[1].toString()).isEqualTo("file:**/src/main/**Bar.java");
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/TestInputFileBuilderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/TestInputFileBuilderTest.java
deleted file mode 100644 (file)
index 4fb37a2..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import org.apache.commons.io.IOUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.batch.fs.InputFile.Type;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class TestInputFileBuilderTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void setContent() throws IOException {
-    DefaultInputFile file = TestInputFileBuilder.create("module", "invalidPath")
-      .setContents("my content")
-      .setCharset(StandardCharsets.UTF_8)
-      .build();
-    assertThat(file.contents()).isEqualTo("my content");
-    assertThat(IOUtils.toString(file.inputStream())).isEqualTo("my content");
-  }
-
-  @Test
-  public void testGetters() {
-    DefaultInputFile file = TestInputFileBuilder.create("module", new File("baseDir"), new File("baseDir", "path"))
-      .setStatus(Status.SAME)
-      .setType(Type.MAIN)
-      .build();
-
-    assertThat(file.type()).isEqualTo(Type.MAIN);
-    assertThat(file.status()).isEqualTo(Status.SAME);
-    assertThat(file.isPublished()).isTrue();
-    assertThat(file.type()).isEqualTo(Type.MAIN);
-    assertThat(file.relativePath()).isEqualTo("path");
-    assertThat(file.absolutePath()).isEqualTo("baseDir/path");
-
-  }
-
-  @Test
-  public void testCreateInputModule() throws IOException {
-    File baseDir = temp.newFolder();
-    AbstractProjectOrModule module = TestInputFileBuilder.newDefaultInputModule("key", baseDir);
-    assertThat(module.key()).isEqualTo("key");
-    assertThat(module.getBaseDir()).isEqualTo(baseDir.toPath());
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/charhandler/IntArrayListTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/charhandler/IntArrayListTest.java
deleted file mode 100644 (file)
index 50c37d8..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.charhandler;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class IntArrayListTest {
-
-  @Test
-  public void addElements() {
-    IntArrayList list = new IntArrayList();
-    assertThat(list.trimAndGet()).isEmpty();
-    list.add(1);
-    list.add(2);
-    assertThat(list.trimAndGet()).containsExactly(1, 2);
-  }
-
-  @Test
-  public void trimIfNeeded() {
-    IntArrayList list = new IntArrayList();
-    list.add(1);
-    list.add(2);
-    assertThat(list.trimAndGet()).isSameAs(list.trimAndGet());
-  }
-
-  @Test
-  public void grow() {
-    // Default capacity is 10
-    IntArrayList list = new IntArrayList();
-    for (int i = 1; i <= 11; i++) {
-      list.add(i);
-    }
-    assertThat(list.trimAndGet()).hasSize(11);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/AndPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/AndPredicateTest.java
deleted file mode 100644 (file)
index e02d5e4..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.util.Arrays;
-import org.junit.Test;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.PathPattern;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class AndPredicateTest {
-
-  @Test
-  public void flattenNestedAnd() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
-    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("foo3/**"));
-    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
-      AndPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
-    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2, pathPatternPredicate3);
-  }
-
-  @Test
-  public void applyPredicates() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo/file1"));
-    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("**"));
-    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
-      AndPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
-
-    InputFile file1 = TestInputFileBuilder.create("module", "foo/file1").build();
-    InputFile file2 = TestInputFileBuilder.create("module", "foo2/file1").build();
-    InputFile file3 = TestInputFileBuilder.create("module", "foo/file2").build();
-
-    assertThat(andPredicate.apply(file1)).isTrue();
-    assertThat(andPredicate.apply(file2)).isFalse();
-    assertThat(andPredicate.apply(file3)).isFalse();
-  }
-
-  @Test
-  public void filterIndex() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo/file1"));
-    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("**"));
-
-    InputFile file1 = TestInputFileBuilder.create("module", "foo/file1").build();
-    InputFile file2 = TestInputFileBuilder.create("module", "foo2/file1").build();
-    InputFile file3 = TestInputFileBuilder.create("module", "foo/file2").build();
-
-    FileSystem.Index index = mock(FileSystem.Index.class);
-    when(index.inputFiles()).thenReturn(Arrays.asList(file1, file2, file3));
-
-    OptimizedFilePredicate andPredicate = (OptimizedFilePredicate) AndPredicate.create(Arrays.asList(pathPatternPredicate1,
-      AndPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
-
-    assertThat(andPredicate.get(index)).containsOnly(file1);
-  }
-
-  @Test
-  public void sortPredicatesByPriority() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
-    RelativePathPredicate relativePathPredicate = new RelativePathPredicate("foo");
-    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
-      relativePathPredicate, pathPatternPredicate2));
-    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(relativePathPredicate, pathPatternPredicate1, pathPatternPredicate2);
-  }
-
-  @Test
-  public void simplifyAndExpressionsWhenEmpty() {
-    FilePredicate andPredicate = AndPredicate.create(Arrays.asList());
-    assertThat(andPredicate).isEqualTo(TruePredicate.TRUE);
-  }
-
-  @Test
-  public void simplifyAndExpressionsWhenTrue() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
-    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
-      TruePredicate.TRUE, pathPatternPredicate2));
-    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2);
-  }
-
-  @Test
-  public void simplifyAndExpressionsWhenFalse() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
-    FilePredicate andPredicate = AndPredicate.create(Arrays.asList(pathPatternPredicate1,
-      FalsePredicate.FALSE, pathPatternPredicate2));
-    assertThat(andPredicate).isEqualTo(FalsePredicate.FALSE);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicatesTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicatesTest.java
deleted file mode 100644 (file)
index 6d9cd4e..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.Collections;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.FilePredicates;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultFilePredicatesTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private Path moduleBasePath;
-
-  @Before
-  public void setUp() throws IOException {
-    moduleBasePath = temp.newFolder().toPath();
-  }
-
-  InputFile javaFile;
-  FilePredicates predicates;
-
-  @Before
-  public void before() throws IOException {
-    predicates = new DefaultFilePredicates(temp.newFolder().toPath());
-    javaFile = new TestInputFileBuilder("foo", "src/main/java/struts/Action.java")
-      .setModuleBaseDir(moduleBasePath)
-      .setLanguage("java")
-      .setStatus(Status.SAME)
-      .build();
-
-  }
-
-  @Test
-  public void all() {
-    assertThat(predicates.all().apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void none() {
-    assertThat(predicates.none().apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void matches_inclusion_pattern() {
-    assertThat(predicates.matchesPathPattern("src/main/**/Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.matchesPathPattern("Action.java").apply(javaFile)).isFalse();
-    assertThat(predicates.matchesPathPattern("src/**/*.php").apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void matches_inclusion_patterns() {
-    assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isTrue();
-    assertThat(predicates.matchesPathPatterns(new String[] {}).apply(javaFile)).isTrue();
-    assertThat(predicates.matchesPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void does_not_match_exclusion_pattern() {
-    assertThat(predicates.doesNotMatchPathPattern("src/main/**/Action.java").apply(javaFile)).isFalse();
-    assertThat(predicates.doesNotMatchPathPattern("Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.doesNotMatchPathPattern("src/**/*.php").apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void does_not_match_exclusion_patterns() {
-    assertThat(predicates.doesNotMatchPathPatterns(new String[] {}).apply(javaFile)).isTrue();
-    assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/**/*.php"}).apply(javaFile)).isTrue();
-    assertThat(predicates.doesNotMatchPathPatterns(new String[] {"src/other/**.java", "src/main/**/Action.java"}).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_relative_path() {
-    assertThat(predicates.hasRelativePath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasRelativePath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
-
-    // path is normalized
-    assertThat(predicates.hasRelativePath("src/main/java/../java/struts/Action.java").apply(javaFile)).isTrue();
-
-    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\Other.java").apply(javaFile)).isFalse();
-    assertThat(predicates.hasRelativePath("src\\main\\java\\struts\\..\\struts\\Action.java").apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void has_absolute_path() throws Exception {
-    String path = javaFile.file().getAbsolutePath();
-    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
-    assertThat(predicates.hasAbsolutePath(path.replaceAll("/", "\\\\")).apply(javaFile)).isTrue();
-
-    assertThat(predicates.hasAbsolutePath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
-    assertThat(predicates.hasAbsolutePath("src/main/java/struts/Action.java").apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_uri() throws Exception {
-    URI uri = javaFile.uri();
-    assertThat(predicates.hasURI(uri).apply(javaFile)).isTrue();
-
-    assertThat(predicates.hasURI(temp.newFile().toURI()).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_path() throws Exception {
-    // is relative path
-    assertThat(predicates.hasPath("src/main/java/struts/Action.java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasPath("src/main/java/struts/Other.java").apply(javaFile)).isFalse();
-
-    // is absolute path
-    String path = javaFile.file().getAbsolutePath();
-    assertThat(predicates.hasAbsolutePath(path).apply(javaFile)).isTrue();
-    assertThat(predicates.hasPath(temp.newFile().getAbsolutePath()).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void is_file() throws Exception {
-    // relative file
-    assertThat(predicates.is(new File(javaFile.relativePath())).apply(javaFile)).isTrue();
-
-    // absolute file
-    assertThat(predicates.is(javaFile.file()).apply(javaFile)).isTrue();
-    assertThat(predicates.is(javaFile.file().getAbsoluteFile()).apply(javaFile)).isTrue();
-    assertThat(predicates.is(new File(javaFile.file().toURI())).apply(javaFile)).isTrue();
-    assertThat(predicates.is(temp.newFile()).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_language() {
-    assertThat(predicates.hasLanguage("java").apply(javaFile)).isTrue();
-    assertThat(predicates.hasLanguage("php").apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_languages() {
-    assertThat(predicates.hasLanguages(Arrays.asList("java", "php")).apply(javaFile)).isTrue();
-    assertThat(predicates.hasLanguages(Arrays.asList("cobol", "php")).apply(javaFile)).isFalse();
-    assertThat(predicates.hasLanguages(Collections.<String>emptyList()).apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void has_type() {
-    assertThat(predicates.hasType(InputFile.Type.MAIN).apply(javaFile)).isTrue();
-    assertThat(predicates.hasType(InputFile.Type.TEST).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void has_status() {
-    assertThat(predicates.hasAnyStatus().apply(javaFile)).isTrue();
-    assertThat(predicates.hasStatus(InputFile.Status.SAME).apply(javaFile)).isTrue();
-    assertThat(predicates.hasStatus(InputFile.Status.ADDED).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void not() {
-    assertThat(predicates.not(predicates.hasType(InputFile.Type.MAIN)).apply(javaFile)).isFalse();
-    assertThat(predicates.not(predicates.hasType(InputFile.Type.TEST)).apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void and() {
-    // empty
-    assertThat(predicates.and().apply(javaFile)).isTrue();
-    assertThat(predicates.and(new FilePredicate[0]).apply(javaFile)).isTrue();
-    assertThat(predicates.and(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
-
-    // two arguments
-    assertThat(predicates.and(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
-    assertThat(predicates.and(predicates.all(), predicates.none()).apply(javaFile)).isFalse();
-    assertThat(predicates.and(predicates.none(), predicates.all()).apply(javaFile)).isFalse();
-
-    // collection
-    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
-    assertThat(predicates.and(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isFalse();
-
-    // array
-    assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
-    assertThat(predicates.and(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void or() {
-    // empty
-    assertThat(predicates.or().apply(javaFile)).isTrue();
-    assertThat(predicates.or(new FilePredicate[0]).apply(javaFile)).isTrue();
-    assertThat(predicates.or(Collections.<FilePredicate>emptyList()).apply(javaFile)).isTrue();
-
-    // two arguments
-    assertThat(predicates.or(predicates.all(), predicates.all()).apply(javaFile)).isTrue();
-    assertThat(predicates.or(predicates.all(), predicates.none()).apply(javaFile)).isTrue();
-    assertThat(predicates.or(predicates.none(), predicates.all()).apply(javaFile)).isTrue();
-    assertThat(predicates.or(predicates.none(), predicates.none()).apply(javaFile)).isFalse();
-
-    // collection
-    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.all())).apply(javaFile)).isTrue();
-    assertThat(predicates.or(Arrays.asList(predicates.all(), predicates.none())).apply(javaFile)).isTrue();
-    assertThat(predicates.or(Arrays.asList(predicates.none(), predicates.none())).apply(javaFile)).isFalse();
-
-    // array
-    assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.all()}).apply(javaFile)).isTrue();
-    assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isTrue();
-    assertThat(predicates.or(new FilePredicate[] {predicates.none(), predicates.none()}).apply(javaFile)).isFalse();
-  }
-
-  @Test
-  public void hasFilename() {
-    assertThat(predicates.hasFilename("Action.java").apply(javaFile)).isTrue();
-  }
-
-  @Test
-  public void hasExtension() {
-    assertThat(predicates.hasExtension("java").apply(javaFile)).isTrue();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicateTest.java
deleted file mode 100644 (file)
index 0f60f6b..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.io.IOException;
-import org.junit.Test;
-import org.sonar.api.batch.fs.InputFile;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.impl.fs.predicates.FileExtensionPredicate.getExtension;
-
-public class FileExtensionPredicateTest {
-
-  @Test
-  public void should_match_correct_extension() throws IOException {
-    FileExtensionPredicate predicate = new FileExtensionPredicate("bat");
-    assertThat(predicate.apply(mockWithName("prog.bat"))).isTrue();
-    assertThat(predicate.apply(mockWithName("prog.bat.bat"))).isTrue();
-  }
-
-  @Test
-  public void should_not_match_incorrect_extension() throws IOException {
-    FileExtensionPredicate predicate = new FileExtensionPredicate("bat");
-    assertThat(predicate.apply(mockWithName("prog.batt"))).isFalse();
-    assertThat(predicate.apply(mockWithName("prog.abat"))).isFalse();
-    assertThat(predicate.apply(mockWithName("prog."))).isFalse();
-    assertThat(predicate.apply(mockWithName("prog.bat."))).isFalse();
-    assertThat(predicate.apply(mockWithName("prog.bat.batt"))).isFalse();
-    assertThat(predicate.apply(mockWithName("prog"))).isFalse();
-  }
-
-  @Test
-  public void should_match_correct_extension_case_insensitively() throws IOException {
-    FileExtensionPredicate predicate = new FileExtensionPredicate("jAVa");
-    assertThat(predicate.apply(mockWithName("Program.java"))).isTrue();
-    assertThat(predicate.apply(mockWithName("Program.JAVA"))).isTrue();
-    assertThat(predicate.apply(mockWithName("Program.Java"))).isTrue();
-    assertThat(predicate.apply(mockWithName("Program.JaVa"))).isTrue();
-  }
-
-  @Test
-  public void test_empty_extension() {
-    assertThat(getExtension("prog")).isEmpty();
-    assertThat(getExtension("prog.")).isEmpty();
-    assertThat(getExtension(".")).isEmpty();
-  }
-
-  private InputFile mockWithName(String filename) throws IOException {
-    InputFile inputFile = mock(InputFile.class);
-    when(inputFile.filename()).thenReturn(filename);
-    return inputFile;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FilenamePredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FilenamePredicateTest.java
deleted file mode 100644 (file)
index 052ff51..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import java.io.IOException;
-import java.util.Collections;
-import org.junit.Test;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class FilenamePredicateTest {
-  @Test
-  public void should_match_file_by_filename() throws IOException {
-    String filename = "some name";
-    InputFile inputFile = mock(InputFile.class);
-    when(inputFile.filename()).thenReturn(filename);
-
-    assertThat(new FilenamePredicate(filename).apply(inputFile)).isTrue();
-  }
-
-  @Test
-  public void should_not_match_file_by_different_filename() throws IOException {
-    String filename = "some name";
-    InputFile inputFile = mock(InputFile.class);
-    when(inputFile.filename()).thenReturn(filename + "x");
-
-    assertThat(new FilenamePredicate(filename).apply(inputFile)).isFalse();
-  }
-
-  @Test
-  public void should_find_matching_file_in_index() throws IOException {
-    String filename = "some name";
-    InputFile inputFile = mock(InputFile.class);
-    when(inputFile.filename()).thenReturn(filename);
-
-    FileSystem.Index index = mock(FileSystem.Index.class);
-    when(index.getFilesByName(filename)).thenReturn(Collections.singleton(inputFile));
-
-    assertThat(new FilenamePredicate(filename).get(index)).containsOnly(inputFile);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/OrPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/OrPredicateTest.java
deleted file mode 100644 (file)
index 489d636..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.junit.Test;
-import org.sonar.api.batch.fs.FilePredicate;
-
-import java.util.Arrays;
-import org.sonar.api.impl.fs.PathPattern;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class OrPredicateTest {
-
-  @Test
-  public void flattenNestedOr() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
-    PathPatternPredicate pathPatternPredicate3 = new PathPatternPredicate(PathPattern.create("foo3/**"));
-    FilePredicate orPredicate = OrPredicate.create(Arrays.asList(pathPatternPredicate1,
-      OrPredicate.create(Arrays.asList(pathPatternPredicate2, pathPatternPredicate3))));
-    assertThat(((OrPredicate) orPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2, pathPatternPredicate3);
-  }
-
-  @Test
-  public void simplifyOrExpressionsWhenEmpty() {
-    FilePredicate orPredicate = OrPredicate.create(Arrays.asList());
-    assertThat(orPredicate).isEqualTo(TruePredicate.TRUE);
-  }
-
-  @Test
-  public void simplifyOrExpressionsWhenFalse() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
-    FilePredicate andPredicate = OrPredicate.create(Arrays.asList(pathPatternPredicate1,
-      FalsePredicate.FALSE, pathPatternPredicate2));
-    assertThat(((OrPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2);
-  }
-
-  @Test
-  public void simplifyAndExpressionsWhenTrue() {
-    PathPatternPredicate pathPatternPredicate1 = new PathPatternPredicate(PathPattern.create("foo1/**"));
-    PathPatternPredicate pathPatternPredicate2 = new PathPatternPredicate(PathPattern.create("foo2/**"));
-    FilePredicate andPredicate = OrPredicate.create(Arrays.asList(pathPatternPredicate1,
-      TruePredicate.TRUE, pathPatternPredicate2));
-    assertThat(andPredicate).isEqualTo(TruePredicate.TRUE);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/RelativePathPredicateTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/RelativePathPredicateTest.java
deleted file mode 100644 (file)
index e7e2efd..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.fs.predicates;
-
-import org.junit.Test;
-import org.sonar.api.batch.fs.InputFile;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class RelativePathPredicateTest {
-  @Test
-  public void returns_false_when_path_is_invalid() {
-    RelativePathPredicate predicate = new RelativePathPredicate("..");
-    InputFile inputFile = mock(InputFile.class);
-    when(inputFile.relativePath()).thenReturn("path");
-    assertThat(predicate.apply(inputFile)).isFalse();
-  }
-
-  @Test
-  public void returns_true_if_matches() {
-    RelativePathPredicate predicate = new RelativePathPredicate("path");
-    InputFile inputFile = mock(InputFile.class);
-    when(inputFile.relativePath()).thenReturn("path");
-    assertThat(predicate.apply(inputFile)).isTrue();
-  }
-
-  @Test
-  public void returns_false_if_doesnt_match() {
-    RelativePathPredicate predicate = new RelativePathPredicate("path1");
-    InputFile inputFile = mock(InputFile.class);
-    when(inputFile.relativePath()).thenReturn("path2");
-    assertThat(predicate.apply(inputFile)).isFalse();
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/DefaultRulesTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/DefaultRulesTest.java
deleted file mode 100644 (file)
index c555516..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.rule;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.junit.Test;
-import org.sonar.api.batch.rule.NewRule;
-import org.sonar.api.impl.rule.DefaultRules;
-import org.sonar.api.rule.RuleKey;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultRulesTest {
-  @Test
-  public void testRepeatedInternalKey() {
-    List<NewRule> newRules = new LinkedList<>();
-    newRules.add(createRule("key1", "repo", "internal"));
-    newRules.add(createRule("key2", "repo", "internal"));
-    
-    DefaultRules rules = new DefaultRules(newRules);
-    assertThat(rules.findByInternalKey("repo", "internal")).hasSize(2);
-    assertThat(rules.find(RuleKey.of("repo", "key1"))).isNotNull();
-    assertThat(rules.find(RuleKey.of("repo", "key2"))).isNotNull();
-    assertThat(rules.findByRepository("repo")).hasSize(2);
-  }
-  
-  @Test
-  public void testNonExistingKey() {
-    List<NewRule> newRules = new LinkedList<>();
-    newRules.add(createRule("key1", "repo", "internal"));
-    newRules.add(createRule("key2", "repo", "internal"));
-    
-    DefaultRules rules = new DefaultRules(newRules);
-    assertThat(rules.findByInternalKey("xx", "xx")).hasSize(0);
-    assertThat(rules.find(RuleKey.of("xxx", "xx"))).isNull();
-    assertThat(rules.findByRepository("xxxx")).hasSize(0);
-  }
-  
-  @Test
-  public void testRepeatedRule() {
-    List<NewRule> newRules = new LinkedList<>();
-    newRules.add(createRule("key", "repo", "internal"));
-    newRules.add(createRule("key", "repo", "internal"));
-    
-    DefaultRules rules = new DefaultRules(newRules);
-    assertThat(rules.find(RuleKey.of("repo", "key"))).isNotNull();
-  }
-  
-  private NewRule createRule(String key, String repo, String internalKey) {
-    RuleKey ruleKey = RuleKey.of(repo, key);
-    NewRule newRule = new NewRule(ruleKey);
-    newRule.setInternalKey(internalKey);
-    
-    return newRule;
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/RulesBuilderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/RulesBuilderTest.java
deleted file mode 100644 (file)
index 1330f90..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.rule;
-
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.rule.NewRule;
-import org.sonar.api.batch.rule.Rule;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.impl.rule.RulesBuilder;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class RulesBuilderTest {
-  @org.junit.Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Test
-  public void no_rules() {
-    RulesBuilder builder = new RulesBuilder();
-    Rules rules = builder.build();
-    assertThat(rules.findAll()).isEmpty();
-  }
-
-  @Test
-  public void build_rules() {
-    RulesBuilder builder = new RulesBuilder();
-    NewRule newSquid1 = builder.add(RuleKey.of("squid", "S0001"));
-    newSquid1.setName("Detect bug");
-    newSquid1.setDescription("Detect potential bug");
-    newSquid1.setInternalKey("foo=bar");
-    newSquid1.setSeverity(org.sonar.api.rule.Severity.CRITICAL);
-    newSquid1.setStatus(RuleStatus.BETA);
-    newSquid1.addParam("min");
-    newSquid1.addParam("max").setDescription("Maximum");
-    // most simple rule
-    builder.add(RuleKey.of("squid", "S0002"));
-    builder.add(RuleKey.of("findbugs", "NPE"));
-
-    Rules rules = builder.build();
-
-    assertThat(rules.findAll()).hasSize(3);
-    assertThat(rules.findByRepository("squid")).hasSize(2);
-    assertThat(rules.findByRepository("findbugs")).hasSize(1);
-    assertThat(rules.findByRepository("unknown")).isEmpty();
-
-    Rule squid1 = rules.find(RuleKey.of("squid", "S0001"));
-    assertThat(squid1.key().repository()).isEqualTo("squid");
-    assertThat(squid1.key().rule()).isEqualTo("S0001");
-    assertThat(squid1.name()).isEqualTo("Detect bug");
-    assertThat(squid1.description()).isEqualTo("Detect potential bug");
-    assertThat(squid1.internalKey()).isEqualTo("foo=bar");
-    assertThat(squid1.status()).isEqualTo(RuleStatus.BETA);
-    assertThat(squid1.severity()).isEqualTo(org.sonar.api.rule.Severity.CRITICAL);
-    assertThat(squid1.params()).hasSize(2);
-    assertThat(squid1.param("min").key()).isEqualTo("min");
-    assertThat(squid1.param("min").description()).isNull();
-    assertThat(squid1.param("max").key()).isEqualTo("max");
-    assertThat(squid1.param("max").description()).isEqualTo("Maximum");
-
-    Rule squid2 = rules.find(RuleKey.of("squid", "S0002"));
-    assertThat(squid2.key().repository()).isEqualTo("squid");
-    assertThat(squid2.key().rule()).isEqualTo("S0002");
-    assertThat(squid2.description()).isNull();
-    assertThat(squid2.internalKey()).isNull();
-    assertThat(squid2.status()).isEqualTo(RuleStatus.defaultStatus());
-    assertThat(squid2.severity()).isEqualTo(Severity.defaultSeverity());
-    assertThat(squid2.params()).isEmpty();
-  }
-
-  @Test
-  public void fail_to_add_twice_the_same_rule() {
-    RulesBuilder builder = new RulesBuilder();
-    builder.add(RuleKey.of("squid", "S0001"));
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Rule 'squid:S0001' already exists");
-
-    builder.add(RuleKey.of("squid", "S0001"));
-  }
-
-  @Test
-  public void fail_to_add_twice_the_same_param() {
-    RulesBuilder builder = new RulesBuilder();
-    NewRule newRule = builder.add(RuleKey.of("squid", "S0001"));
-    newRule.addParam("min");
-    newRule.addParam("max");
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Parameter 'min' already exists on rule 'squid:S0001'");
-
-    newRule.addParam("min");
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAdHocRuleTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAdHocRuleTest.java
deleted file mode 100644 (file)
index fd766c2..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.rule.NewAdHocRule;
-import org.sonar.api.rules.RuleType;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DefaultAdHocRuleTest {
-
-  @Rule
-  public ExpectedException exception = ExpectedException.none();
-
-  @Test
-  public void store() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultAdHocRule rule = new DefaultAdHocRule(storage)
-      .engineId("engine")
-      .ruleId("ruleId")
-      .name("name")
-      .description("desc")
-      .severity(Severity.BLOCKER)
-      .type(RuleType.CODE_SMELL);
-      rule.save();
-
-    assertThat(rule.engineId()).isEqualTo("engine");
-    assertThat(rule.ruleId()).isEqualTo("ruleId");
-    assertThat(rule.name()).isEqualTo("name");
-    assertThat(rule.description()).isEqualTo("desc");
-    assertThat(rule.severity()).isEqualTo(Severity.BLOCKER);
-    assertThat(rule.type()).isEqualTo(RuleType.CODE_SMELL);
-
-    verify(storage).store(any(DefaultAdHocRule.class));
-  }
-
-
-  @Test
-  public void description_is_optional() {
-    SensorStorage storage = mock(SensorStorage.class);
-    new DefaultAdHocRule(storage)
-      .engineId("engine")
-      .ruleId("ruleId")
-      .name("name")
-      .severity(Severity.BLOCKER)
-      .type(RuleType.CODE_SMELL)
-      .save();
-
-    verify(storage).store(any(DefaultAdHocRule.class));
-  }
-
-  @Test
-  public void fail_to_store_if_no_engine_id() {
-    SensorStorage storage = mock(SensorStorage.class);
-    NewAdHocRule rule = new DefaultAdHocRule(storage)
-      .engineId(" ")
-      .ruleId("ruleId")
-      .name("name")
-      .description("desc")
-      .severity(Severity.BLOCKER)
-      .type(RuleType.CODE_SMELL);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Engine id is mandatory");
-    rule.save();
-  }
-
-  @Test
-  public void fail_to_store_if_no_rule_id() {
-    SensorStorage storage = mock(SensorStorage.class);
-    NewAdHocRule rule = new DefaultAdHocRule(storage)
-      .engineId("engine")
-      .ruleId("  ")
-      .name("name")
-      .description("desc")
-      .severity(Severity.BLOCKER)
-      .type(RuleType.CODE_SMELL);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Rule id is mandatory");
-    rule.save();
-  }
-
-  @Test
-  public void fail_to_store_if_no_name() {
-    SensorStorage storage = mock(SensorStorage.class);
-    NewAdHocRule rule = new DefaultAdHocRule(storage)
-      .engineId("engine")
-      .ruleId("ruleId")
-      .name("  ")
-      .description("desc")
-      .severity(Severity.BLOCKER)
-      .type(RuleType.CODE_SMELL);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Name is mandatory");
-    rule.save();
-  }
-
-
-  @Test
-  public void fail_to_store_if_no_severity() {
-    SensorStorage storage = mock(SensorStorage.class);
-    NewAdHocRule rule = new DefaultAdHocRule(storage)
-      .engineId("engine")
-      .ruleId("ruleId")
-      .name("name")
-      .description("desc")
-      .type(RuleType.CODE_SMELL);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Severity is mandatory");
-    rule.save();
-  }
-
-  @Test
-  public void fail_to_store_if_no_type() {
-    SensorStorage storage = mock(SensorStorage.class);
-    NewAdHocRule rule = new DefaultAdHocRule(storage)
-      .engineId("engine")
-      .ruleId("ruleId")
-      .name("name")
-      .description("desc")
-      .severity(Severity.BLOCKER);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Type is mandatory");
-    rule.save();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAnalysisErrorTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAnalysisErrorTest.java
deleted file mode 100644 (file)
index 9f6be9d..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextPointer;
-import org.sonar.api.batch.sensor.error.NewAnalysisError;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-public class DefaultAnalysisErrorTest {
-  private InputFile inputFile;
-  private SensorStorage storage;
-  private TextPointer textPointer;
-
-  @Rule
-  public ExpectedException exception = ExpectedException.none();
-
-  @Before
-  public void setUp() {
-    inputFile = new TestInputFileBuilder("module1", "src/File.java").build();
-    textPointer = new DefaultTextPointer(5, 2);
-    storage = mock(SensorStorage.class);
-  }
-
-  @Test
-  public void test_analysis_error() {
-    DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
-    analysisError.onFile(inputFile)
-      .at(textPointer)
-      .message("msg");
-
-    assertThat(analysisError.location()).isEqualTo(textPointer);
-    assertThat(analysisError.message()).isEqualTo("msg");
-    assertThat(analysisError.inputFile()).isEqualTo(inputFile);
-  }
-
-  @Test
-  public void test_save() {
-    DefaultAnalysisError analysisError = new DefaultAnalysisError(storage);
-    analysisError.onFile(inputFile).save();
-
-    verify(storage).store(analysisError);
-    verifyNoMoreInteractions(storage);
-  }
-
-  @Test
-  public void test_no_storage() {
-    exception.expect(NullPointerException.class);
-    DefaultAnalysisError analysisError = new DefaultAnalysisError();
-    analysisError.onFile(inputFile).save();
-  }
-
-  @Test
-  public void test_validation() {
-    try {
-      new DefaultAnalysisError(storage).onFile(null);
-      fail("Expected exception");
-    } catch (IllegalArgumentException e) {
-      // expected
-    }
-
-    NewAnalysisError error = new DefaultAnalysisError(storage).onFile(inputFile);
-    try {
-      error.onFile(inputFile);
-      fail("Expected exception");
-    } catch (IllegalStateException e) {
-      // expected
-    }
-
-    error = new DefaultAnalysisError(storage).at(textPointer);
-    try {
-      error.at(textPointer);
-      fail("Expected exception");
-    } catch (IllegalStateException e) {
-      // expected
-    }
-
-    try {
-      new DefaultAnalysisError(storage).save();
-      fail("Expected exception");
-    } catch (NullPointerException e) {
-      // expected
-    }
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultCpdTokensTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultCpdTokensTest.java
deleted file mode 100644 (file)
index fd2c60d..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.junit.Test;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-public class DefaultCpdTokensTest {
-  private final SensorStorage sensorStorage = mock(SensorStorage.class);
-
-  private final DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
-    .setLines(2)
-    .setOriginalLineStartOffsets(new int[] {0, 50})
-    .setOriginalLineEndOffsets(new int[] {49, 100})
-    .setLastValidOffset(101)
-    .build();
-
-  @Test
-  public void save_no_tokens() {
-    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
-      .onFile(inputFile);
-
-    tokens.save();
-
-    verify(sensorStorage).store(tokens);
-
-    assertThat(tokens.inputFile()).isEqualTo(inputFile);
-  }
-
-  @Test
-  public void save_one_token() {
-    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
-      .onFile(inputFile)
-      .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
-
-    tokens.save();
-
-    verify(sensorStorage).store(tokens);
-
-    assertThat(tokens.getTokenLines()).extracting("value", "startLine", "hashCode", "startUnit", "endUnit").containsExactly(tuple("foo", 1, "foo".hashCode(), 1, 1));
-  }
-
-  @Test
-  public void handle_exclusions() {
-    inputFile.setExcludedForDuplication(true);
-    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
-      .onFile(inputFile)
-      .addToken(inputFile.newRange(1, 2, 1, 5), "foo");
-
-    tokens.save();
-
-    verifyZeroInteractions(sensorStorage);
-
-    assertThat(tokens.getTokenLines()).isEmpty();
-  }
-
-  @Test
-  public void dont_save_for_test_files() {
-    DefaultInputFile testInputFile = new TestInputFileBuilder("foo", "src/Foo.java")
-      .setLines(2)
-      .setOriginalLineStartOffsets(new int[] {0, 50})
-      .setOriginalLineEndOffsets(new int[] {49, 100})
-      .setLastValidOffset(101)
-      .setType(InputFile.Type.TEST)
-      .build();
-
-    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
-      .onFile(testInputFile)
-      .addToken(testInputFile.newRange(1, 2, 1, 5), "foo");
-
-    tokens.save();
-    verifyZeroInteractions(sensorStorage);
-    assertThat(tokens.getTokenLines()).isEmpty();
-  }
-
-  @Test
-  public void save_many_tokens() {
-    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
-      .onFile(inputFile)
-      .addToken(inputFile.newRange(1, 2, 1, 5), "foo")
-      .addToken(inputFile.newRange(1, 6, 1, 10), "bar")
-      .addToken(inputFile.newRange(1, 20, 1, 25), "biz")
-      .addToken(inputFile.newRange(2, 1, 2, 10), "next");
-
-    tokens.save();
-
-    verify(sensorStorage).store(tokens);
-
-    assertThat(tokens.getTokenLines())
-      .extracting("value", "startLine", "hashCode", "startUnit", "endUnit")
-      .containsExactly(
-        tuple("foobarbiz", 1, "foobarbiz".hashCode(), 1, 3),
-        tuple("next", 2, "next".hashCode(), 4, 4));
-  }
-
-  @Test
-  public void basic_validation() {
-    SensorStorage sensorStorage = mock(SensorStorage.class);
-    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage);
-    try {
-      tokens.save();
-      fail("Expected exception");
-    } catch (Exception e) {
-      assertThat(e).hasMessage("Call onFile() first");
-    }
-    try {
-      tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
-      fail("Expected exception");
-    } catch (Exception e) {
-      assertThat(e).hasMessage("Call onFile() first");
-    }
-    try {
-      tokens.addToken(null, "foo");
-      fail("Expected exception");
-    } catch (Exception e) {
-      assertThat(e).hasMessage("Range should not be null");
-    }
-    try {
-      tokens.addToken(inputFile.newRange(1, 2, 1, 5), null);
-      fail("Expected exception");
-    } catch (Exception e) {
-      assertThat(e).hasMessage("Image should not be null");
-    }
-  }
-
-  @Test
-  public void validate_tokens_order() {
-    SensorStorage sensorStorage = mock(SensorStorage.class);
-    DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
-      .onFile(inputFile)
-      .addToken(inputFile.newRange(1, 6, 1, 10), "bar");
-
-    try {
-      tokens.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
-      fail("Expected exception");
-    } catch (Exception e) {
-      assertThat(e).hasMessage("Tokens of file src/Foo.java should be provided in order.\n" +
-        "Previous token: Range[from [line=1, lineOffset=6] to [line=1, lineOffset=10]]\n" +
-        "Last token: Range[from [line=1, lineOffset=2] to [line=1, lineOffset=5]]");
-    }
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultExternalIssueTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultExternalIssueTest.java
deleted file mode 100644 (file)
index 06ff406..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.io.IOException;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleType;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.issue.DefaultIssueLocation;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DefaultExternalIssueTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private DefaultInputProject project;
-
-  @Before
-  public void setup() throws IOException {
-    project = new DefaultInputProject(ProjectDefinition.create()
-      .setKey("foo")
-      .setBaseDir(temp.newFolder())
-      .setWorkDir(temp.newFolder()));
-  }
-
-  @Rule
-  public ExpectedException exception = ExpectedException.none();
-
-  private DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
-    .initMetadata("Foo\nBar\n")
-    .build();
-
-  @Test
-  public void build_file_issue() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(inputFile)
-        .at(inputFile.selectLine(1))
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .remediationEffortMinutes(10l)
-      .type(RuleType.BUG)
-      .severity(Severity.BLOCKER);
-
-    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(inputFile);
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("external_repo", "rule"));
-    assertThat(issue.engineId()).isEqualTo("repo");
-    assertThat(issue.ruleId()).isEqualTo("rule");
-    assertThat(issue.primaryLocation().textRange().start().line()).isEqualTo(1);
-    assertThat(issue.remediationEffort()).isEqualTo(10l);
-    assertThat(issue.type()).isEqualTo(RuleType.BUG);
-    assertThat(issue.severity()).isEqualTo(Severity.BLOCKER);
-    assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!");
-
-    issue.save();
-
-    verify(storage).store(issue);
-  }
-
-  @Test
-  public void fail_to_store_if_no_type() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(inputFile)
-        .at(inputFile.selectLine(1))
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .remediationEffortMinutes(10l)
-      .severity(Severity.BLOCKER);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Type is mandatory");
-    issue.save();
-  }
-
-  @Test
-  public void fail_to_store_if_primary_location_is_not_a_file() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(mock(InputComponent.class))
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .remediationEffortMinutes(10l)
-      .severity(Severity.BLOCKER);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("External issues must be located in files");
-    issue.save();
-  }
-
-  @Test
-  public void fail_to_store_if_primary_location_has_no_message() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(inputFile)
-        .at(inputFile.selectLine(1)))
-      .forRule(RuleKey.of("repo", "rule"))
-      .remediationEffortMinutes(10l)
-      .type(RuleType.BUG)
-      .severity(Severity.BLOCKER);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("External issues must have a message");
-    issue.save();
-  }
-
-  @Test
-  public void fail_to_store_if_no_severity() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultExternalIssue issue = new DefaultExternalIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(inputFile)
-        .at(inputFile.selectLine(1))
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .remediationEffortMinutes(10l)
-      .type(RuleType.BUG);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Severity is mandatory");
-    issue.save();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultHighlightingTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultHighlightingTest.java
deleted file mode 100644 (file)
index 99beb98..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.Collection;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.fs.DefaultTextRange;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.COMMENT;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.CPP_DOC;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.KEYWORD;
-
-public class DefaultHighlightingTest {
-
-  private static final InputFile INPUT_FILE = new TestInputFileBuilder("foo", "src/Foo.java")
-    .setLines(2)
-    .setOriginalLineStartOffsets(new int[] {0, 50})
-    .setOriginalLineEndOffsets(new int[] {49, 100})
-    .setLastValidOffset(101)
-    .build();
-
-  private Collection<SyntaxHighlightingRule> highlightingRules;
-
-  @Rule
-  public ExpectedException throwable = ExpectedException.none();
-
-  @Before
-  public void setUpSampleRules() {
-
-    DefaultHighlighting highlightingDataBuilder = new DefaultHighlighting(mock(SensorStorage.class))
-      .onFile(INPUT_FILE)
-      .highlight(0, 10, COMMENT)
-      .highlight(1, 10, 1, 12, KEYWORD)
-      .highlight(24, 38, KEYWORD)
-      .highlight(42, 50, KEYWORD)
-      .highlight(24, 65, CPP_DOC)
-      .highlight(12, 20, COMMENT);
-
-    highlightingDataBuilder.save();
-
-    highlightingRules = highlightingDataBuilder.getSyntaxHighlightingRuleSet();
-  }
-
-  @Test
-  public void should_register_highlighting_rule() {
-    assertThat(highlightingRules).hasSize(6);
-  }
-
-  private static TextRange rangeOf(int startLine, int startOffset, int endLine, int endOffset) {
-    return new DefaultTextRange(new DefaultTextPointer(startLine, startOffset), new DefaultTextPointer(endLine, endOffset));
-  }
-
-  @Test
-  public void should_order_by_start_then_end_offset() {
-    assertThat(highlightingRules).extracting("range", TextRange.class).containsExactly(
-      rangeOf(1, 0, 1, 10),
-      rangeOf(1, 10, 1, 12),
-      rangeOf(1, 12, 1, 20),
-      rangeOf(1, 24, 2, 15),
-      rangeOf(1, 24, 1, 38),
-      rangeOf(1, 42, 2, 0));
-    assertThat(highlightingRules).extracting("textType").containsExactly(COMMENT, KEYWORD, COMMENT, CPP_DOC, KEYWORD, KEYWORD);
-  }
-
-  @Test
-  public void should_support_overlapping() {
-    new DefaultHighlighting(mock(SensorStorage.class))
-      .onFile(INPUT_FILE)
-      .highlight(0, 15, KEYWORD)
-      .highlight(8, 12, CPP_DOC)
-      .save();
-  }
-
-  @Test
-  public void should_prevent_start_equal_end() {
-    throwable.expect(IllegalArgumentException.class);
-    throwable
-      .expectMessage("Unable to highlight file");
-
-    new DefaultHighlighting(mock(SensorStorage.class))
-      .onFile(INPUT_FILE)
-      .highlight(10, 10, KEYWORD)
-      .save();
-  }
-
-  @Test
-  public void should_prevent_boudaries_overlapping() {
-    throwable.expect(IllegalStateException.class);
-    throwable
-      .expectMessage("Cannot register highlighting rule for characters at Range[from [line=1, lineOffset=8] to [line=1, lineOffset=15]] as it overlaps at least one existing rule");
-
-    new DefaultHighlighting(mock(SensorStorage.class))
-      .onFile(INPUT_FILE)
-      .highlight(0, 10, KEYWORD)
-      .highlight(8, 15, KEYWORD)
-      .save();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueLocationTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueLocationTest.java
deleted file mode 100644 (file)
index 540a0bb..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.apache.commons.lang.StringUtils;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.issue.DefaultIssueLocation;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.rules.ExpectedException.none;
-
-public class DefaultIssueLocationTest {
-
-  @Rule
-  public ExpectedException thrown = none();
-
-  private InputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
-    .initMetadata("Foo\nBar\n")
-    .build();
-
-  @Test
-  public void should_build() {
-    assertThat(new DefaultIssueLocation()
-      .on(inputFile)
-      .message("pipo bimbo")
-      .message()
-    ).isEqualTo("pipo bimbo");
-  }
-
-  @Test
-  public void not_allowed_to_call_on_twice() {
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("on() already called");
-    new DefaultIssueLocation()
-      .on(inputFile)
-      .on(inputFile)
-      .message("Wrong way!");
-  }
-
-  @Test
-  public void prevent_too_long_messages() {
-    assertThat(new DefaultIssueLocation()
-      .on(inputFile)
-      .message(StringUtils.repeat("a", 4000)).message()).hasSize(4000);
-
-    assertThat(new DefaultIssueLocation()
-      .on(inputFile)
-      .message(StringUtils.repeat("a", 4001)).message()).hasSize(4000);
-  }
-
-  @Test
-  public void prevent_null_character_in_message_text() {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage("Character \\u0000 is not supported in issue message");
-
-    new DefaultIssueLocation()
-      .message("pipo " + '\u0000' + " bimbo");
-  }
-
-  @Test
-  public void prevent_null_character_in_message_text_when_builder_has_been_initialized() {
-    thrown.expect(IllegalArgumentException.class);
-    thrown.expectMessage(customMatcher("Character \\u0000 is not supported in issue message", ", on component: src/Foo.php"));
-
-    new DefaultIssueLocation()
-      .on(inputFile)
-      .message("pipo " + '\u0000' + " bimbo");
-  }
-
-  private Matcher<String> customMatcher(String startWith, String endWith) {
-    return new TypeSafeMatcher<String>() {
-      @Override
-      public void describeTo(Description description) {
-        description.appendText("Invalid message");
-      }
-
-      @Override
-      protected boolean matchesSafely(final String item) {
-        return item.startsWith(startWith) && item.endsWith(endWith);
-      }
-    };
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueTest.java
deleted file mode 100644 (file)
index f88a099..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.impl.fs.DefaultInputDir;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.issue.DefaultIssue;
-import org.sonar.api.impl.issue.DefaultIssueLocation;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DefaultIssueTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private DefaultInputProject project;
-
-  private DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
-    .initMetadata("Foo\nBar\n")
-    .build();
-
-  @Before
-  public void prepare() throws IOException {
-    project = new DefaultInputProject(ProjectDefinition.create()
-      .setKey("foo")
-      .setBaseDir(temp.newFolder())
-      .setWorkDir(temp.newFolder()));
-  }
-
-  @Test
-  public void build_file_issue() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultIssue issue = new DefaultIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(inputFile)
-        .at(inputFile.selectLine(1))
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .gap(10.0);
-
-    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(inputFile);
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
-    assertThat(issue.primaryLocation().textRange().start().line()).isEqualTo(1);
-    assertThat(issue.gap()).isEqualTo(10.0);
-    assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!");
-
-    issue.save();
-
-    verify(storage).store(issue);
-  }
-
-  @Test
-  public void move_directory_issue_to_project_root() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultIssue issue = new DefaultIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(new DefaultInputDir("foo", "src/main").setModuleBaseDir(project.getBaseDir()))
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .overrideSeverity(Severity.BLOCKER);
-
-    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(project);
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
-    assertThat(issue.primaryLocation().textRange()).isNull();
-    assertThat(issue.primaryLocation().message()).isEqualTo("[src/main] Wrong way!");
-    assertThat(issue.overriddenSeverity()).isEqualTo(Severity.BLOCKER);
-
-    issue.save();
-
-    verify(storage).store(issue);
-  }
-
-  @Test
-  public void move_submodule_issue_to_project_root() {
-    File subModuleDirectory = new File(project.getBaseDir().toString(), "bar");
-    subModuleDirectory.mkdir();
-
-    ProjectDefinition subModuleDefinition = ProjectDefinition.create()
-      .setKey("foo/bar")
-      .setBaseDir(subModuleDirectory)
-      .setWorkDir(subModuleDirectory);
-    project.definition().addSubProject(subModuleDefinition);
-    DefaultInputModule subModule = new DefaultInputModule(subModuleDefinition);
-
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultIssue issue = new DefaultIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(subModule)
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .overrideSeverity(Severity.BLOCKER);
-
-    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(project);
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
-    assertThat(issue.primaryLocation().textRange()).isNull();
-    assertThat(issue.primaryLocation().message()).isEqualTo("[bar] Wrong way!");
-    assertThat(issue.overriddenSeverity()).isEqualTo(Severity.BLOCKER);
-
-    issue.save();
-
-    verify(storage).store(issue);
-  }
-
-  @Test
-  public void build_project_issue() throws IOException {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultInputModule inputModule = new DefaultInputModule(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()));
-    DefaultIssue issue = new DefaultIssue(project, storage)
-      .at(new DefaultIssueLocation()
-        .on(inputModule)
-        .message("Wrong way!"))
-      .forRule(RuleKey.of("repo", "rule"))
-      .gap(10.0);
-
-    assertThat(issue.primaryLocation().inputComponent()).isEqualTo(inputModule);
-    assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
-    assertThat(issue.primaryLocation().textRange()).isNull();
-    assertThat(issue.gap()).isEqualTo(10.0);
-    assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!");
-
-    issue.save();
-
-    verify(storage).store(issue);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultMeasureTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultMeasureTest.java
deleted file mode 100644 (file)
index 0c7ece2..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.io.IOException;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.impl.fs.AbstractProjectOrModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DefaultMeasureTest {
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void build_file_measure() {
-    SensorStorage storage = mock(SensorStorage.class);
-    DefaultMeasure<Integer> newMeasure = new DefaultMeasure<Integer>(storage)
-      .forMetric(CoreMetrics.LINES)
-      .on(new TestInputFileBuilder("foo", "src/Foo.php").build())
-      .withValue(3);
-
-    assertThat(newMeasure.inputComponent()).isEqualTo(new TestInputFileBuilder("foo", "src/Foo.php").build());
-    assertThat(newMeasure.metric()).isEqualTo(CoreMetrics.LINES);
-    assertThat(newMeasure.value()).isEqualTo(3);
-
-    newMeasure.save();
-
-    verify(storage).store(newMeasure);
-  }
-
-  @Test
-  public void build_project_measure() throws IOException {
-    SensorStorage storage = mock(SensorStorage.class);
-    AbstractProjectOrModule module = new DefaultInputProject(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()));
-    DefaultMeasure<Integer> newMeasure = new DefaultMeasure<Integer>(storage)
-      .forMetric(CoreMetrics.LINES)
-      .on(module)
-      .withValue(3);
-
-    assertThat(newMeasure.inputComponent()).isEqualTo(module);
-    assertThat(newMeasure.metric()).isEqualTo(CoreMetrics.LINES);
-    assertThat(newMeasure.value()).isEqualTo(3);
-
-    newMeasure.save();
-
-    verify(storage).store(newMeasure);
-  }
-
-  @Test
-  public void not_allowed_to_call_on_twice() throws IOException {
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("on() already called");
-    new DefaultMeasure<Integer>()
-      .on(new DefaultInputProject(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder())))
-      .on(new TestInputFileBuilder("foo", "src/Foo.php").build())
-      .withValue(3)
-      .save();
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSensorDescriptorTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSensorDescriptorTest.java
deleted file mode 100644 (file)
index b09b5ed..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.junit.Test;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.config.MapSettings;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultSensorDescriptorTest {
-
-  @Test
-  public void describe() {
-    DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor();
-    descriptor
-      .name("Foo")
-      .onlyOnLanguage("java")
-      .onlyOnFileType(InputFile.Type.MAIN)
-      .requireProperty("sonar.foo.reportPath", "sonar.foo.reportPath2")
-      .createIssuesForRuleRepository("squid-java");
-
-    assertThat(descriptor.name()).isEqualTo("Foo");
-    assertThat(descriptor.languages()).containsOnly("java");
-    assertThat(descriptor.type()).isEqualTo(InputFile.Type.MAIN);
-    MapSettings settings = new MapSettings();
-    settings.setProperty("sonar.foo.reportPath", "foo");
-    assertThat(descriptor.configurationPredicate().test(settings.asConfig())).isFalse();
-    settings.setProperty("sonar.foo.reportPath2", "foo");
-    assertThat(descriptor.configurationPredicate().test(settings.asConfig())).isTrue();
-    assertThat(descriptor.ruleRepositories()).containsOnly("squid-java");
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSignificantCodeTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSignificantCodeTest.java
deleted file mode 100644 (file)
index f6d7f45..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DefaultSignificantCodeTest {
-  private SensorStorage sensorStorage = mock(SensorStorage.class);
-  private DefaultSignificantCode underTest = new DefaultSignificantCode(sensorStorage);
-  private InputFile inputFile = TestInputFileBuilder.create("module", "file1.xoo")
-    .setContents("this is\na file\n with some code")
-    .build();
-
-  @Rule
-  public ExpectedException exception = ExpectedException.none();
-
-  @Test
-  public void should_save_ranges() {
-    underTest.onFile(inputFile)
-      .addRange(inputFile.selectLine(1))
-      .save();
-    verify(sensorStorage).store(underTest);
-  }
-
-  @Test
-  public void fail_if_save_without_file() {
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Call onFile() first");
-    underTest.save();
-  }
-
-  @Test
-  public void fail_if_add_range_to_same_line_twice() {
-    underTest.onFile(inputFile);
-    underTest.addRange(inputFile.selectLine(1));
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("Significant code was already reported for line '1'.");
-    underTest.addRange(inputFile.selectLine(1));
-  }
-
-  @Test
-  public void fail_if_range_includes_many_lines() {
-    underTest.onFile(inputFile);
-
-    exception.expect(IllegalArgumentException.class);
-    exception.expectMessage("Ranges of significant code must be located in a single line");
-    underTest.addRange(inputFile.newRange(1, 1, 2, 1));
-  }
-
-  @Test
-  public void fail_if_add_range_before_setting_file() {
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("addRange() should be called after on()");
-    underTest.addRange(inputFile.selectLine(1));
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSymbolTableTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSymbolTableTest.java
deleted file mode 100644 (file)
index affd87b..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.util.Map;
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.TextRange;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class DefaultSymbolTableTest {
-
-  private static final InputFile INPUT_FILE = new TestInputFileBuilder("foo", "src/Foo.java")
-    .setLines(2)
-    .setOriginalLineStartOffsets(new int[] {0, 50})
-    .setOriginalLineEndOffsets(new int[] {49, 100})
-    .setLastValidOffset(101)
-    .build();
-
-  private Map<TextRange, Set<TextRange>> referencesPerSymbol;
-
-  @Rule
-  public ExpectedException throwable = ExpectedException.none();
-
-  @Before
-  public void setUpSampleSymbols() {
-
-    DefaultSymbolTable symbolTableBuilder = new DefaultSymbolTable(mock(SensorStorage.class))
-      .onFile(INPUT_FILE);
-    symbolTableBuilder
-      .newSymbol(0, 10)
-      .newReference(12, 15)
-      .newReference(2, 10, 2, 15);
-
-    symbolTableBuilder.newSymbol(1, 12, 1, 15).newReference(52, 55);
-
-    symbolTableBuilder.save();
-
-    referencesPerSymbol = symbolTableBuilder.getReferencesBySymbol();
-  }
-
-  @Test
-  public void should_register_symbols() {
-    assertThat(referencesPerSymbol).hasSize(2);
-  }
-
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/InMemorySensorStorageTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/InMemorySensorStorageTest.java
deleted file mode 100644 (file)
index 25b44f5..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.sensor.InMemorySensorStorage;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.data.MapEntry.entry;
-
-public class InMemorySensorStorageTest {
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  InMemorySensorStorage underTest = new InMemorySensorStorage();
-
-  @Test
-  public void test_storeProperty() {
-    assertThat(underTest.contextProperties).isEmpty();
-
-    underTest.storeProperty("foo", "bar");
-    assertThat(underTest.contextProperties).containsOnly(entry("foo", "bar"));
-  }
-
-  @Test
-  public void storeProperty_throws_IAE_if_key_is_null() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Key of context property must not be null");
-
-    underTest.storeProperty(null, "bar");
-  }
-
-  @Test
-  public void storeProperty_throws_IAE_if_value_is_null() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Value of context property must not be null");
-
-    underTest.storeProperty("foo", null);
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/SensorContextTesterTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/SensorContextTesterTest.java
deleted file mode 100644 (file)
index 9684c7c..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.impl.sensor;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
-import org.sonar.api.batch.rule.NewActiveRule;
-import org.sonar.api.batch.rule.Severity;
-import org.sonar.api.batch.sensor.error.AnalysisError;
-import org.sonar.api.batch.sensor.error.NewAnalysisError;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.batch.sensor.issue.NewExternalIssue;
-import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
-import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleType;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-import static org.assertj.core.data.MapEntry.entry;
-
-public class SensorContextTesterTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public ExpectedException exception = ExpectedException.none();
-
-  private SensorContextTester tester;
-  private File baseDir;
-
-  @Before
-  public void prepare() throws Exception {
-    baseDir = temp.newFolder();
-    tester = SensorContextTester.create(baseDir);
-  }
-
-  @Test
-  public void testSettings() {
-    Settings settings = new MapSettings();
-    settings.setProperty("foo", "bar");
-    tester.setSettings(settings);
-    assertThat(tester.settings().getString("foo")).isEqualTo("bar");
-  }
-
-  @Test
-  public void testActiveRules() {
-    NewActiveRule activeRule = new NewActiveRule.Builder()
-      .setRuleKey(RuleKey.of("foo", "bar"))
-      .build();
-    ActiveRules activeRules = new ActiveRulesBuilder().addRule(activeRule).build();
-    tester.setActiveRules(activeRules);
-    assertThat(tester.activeRules().findAll()).hasSize(1);
-  }
-
-  @Test
-  public void testFs() throws Exception {
-    DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder());
-    tester.setFileSystem(fs);
-    assertThat(tester.fileSystem().baseDir()).isNotEqualTo(baseDir);
-  }
-
-  @Test
-  public void testIssues() {
-    assertThat(tester.allIssues()).isEmpty();
-    NewIssue newIssue = tester.newIssue();
-    newIssue
-      .at(newIssue.newLocation().on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
-      .forRule(RuleKey.of("repo", "rule"))
-      .save();
-    newIssue = tester.newIssue();
-    newIssue
-      .at(newIssue.newLocation().on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
-      .forRule(RuleKey.of("repo", "rule"))
-      .save();
-    assertThat(tester.allIssues()).hasSize(2);
-  }
-
-  @Test
-  public void testExternalIssues() {
-    assertThat(tester.allExternalIssues()).isEmpty();
-    NewExternalIssue newExternalIssue = tester.newExternalIssue();
-    newExternalIssue
-      .at(newExternalIssue.newLocation().message("message").on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
-      .forRule(RuleKey.of("repo", "rule"))
-      .type(RuleType.BUG)
-      .severity(Severity.BLOCKER)
-      .save();
-    newExternalIssue = tester.newExternalIssue();
-    newExternalIssue
-      .at(newExternalIssue.newLocation().message("message").on(new TestInputFileBuilder("foo", "src/Foo.java").build()))
-      .type(RuleType.BUG)
-      .severity(Severity.BLOCKER)
-      .forRule(RuleKey.of("repo", "rule"))
-      .save();
-    assertThat(tester.allExternalIssues()).hasSize(2);
-  }
-
-  @Test
-  public void testAnalysisErrors() {
-    assertThat(tester.allAnalysisErrors()).isEmpty();
-    NewAnalysisError newAnalysisError = tester.newAnalysisError();
-
-    InputFile file = new TestInputFileBuilder("foo", "src/Foo.java").build();
-    newAnalysisError.onFile(file)
-      .message("error")
-      .at(new DefaultTextPointer(5, 2))
-      .save();
-
-    assertThat(tester.allAnalysisErrors()).hasSize(1);
-    AnalysisError analysisError = tester.allAnalysisErrors().iterator().next();
-
-    assertThat(analysisError.inputFile()).isEqualTo(file);
-    assertThat(analysisError.message()).isEqualTo("error");
-    assertThat(analysisError.location()).isEqualTo(new DefaultTextPointer(5, 2));
-
-  }
-
-  @Test
-  public void testMeasures() throws IOException {
-    assertThat(tester.measures("foo:src/Foo.java")).isEmpty();
-    assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNull();
-    tester.<Integer>newMeasure()
-      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
-      .forMetric(CoreMetrics.NCLOC)
-      .withValue(2)
-      .save();
-    assertThat(tester.measures("foo:src/Foo.java")).hasSize(1);
-    assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNotNull();
-    tester.<Integer>newMeasure()
-      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
-      .forMetric(CoreMetrics.LINES)
-      .withValue(4)
-      .save();
-    assertThat(tester.measures("foo:src/Foo.java")).hasSize(2);
-    assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNotNull();
-    assertThat(tester.measure("foo:src/Foo.java", "lines")).isNotNull();
-    tester.<Integer>newMeasure()
-      .on(new DefaultInputModule(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder())))
-      .forMetric(CoreMetrics.DIRECTORIES)
-      .withValue(4)
-      .save();
-    assertThat(tester.measures("foo")).hasSize(1);
-    assertThat(tester.measure("foo", "directories")).isNotNull();
-  }
-
-  @Test(expected = IllegalStateException.class)
-  public void duplicateMeasures() {
-    tester.<Integer>newMeasure()
-      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
-      .forMetric(CoreMetrics.NCLOC)
-      .withValue(2)
-      .save();
-    tester.<Integer>newMeasure()
-      .on(new TestInputFileBuilder("foo", "src/Foo.java").build())
-      .forMetric(CoreMetrics.NCLOC)
-      .withValue(2)
-      .save();
-  }
-
-  @Test
-  public void testHighlighting() {
-    assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 3)).isEmpty();
-    tester.newHighlighting()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
-      .highlight(1, 0, 1, 5, TypeOfText.ANNOTATION)
-      .highlight(8, 10, TypeOfText.CONSTANT)
-      .highlight(9, 10, TypeOfText.COMMENT)
-      .save();
-    assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 3)).containsExactly(TypeOfText.ANNOTATION);
-    assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 9)).containsExactly(TypeOfText.CONSTANT, TypeOfText.COMMENT);
-  }
-
-  @Test(expected = UnsupportedOperationException.class)
-  public void duplicateHighlighting() {
-    tester.newHighlighting()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
-      .highlight(1, 0, 1, 5, TypeOfText.ANNOTATION)
-      .save();
-    tester.newHighlighting()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
-      .highlight(1, 0, 1, 5, TypeOfText.ANNOTATION)
-      .save();
-  }
-
-  @Test
-  public void testSymbolReferences() {
-    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 0)).isNull();
-
-    NewSymbolTable symbolTable = tester.newSymbolTable()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build());
-    symbolTable
-      .newSymbol(1, 8, 1, 10);
-
-    symbolTable
-      .newSymbol(1, 1, 1, 5)
-      .newReference(6, 9)
-      .newReference(1, 10, 1, 13);
-
-    symbolTable.save();
-
-    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 0)).isNull();
-    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 8)).isEmpty();
-    assertThat(tester.referencesForSymbolAt("foo:src/Foo.java", 1, 3)).extracting("start.line", "start.lineOffset", "end.line", "end.lineOffset").containsExactly(tuple(1, 6, 1, 9),
-      tuple(1, 10, 1, 13));
-  }
-
-  @Test(expected = UnsupportedOperationException.class)
-  public void duplicateSymbolReferences() {
-    NewSymbolTable symbolTable = tester.newSymbolTable()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build());
-    symbolTable
-      .newSymbol(1, 8, 1, 10);
-
-    symbolTable.save();
-
-    symbolTable = tester.newSymbolTable()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build());
-    symbolTable
-      .newSymbol(1, 8, 1, 10);
-
-    symbolTable.save();
-  }
-
-  @Test
-  public void testCoverageAtLineZero() {
-    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isNull();
-    assertThat(tester.lineHits("foo:src/Foo.java", 4)).isNull();
-
-    exception.expect(IllegalStateException.class);
-    tester.newCoverage()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
-      .lineHits(0, 3);
-  }
-
-  @Test
-  public void testCoverageAtLineOutOfRange() {
-    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isNull();
-    assertThat(tester.lineHits("foo:src/Foo.java", 4)).isNull();
-    exception.expect(IllegalStateException.class);
-
-    tester.newCoverage()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar").build())
-      .lineHits(4, 3);
-  }
-
-  @Test
-  public void testLineHits() {
-    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isNull();
-    assertThat(tester.lineHits("foo:src/Foo.java", 4)).isNull();
-    tester.newCoverage()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar\nasdas").build())
-      .lineHits(1, 2)
-      .lineHits(2, 3)
-      .save();
-    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isEqualTo(2);
-    assertThat(tester.lineHits("foo:src/Foo.java", 2)).isEqualTo(3);
-  }
-
-  public void multipleCoverage() {
-    tester.newCoverage()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar\nasdas").build())
-      .lineHits(1, 2)
-      .conditions(3, 4, 2)
-      .save();
-    tester.newCoverage()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java").initMetadata("annot dsf fds foo bar\nasdas").build())
-      .lineHits(1, 2)
-      .conditions(3, 4, 3)
-      .save();
-    assertThat(tester.lineHits("foo:src/Foo.java", 1)).isEqualTo(4);
-    assertThat(tester.conditions("foo:src/Foo.java", 3)).isEqualTo(4);
-    assertThat(tester.coveredConditions("foo:src/Foo.java", 3)).isEqualTo(3);
-  }
-
-  @Test
-  public void testConditions() {
-    assertThat(tester.conditions("foo:src/Foo.java", 1)).isNull();
-    assertThat(tester.coveredConditions("foo:src/Foo.java", 1)).isNull();
-    tester.newCoverage()
-      .onFile(new TestInputFileBuilder("foo", "src/Foo.java")
-        .initMetadata("annot dsf fds foo bar\nasd\nasdas\nasdfas")
-        .build())
-      .conditions(1, 4, 2)
-      .save();
-    assertThat(tester.conditions("foo:src/Foo.java", 1)).isEqualTo(4);
-    assertThat(tester.coveredConditions("foo:src/Foo.java", 1)).isEqualTo(2);
-  }
-
-  @Test
-  public void testCpdTokens() {
-    assertThat(tester.cpdTokens("foo:src/Foo.java")).isNull();
-    DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
-      .initMetadata("public class Foo {\n\n}")
-      .build();
-    tester.newCpdTokens()
-      .onFile(inputFile)
-      .addToken(inputFile.newRange(0, 6), "public")
-      .addToken(inputFile.newRange(7, 12), "class")
-      .addToken(inputFile.newRange(13, 16), "$IDENTIFIER")
-      .addToken(inputFile.newRange(17, 18), "{")
-      .addToken(inputFile.newRange(3, 0, 3, 1), "}")
-      .save();
-    assertThat(tester.cpdTokens("foo:src/Foo.java")).extracting("value", "startLine", "startUnit", "endUnit")
-      .containsExactly(
-        tuple("publicclass$IDENTIFIER{", 1, 1, 4),
-        tuple("}", 3, 5, 5));
-  }
-
-  @Test(expected = UnsupportedOperationException.class)
-  public void duplicateCpdTokens() {
-    DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
-      .initMetadata("public class Foo {\n\n}")
-      .build();
-    tester.newCpdTokens()
-      .onFile(inputFile)
-      .addToken(inputFile.newRange(0, 6), "public")
-      .save();
-
-    tester.newCpdTokens()
-      .onFile(inputFile)
-      .addToken(inputFile.newRange(0, 6), "public")
-      .save();
-  }
-
-  @Test
-  public void testCancellation() {
-    assertThat(tester.isCancelled()).isFalse();
-    tester.setCancelled(true);
-    assertThat(tester.isCancelled()).isTrue();
-  }
-
-  @Test
-  public void testContextProperties() {
-    assertThat(tester.getContextProperties()).isEmpty();
-
-    tester.addContextProperty("foo", "bar");
-    assertThat(tester.getContextProperties()).containsOnly(entry("foo", "bar"));
-  }
-}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/internal/MetadataLoaderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/internal/MetadataLoaderTest.java
new file mode 100644 (file)
index 0000000..d62ebdc
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.internal;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import org.sonar.api.SonarEdition;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.Version;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class MetadataLoaderTest {
+  private System2 system = mock(System2.class);
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void load_version_from_file_in_classpath() {
+    Version version = MetadataLoader.loadVersion(System2.INSTANCE);
+    assertThat(version).isNotNull();
+    assertThat(version.major()).isGreaterThanOrEqualTo(5);
+  }
+
+  @Test
+  public void load_edition_from_file_in_classpath() {
+    SonarEdition edition = MetadataLoader.loadEdition(System2.INSTANCE);
+    assertThat(edition).isNotNull();
+  }
+
+  @Test
+  public void load_edition_defaults_to_community_if_file_not_found() throws MalformedURLException {
+    when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL());
+    SonarEdition edition = MetadataLoader.loadEdition(System2.INSTANCE);
+    assertThat(edition).isEqualTo(SonarEdition.COMMUNITY);
+  }
+
+  @Test
+  public void throw_ISE_if_edition_is_invalid() {
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Invalid edition found in '/sonar-edition.txt': 'TRASH'");
+
+    MetadataLoader.parseEdition("trash");
+  }
+
+  @Test
+  public void throw_ISE_if_fail_to_load_version() throws Exception {
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Can not load /sonar-api-version.txt from classpath");
+
+    when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL());
+    MetadataLoader.loadVersion(system);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java
new file mode 100644 (file)
index 0000000..8e439af
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.internal;
+
+import org.sonar.api.SonarEdition;
+import org.assertj.core.api.Assertions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.SonarProduct;
+import org.sonar.api.SonarQubeSide;
+import org.sonar.api.SonarRuntime;
+import org.sonar.api.utils.Version;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SonarRuntimeImplTest {
+
+  private static final Version A_VERSION = Version.parse("6.0");
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void sonarQube_environment() {
+    SonarRuntime apiVersion = SonarRuntimeImpl.forSonarQube(A_VERSION, SonarQubeSide.SCANNER, SonarEdition.COMMUNITY);
+    assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION);
+    assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARQUBE);
+    assertThat(apiVersion.getSonarQubeSide()).isEqualTo(SonarQubeSide.SCANNER);
+  }
+
+  @Test
+  public void sonarLint_environment() {
+    SonarRuntime apiVersion = SonarRuntimeImpl.forSonarLint(A_VERSION);
+    assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION);
+    assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARLINT);
+    try {
+      apiVersion.getSonarQubeSide();
+      Assertions.fail("Expected exception");
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(UnsupportedOperationException.class);
+    }
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void sonarqube_requires_side() {
+    SonarRuntimeImpl.forSonarQube(A_VERSION, null, null);
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/resources/org/sonar/api/batch/fs/internal/fs/glyphicons-halflings-regular.woff b/sonar-plugin-api-impl/src/test/resources/org/sonar/api/batch/fs/internal/fs/glyphicons-halflings-regular.woff
new file mode 100644 (file)
index 0000000..2cc3e48
Binary files /dev/null and b/sonar-plugin-api-impl/src/test/resources/org/sonar/api/batch/fs/internal/fs/glyphicons-halflings-regular.woff differ
diff --git a/sonar-plugin-api-impl/src/test/resources/org/sonar/api/impl/fs/glyphicons-halflings-regular.woff b/sonar-plugin-api-impl/src/test/resources/org/sonar/api/impl/fs/glyphicons-halflings-regular.woff
deleted file mode 100644 (file)
index 2cc3e48..0000000
Binary files a/sonar-plugin-api-impl/src/test/resources/org/sonar/api/impl/fs/glyphicons-halflings-regular.woff and /dev/null differ
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java
deleted file mode 100644 (file)
index 6f14a13..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.batch.rule;
-
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
-
-/**
- * @since 4.2
- */
-@Immutable
-public class NewActiveRule {
-  final RuleKey ruleKey;
-  final String name;
-  final String severity;
-  final Map<String, String> params;
-  final long createdAt;
-  final long updatedAt;
-  final String internalKey;
-  final String language;
-  final String templateRuleKey;
-  final String qProfileKey;
-
-  NewActiveRule(Builder builder) {
-    this.ruleKey = builder.ruleKey;
-    this.name = builder.name;
-    this.severity = builder.severity;
-    this.params = builder.params;
-    this.createdAt = builder.createdAt;
-    this.updatedAt = builder.updatedAt;
-    this.internalKey = builder.internalKey;
-    this.language = builder.language;
-    this.templateRuleKey = builder.templateRuleKey;
-    this.qProfileKey = builder.qProfileKey;
-  }
-
-  public RuleKey ruleKey() {
-    return this.ruleKey;
-  }
-
-  public static class Builder {
-    private RuleKey ruleKey;
-    private String name;
-    private String severity = Severity.defaultSeverity();
-    private Map<String, String> params = new HashMap<>();
-    private long createdAt;
-    private long updatedAt;
-    private String internalKey;
-    private String language;
-    private String templateRuleKey;
-    private String qProfileKey;
-
-    public Builder setRuleKey(RuleKey ruleKey) {
-      this.ruleKey = ruleKey;
-      return this;
-    }
-
-    public Builder setName(String name) {
-      this.name = name;
-      return this;
-    }
-
-    public Builder setSeverity(@Nullable String severity) {
-      this.severity = StringUtils.defaultIfBlank(severity, Severity.defaultSeverity());
-      return this;
-    }
-
-    public Builder setParam(String key, @Nullable String value) {
-      // possible improvement : check that the param key exists in rule definition
-      if (value == null) {
-        params.remove(key);
-      } else {
-        params.put(key, value);
-      }
-      return this;
-    }
-
-    public Builder setCreatedAt(long createdAt) {
-      this.createdAt = createdAt;
-      return this;
-    }
-
-    public Builder setUpdatedAt(long updatedAt) {
-      this.updatedAt = updatedAt;
-      return this;
-    }
-
-    public Builder setInternalKey(@Nullable String internalKey) {
-      this.internalKey = internalKey;
-      return this;
-    }
-
-    public Builder setLanguage(@Nullable String language) {
-      this.language = language;
-      return this;
-    }
-
-    public Builder setTemplateRuleKey(@Nullable String templateRuleKey) {
-      this.templateRuleKey = templateRuleKey;
-      return this;
-    }
-
-    public Builder setQProfileKey(String qProfileKey) {
-      this.qProfileKey = qProfileKey;
-      return this;
-    }
-
-    public NewActiveRule build() {
-      return new NewActiveRule(this);
-    }
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java
deleted file mode 100644 (file)
index edcf70f..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.batch.rule;
-
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-
-public class NewRule {
-
-  private static final String DEFAULT_SEVERITY = Severity.defaultSeverity();
-
-  final RuleKey key;
-  Integer id;
-  String name;
-  String description;
-  String severity = DEFAULT_SEVERITY;
-  String type;
-  String internalKey;
-  RuleStatus status = RuleStatus.defaultStatus();
-  Map<String, NewRuleParam> params = new HashMap<>();
-
-  public NewRule(RuleKey key) {
-    this.key = key;
-  }
-
-  public NewRule setId(@Nullable Integer id) {
-    this.id = id;
-    return this;
-  }
-
-  public NewRule setDescription(@Nullable String description) {
-    this.description = description;
-    return this;
-  }
-
-  public NewRule setName(@Nullable String s) {
-    this.name = s;
-    return this;
-  }
-
-  public NewRule setSeverity(@Nullable String severity) {
-    this.severity = StringUtils.defaultIfBlank(severity, DEFAULT_SEVERITY);
-    return this;
-  }
-  
-  public NewRule setType(@Nullable String type) {
-    this.type = type;
-    return this;
-  }
-
-  public NewRule setStatus(@Nullable RuleStatus s) {
-    this.status = (RuleStatus) ObjectUtils.defaultIfNull(s, RuleStatus.defaultStatus());
-    return this;
-  }
-
-  public NewRule setInternalKey(@Nullable String s) {
-    this.internalKey = s;
-    return this;
-  }
-
-  public NewRuleParam addParam(String paramKey) {
-    if (params.containsKey(paramKey)) {
-      throw new IllegalStateException(String.format("Parameter '%s' already exists on rule '%s'", paramKey, key));
-    }
-    NewRuleParam param = new NewRuleParam(paramKey);
-    params.put(paramKey, param);
-    return param;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java
deleted file mode 100644 (file)
index f06830d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.batch.rule;
-
-import javax.annotation.Nullable;
-
-public class NewRuleParam {
-  final String key;
-  String description;
-
-  NewRuleParam(String key) {
-    this.key = key;
-  }
-
-  public NewRuleParam setDescription(@Nullable String s) {
-    description = s;
-    return this;
-  }
-}
index 6f8452a8bd4d587db43d13ffac355f06896f210d..05071d3e5b5c014d282da810a9d665d1d3c66c9c 100644 (file)
@@ -32,7 +32,6 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.SonarException;
 import org.sonar.check.Cardinality;
 
 import static java.util.Arrays.asList;
index 6a75a66d49acf4b23b16c36b930e7efcc21a24d8..53b84c86164266ce134d9c45524d6bca9e165939 100644 (file)
@@ -21,9 +21,9 @@ package org.sonar.api;
 
 import java.util.Arrays;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.context.PluginContextImpl;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.internal.PluginContextImpl;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 501b48945e87f60b560e19b36f1abe9ab2ed7fc3..48f3746bd356fa0da6ffed84d37a82dd5443637f 100644 (file)
@@ -23,7 +23,7 @@ import java.io.File;
 import org.junit.Test;
 import org.sonar.api.batch.bootstrap.internal.ProjectBuilderContext;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.core.Is.is;
index b2ccc7a514aac4a9da91a98f602ad65fcac08f7d..60136eec67ae6c555d1dd2b3240e43f015ab72a1 100644 (file)
@@ -21,7 +21,8 @@ package org.sonar.api.batch.rule;
 
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.SonarException;
 
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/NewActiveRuleTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/NewActiveRuleTest.java
deleted file mode 100644 (file)
index 927c793..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.api.batch.rule;
-
-import com.google.common.collect.ImmutableMap;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class NewActiveRuleTest {
-
-  private NewActiveRule.Builder builder;
-
-  @Before
-  public void setBuilder() {
-    builder = new NewActiveRule.Builder();
-  }
-
-  @Test
-  public void builder_should_set_every_param() {
-    NewActiveRule rule = builder
-      .setRuleKey(RuleKey.of("foo", "bar"))
-      .setName("name")
-      .setSeverity(org.sonar.api.rule.Severity.CRITICAL)
-      .setParam("key", "value")
-      .setCreatedAt(1_000L)
-      .setUpdatedAt(1_000L)
-      .setInternalKey("internal_key")
-      .setLanguage("language")
-      .setTemplateRuleKey("templateRuleKey")
-      .setQProfileKey("qProfileKey")
-      .build();
-
-    assertThat(rule.ruleKey).isEqualTo(RuleKey.of("foo", "bar"));
-    assertThat(rule.name).isEqualTo("name");
-    assertThat(rule.severity).isEqualTo(org.sonar.api.rule.Severity.CRITICAL);
-    assertThat(rule.params).isEqualTo(ImmutableMap.of("key", "value"));
-    assertThat(rule.createdAt).isEqualTo(1_000L);
-    assertThat(rule.updatedAt).isEqualTo(1_000L);
-    assertThat(rule.internalKey).isEqualTo("internal_key");
-    assertThat(rule.language).isEqualTo("language");
-    assertThat(rule.templateRuleKey).isEqualTo("templateRuleKey");
-    assertThat(rule.qProfileKey).isEqualTo("qProfileKey");
-  }
-
-  @Test
-  public void severity_should_have_default_value() {
-    NewActiveRule rule = builder.build();
-    assertThat(rule.severity).isEqualTo(Severity.defaultSeverity());
-  }
-
-  @Test
-  public void params_should_be_empty_map_if_no_params() {
-    NewActiveRule rule = builder.build();
-    assertThat(rule.params).isEqualTo(ImmutableMap.of());
-  }
-
-  @Test
-  public void set_param_remove_param_if_value_is_null() {
-    NewActiveRule rule = builder
-      .setParam("foo", "bar")
-      .setParam("removed", "value")
-      .setParam("removed", null)
-      .build();
-    assertThat(rule.params).isEqualTo(ImmutableMap.of("foo", "bar"));
-  }
-}
index a67127d5e2d21f925a4536996ed2c237f9018986..8de07ea19a02ee962da6f7646d9e7a2014efb8d4 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.api.config;
 
 import org.apache.commons.lang.RandomStringUtils;
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 
 import static org.assertj.core.api.Assertions.assertThat;
index efe7b99c67b87e04f37acd95768458884e5ed279..ea4c2a0c94348734c545426c30393de45dfd4a27 100644 (file)
@@ -22,9 +22,9 @@ package org.sonar.api.issue;
 import java.util.Arrays;
 import java.util.HashSet;
 import org.junit.Test;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.issue.DefaultNoSonarFilter;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.issue.internal.DefaultNoSonarFilter;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 0889a04aaf28fbb4b42eba565d2da4c521bb8ad8..91499a18c77a74502c340e3dc14232f34c5b3ae2 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.api.scan.filesystem;
 
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index f841e1a6afd25b4ffa04788e52ca98d8d6aa155d..3a17b08b6a4a12dceb96ffafa7249ec370ef289c 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.server.rule.RulesDefinition.NewRule;
 import org.sonar.check.Priority;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -58,7 +58,7 @@ public class RulesDefinitionAnnotationLoaderTest {
 
   @Test
   public void override_annotation_programmatically() {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java");
     NewRule newRule = annotationLoader.loadRule(newRepository, RuleWithProperty.class);
     newRule.setName("Overridden name");
@@ -145,7 +145,7 @@ public class RulesDefinitionAnnotationLoaderTest {
   }
 
   private RulesDefinition.Repository load(Class annotatedClass) {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewExtendedRepository newRepository = context.createRepository("squid", "java");
     annotationLoader.load(newRepository, annotatedClass);
     newRepository.done();
index 65a523e017950f0aad5d000ae5618d699da84436..b92052b19af71d4d34f757aff604e11c1c309efc 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.api.server.rule;
 
 import org.junit.Test;
 import org.sonar.api.i18n.RuleI18n;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -37,7 +37,7 @@ public class RulesDefinitionI18nLoaderTest {
     when(i18n.getName("squid", "S0001")).thenReturn("SOne");
     when(i18n.getDescription("squid", "S0001")).thenReturn("S One");
 
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
     // rule without description
     repo.createRule("S0001");
@@ -54,7 +54,7 @@ public class RulesDefinitionI18nLoaderTest {
   public void do_not_override_if_no_bundle() {
     // i18n returns null values
 
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
     repo.createRule("S0001").setName("SOne").setHtmlDescription("S One");
 
@@ -71,7 +71,7 @@ public class RulesDefinitionI18nLoaderTest {
     when(i18n.getName("squid", "S0001")).thenReturn("SOne");
     when(i18n.getDescription("squid", "S0001")).thenReturn("S One");
 
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
     repo.createRule("S0001").setName("Bad").setHtmlDescription("Bad");
 
@@ -87,7 +87,7 @@ public class RulesDefinitionI18nLoaderTest {
   public void complete_param_description() {
     when(i18n.getParamDescription("squid", "S0001", "max")).thenReturn("Maximum");
 
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewRepository repo = context.createRepository("squid", "java");
     repo.createRule("S0001").setName("SOne").setHtmlDescription("S One").createParam("max");
 
index 27fd0a673ceaa7decf483263aecb5423c9538db2..40db9778ffc639c5f0b17bd0f169d6450d580186 100644 (file)
@@ -41,7 +41,7 @@ import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.fail;
@@ -49,7 +49,7 @@ import static org.junit.Assert.fail;
 @RunWith(DataProviderRunner.class)
 public class RulesDefinitionTest {
 
-  RulesDefinition.Context context = new RuleDefinitionContext();
+  RulesDefinition.Context context = new RulesDefinitionContext();
 
   @Rule
   public LogTester logTester = new LogTester();
index 4103c498b08d2bff98ac24ac3fd211fd32070ea5..37a06e8f6453b969995355fe199407409e33cb18 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.debt.DebtRemediationFunction;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.utils.ExceptionCauseMatcher.hasType;
@@ -295,7 +295,7 @@ public class RulesDefinitionXmlLoaderTest {
   }
 
   private RulesDefinition.Repository load(InputStream input, String encoding) {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java");
     underTest.load(newRepository, input, encoding);
     newRepository.done();
@@ -303,7 +303,7 @@ public class RulesDefinitionXmlLoaderTest {
   }
 
   private RulesDefinition.Repository load(String xml) {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java");
     underTest.load(newRepository, new StringReader(xml));
     newRepository.done();
index 802c5ff112c6278e32d28528952a7c885371c327..a61ff027f103d9bbdbaae74bc280ffecea97983b 100644 (file)
@@ -28,7 +28,7 @@ import java.util.Map.Entry;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.sensor.DefaultMeasure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.FileLinesContext;
 import org.sonar.api.utils.KeyValueFormat;
index 8848449b2f30478f5202d3f01434d0f2d2f0d9cf..ae3d097f7d282b147f88a20a4ff2678baebbbd80 100644 (file)
@@ -25,7 +25,7 @@ import java.nio.file.Path;
 import org.picocontainer.ComponentLifecycle;
 import org.picocontainer.PicoContainer;
 import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.api.impl.utils.DefaultTempFolder;
 import org.sonar.api.utils.TempFolder;
 
index 7c93cfa4ce407d27e406bd95530e8dea6eab9527..cf39ff12cdf23d7cc35d196964bbab47c1bf4a95 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.ExtensionProvider;
 import org.sonar.api.Plugin;
 import org.sonar.api.SonarRuntime;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.context.PluginContextImpl;
+import org.sonar.api.internal.PluginContextImpl;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginInfo;
 import org.sonar.core.platform.PluginRepository;
index 5903adcbf67c34c5a90253abbf82f811d69d5f17..87f69aad2a849ce9182ea0c934724ad5c12b612e 100644 (file)
@@ -29,8 +29,8 @@ import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarQubeVersion;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.impl.context.MetadataLoader;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.internal.MetadataLoader;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.UriReader;
index 8c392cfed46c0cf0e5c02bb3b350e1b2394d195b..d57b46c7994af7f056dcb990c492587b12cc1480 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.utils.log.Loggers;
 
 import static java.util.Objects.requireNonNull;
 import static org.apache.commons.lang.StringUtils.trim;
-import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
+import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
 
 @Immutable
 public abstract class DefaultConfiguration implements Configuration {
index 5f6cfd1a5f7696f692e16e41b074d0b8fb490ab0..635c07fb94ed5f117a3c2fe5830c3b5647fe00b3 100644 (file)
@@ -33,8 +33,8 @@ import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.impl.fs.DefaultInputComponent;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.duplications.block.Block;
index 82ee99a37ee58d66dec61edceaeb6dcb873cc9f3..fd5080d943881ab6f032db4d947f4ca5631b1fb3 100644 (file)
@@ -23,7 +23,7 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.config.Configuration;
 import org.sonar.duplications.block.BlockChunker;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 public class CpdSettings {
   private final Configuration settings;
index 69645b6c05dd3620b83344a1c6f555b5c459c642..2411a3958e5cca02daeaa3257e2ff8bfebd1b26f 100644 (file)
@@ -43,7 +43,7 @@ import org.sonar.duplications.statement.Statement;
 import org.sonar.duplications.statement.StatementChunker;
 import org.sonar.duplications.token.TokenChunker;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 
 /**
  * Special case for Java that use a dedicated block indexer.
index 44b419f26ff5783ea3867fb2dc09b5274ecca5d5..7f46121d177eb5e530441d10d243d9a80315aaf7 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.duplications.index.CloneIndex;
 import org.sonar.duplications.index.PackedMemoryCloneIndex;
 import org.sonar.duplications.index.PackedMemoryCloneIndex.ResourceBlocks;
 import org.sonar.scanner.cpd.CpdSettings;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.protocol.output.FileStructure;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.report.ReportPublisher;
index be9e3686cdf35433349e2d8e4b8d9f581e451c5a..b01425adb832ac979d58f1edcd2a1f0528cdf0f7 100644 (file)
@@ -23,7 +23,7 @@ import java.util.List;
 import org.sonar.api.test.CoverageBlock;
 import org.sonar.api.test.TestCase;
 import org.sonar.api.test.Testable;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 
 public class DefaultCoverageBlock implements CoverageBlock {
 
index a694f434fd9f1541fc19d1582e745818f4b116a4..2c56bcdd7663bc3f750e843b2b2296134017a56b 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Map;
 import javax.annotation.Nullable;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.test.CoverageBlock;
 import org.sonar.api.test.MutableTestCase;
 import org.sonar.api.test.TestPlan;
index 5219368da91541db38d5dfeb6ae56605b3a5eaef..c31a25c512eb560c012afe9d8ad4b45281f658f2 100644 (file)
@@ -25,7 +25,7 @@ import java.util.SortedSet;
 import org.sonar.api.test.CoverageBlock;
 import org.sonar.api.test.MutableTestable;
 import org.sonar.api.test.TestCase;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 
 public class DefaultTestable implements MutableTestable {
 
index c4c5286590728b355d62b6a0f9cfcd38b90210d5..c75e29d67c8fd5bf39f5a9f18e3d756f56995aaf 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
 import org.sonar.api.test.MutableTestPlan;
 import org.sonar.scanner.deprecated.perspectives.PerspectiveBuilder;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 
 public class TestPlanBuilder extends PerspectiveBuilder<MutableTestPlan> {
 
index 4498f0b4d9380deb89e366666d5f110c0fd46f88..1fb0bb20ede243c1a146e6bb42b0461b10b01f98 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
 import org.sonar.api.test.MutableTestable;
 import org.sonar.scanner.deprecated.perspectives.PerspectiveBuilder;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 
 public class TestableBuilder extends PerspectiveBuilder<MutableTestable> {
 
index ef1124cbcc9a2379b8c64f4fc79d5e5aadd318ce..0c54edbb65982b664d2be2d5afc983633b445deb 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.scanner.fs;
 import java.util.Collection;
 import javax.annotation.CheckForNull;
 import javax.annotation.concurrent.Immutable;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 
 @Immutable
 public interface InputModuleHierarchy {
index 5d107da2d76180c9dcf5c0849163e4ded5cc3c08..4482a2b7f3b2eaa5a51f16b6ab1130bfcde8a92a 100644 (file)
@@ -28,9 +28,9 @@ import org.sonar.api.batch.fs.TextRange;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.scan.issue.filter.FilterableIssue;
 import org.sonar.scanner.ProjectInfo;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.DefaultTextPointer;
-import org.sonar.api.impl.fs.DefaultTextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.DefaultTextRange;
 import org.sonar.scanner.protocol.output.ScannerReport.Issue;
 
 @ThreadSafe
index 3b887b024efd43a4707ba31d4bce378756795014..ca58f8ed932b85154290fd1a3bebb1a2a8321d26 100644 (file)
@@ -24,7 +24,7 @@ import org.sonar.api.scan.issue.filter.FilterableIssue;
 import org.sonar.api.scan.issue.filter.IssueFilter;
 import org.sonar.api.scan.issue.filter.IssueFilterChain;
 import org.sonar.scanner.ProjectInfo;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.protocol.output.ScannerReport;
 
 /**
index 326f38e6b830ca20d42d8f221805bec0698920b9..5e07f70d8e80c7495b2105ecf135364b064575df 100644 (file)
@@ -30,8 +30,8 @@ import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.batch.sensor.issue.ExternalIssue;
 import org.sonar.api.batch.sensor.issue.Issue;
 import org.sonar.api.batch.sensor.issue.Issue.Flow;
-import org.sonar.api.impl.fs.DefaultInputComponent;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.protocol.Constants.Severity;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.IssueLocation;
index 3faefb38407da5c5e3688425e8fed53381f38e16..9bbd9b50ca5fd495846d4898222b58162938c65f 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.scan.issue.filter.IssueFilter;
 import org.sonar.api.scan.issue.filter.IssueFilterChain;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.issue.DefaultFilterableIssue;
 import org.sonar.scanner.issue.ignore.pattern.IssueInclusionPatternInitializer;
 import org.sonar.scanner.issue.ignore.pattern.IssuePattern;
index 2a961ee65ad8595d4d7664712118022f2ea8d3ed..6626bb685d93673a61c661e7f9d32de7a012fe70 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.scan.issue.filter.IssueFilterChain;
 import org.sonar.api.utils.WildcardPattern;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.issue.DefaultFilterableIssue;
 
 public class IgnoreIssuesFilter implements IssueFilter {
index 51c10c1e3cf3193a3f6f35c2e7ead028c3cfffad..2d98081334bf5d3764a30a31a380817c9f6d6135 100644 (file)
@@ -78,7 +78,7 @@ public class IssueExclusionPatternInitializer extends AbstractPatternInitializer
     allFilePatterns = Collections.unmodifiableList(allFilePatterns);
   }
 
-  private String nullToEmpty(@Nullable String str) {
+  private static String nullToEmpty(@Nullable String str) {
     if (str == null) {
       return "";
     }
index ad9b431b5d386e11af516d4180f49d97196b2d47..521235c4285bb4c1922aa981178037183c93bff2 100644 (file)
@@ -26,8 +26,8 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.notifications.AnalysisWarnings;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.charhandler.CharHandler;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.charhandler.CharHandler;
 import org.sonar.scanner.issue.ignore.IgnoreIssuesFilter;
 import org.sonar.scanner.issue.ignore.pattern.BlockIssuePattern;
 import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
index 345db834790be4dd43222754d714cfb4c1166525..fe2001f062094c791e84a3d3cdce3b2664a6edc4 100644 (file)
@@ -27,8 +27,8 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.charhandler.CharHandler;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.charhandler.CharHandler;
 import org.sonar.scanner.issue.ignore.pattern.LineRange;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader.DoubleRegexpMatcher;
 
index 7770db3b4797fa2283011da5816aafdb7096d816..6367d40397f432e3c235736fa705c9c128e4b67a 100644 (file)
@@ -33,8 +33,8 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.TextPointer;
 import org.sonar.api.batch.fs.TextRange;
 import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.impl.fs.DefaultInputComponent;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.scanner.fs.InputProject;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.scanner.protocol.output.ScannerReport;
index ea9acd22d342bd08556c1b525401c5a5f95f31c7..cee85b0e463df63d82eea8122790c169be4a1709 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.scanner.postjob;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
 
 public class PostJobOptimizer {
 
index 9df6f4cd892de46504322f15cc29ffa8e8537691..408ad6385c0a14c88e4bef0896aa104105c5b553 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.scanner.postjob;
 
 import org.sonar.api.batch.postjob.PostJob;
 import org.sonar.api.batch.postjob.PostJobContext;
-import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
 
 public class PostJobWrapper {
 
index 174659fe796844fe7edee1fe4eacc7c85b990d59..d8677af3bce2c0fd7ec739e4aaca545c8a3f45af 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.report;
 
 import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.DefaultActiveRule;
+import org.sonar.api.batch.rule.internal.DefaultActiveRule;
 import org.sonar.scanner.protocol.Constants;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
index 5c6daad40b86ce76e7531ad00873dfaecbfc7b6b..59e84298d67c1793ae2c89efec17bde803739100 100644 (file)
@@ -30,8 +30,8 @@ import java.util.Map;
 import java.util.TreeSet;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.fs.AbstractProjectOrModule;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.utils.System2;
 import org.sonar.core.platform.PluginInfo;
 import org.sonar.scanner.bootstrap.GlobalServerSettings;
index db7d22baf08c85920c38fe317a7451701a6fb202..7da793fdf8dc8108eb8219a449874fffb828cec1 100644 (file)
@@ -29,8 +29,8 @@ import org.sonar.api.batch.scm.ScmProvider;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.api.utils.log.Profiler;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
index b66fc8e8a93f630d702d2a76509ce261bde1a65d..cb7d50f7dcc55f15e373574880e6e47fcd051e57 100644 (file)
@@ -25,9 +25,9 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Status;
-import org.sonar.api.impl.fs.AbstractProjectOrModule;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
 import org.sonar.scanner.protocol.output.ScannerReport.Component.FileStatus;
index f238735d3cb7eb0bd305e2840a13f1fa7e95778b..22294eaa3594dbd0db6c11cb4b7aec0869b2fe85 100644 (file)
@@ -32,8 +32,8 @@ import org.sonar.scanner.ProjectInfo;
 import org.sonar.scanner.bootstrap.ScannerPlugin;
 import org.sonar.scanner.bootstrap.ScannerPluginRepository;
 import org.sonar.scanner.cpd.CpdSettings;
-import org.sonar.api.impl.fs.AbstractProjectOrModule;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Metadata.BranchType;
index f18549f81df5088ba7a43a9889a9c4e59d9f5420..065dd58a4cb8718d057f154535521228ea327fcc 100644 (file)
@@ -29,7 +29,7 @@ import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.nio.charset.StandardCharsets;
 import org.apache.commons.io.IOUtils;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
index da6d8fc3ddef9ca607e46968c77dcb68536e3e38..f837221a0af3ddf8c0326b24c587896902fb05cb 100644 (file)
@@ -23,9 +23,9 @@ import java.util.Objects;
 import java.util.stream.StreamSupport;
 import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.DefaultInputComponent;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.sensor.DefaultMeasure;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.test.MutableTestPlan;
 import org.sonar.api.test.TestCase;
 import org.sonar.api.test.TestCase.Status;
index ad817fd2a4776928e38768f7ee825db9fe033131..7ca0913805c5915d9cd8aa1effccf60b6897a7e9 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.scanner.repository;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.concurrent.Immutable;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 
 @Immutable
 public abstract class ProjectRepositories {
index dbf8ec440a230ffb3c8d9efe84f0e7c6bdc74f15..e0476954efccd88d3d947ba8e7c681df7022ccf4 100644 (file)
@@ -27,9 +27,9 @@ import java.util.Map;
 import java.util.Set;
 import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 import org.sonar.api.batch.rule.LoadedActiveRule;
-import org.sonar.api.batch.rule.NewActiveRule;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
index 3b365ac3c718cf25effe1dd758d197b4d4ec9e64..faa85ecf52744d00912f14333c9d32d643f7825a 100644 (file)
@@ -21,9 +21,9 @@ package org.sonar.scanner.rule;
 
 import java.util.List;
 import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.batch.rule.NewRule;
+import org.sonar.api.batch.rule.internal.NewRule;
 import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.impl.rule.RulesBuilder;
+import org.sonar.api.batch.rule.internal.RulesBuilder;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
index 108a6dc72857693fb835797cd65a02f0a3857c22..db0d7cfeb23d84695b1a7e7fbc9c289aee8376c5 100644 (file)
@@ -28,8 +28,8 @@ import java.util.Map;
 import javax.annotation.CheckForNull;
 import javax.annotation.concurrent.Immutable;
 import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.api.impl.fs.AbstractProjectOrModule;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 @Immutable
index ef806c5b2ab8bfe0f956b790c09484adfe640a35..42d8517840af8d6abd3d55c89071586a0f34892f 100644 (file)
@@ -26,8 +26,8 @@ import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
 
 public class InputModuleHierarchyProvider extends ProviderAdapter {
index 9500e47d8f75d43d9b23ca3152516d6ec01d57b1..3f983b064fca1ff5a03d736e547ec3bda91aad3f 100644 (file)
@@ -24,7 +24,7 @@ import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
 
 public class InputProjectProvider extends ProviderAdapter {
index dab9cc531fd9bb93642fe98ea8d437c11e1ca2a5..a85d1d4ac7aa658279d0e05359cfda9fffa8ab71 100644 (file)
@@ -27,7 +27,7 @@ import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.scanner.bootstrap.GlobalConfiguration;
 import org.sonar.scanner.bootstrap.GlobalServerSettings;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 
 public class ModuleConfigurationProvider extends ProviderAdapter {
 
index c307a20aafc013e1c5a5280cba5701bf5e6544b0..029f124b0491f094b82886a3f97a99a19b65f427 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan;
 
 import org.picocontainer.Startable;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
index f573dd47e4dcedfc7acb3a5b56a09d2db0861ecf..617ab3467eff8bb7620d69f87e5e432d0aa7b4e1 100644 (file)
@@ -23,7 +23,7 @@ import org.sonar.api.scan.filesystem.FileExclusions;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.scanner.bootstrap.ExtensionInstaller;
 import org.sonar.scanner.deprecated.perspectives.ScannerPerspectives;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
 import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore;
 import org.sonar.scanner.sensor.ModuleSensorContext;
index 1903ad736eb0f1e89d9eda59dea0fbd24b176cda..425104fe7e696721e93148bbe3bd124eb8d4570d 100644 (file)
@@ -24,7 +24,7 @@ import java.util.Map;
 import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.scanner.bootstrap.GlobalConfiguration;
 import org.sonar.scanner.bootstrap.GlobalServerSettings;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 public class ProjectConfigurationProvider extends ProviderAdapter {
 
index d024d47f7cbc9aa142a4187b3b510691dd6eac8d..89bfe76c1f278b68e777fb03b794baa3d19bdbe4 100644 (file)
@@ -24,7 +24,7 @@ import java.nio.channels.OverlappingFileLockException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import org.picocontainer.Startable;
-import org.sonar.api.impl.fs.AbstractProjectOrModule;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
 
 public class ProjectLock implements Startable {
   private final DirectoryLock lock;
index da610c5ac341cb1c06f05d8c0eccd132c43fbabe..eafe035bf11f3340653c91f06b07c5e37fea8ce1 100644 (file)
@@ -52,7 +52,7 @@ import org.sonar.scanner.issue.ignore.pattern.IssueInclusionPatternInitializer;
 
 import static java.util.Arrays.asList;
 import static java.util.stream.Collectors.toList;
-import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
+import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
 
 /**
  * Class that creates a project definition based on a set of properties.
index 0f0d81d1b8d08a9c2adb8570a3908472682096d3..326ba1d4287d98589049a6cff368c4e63aac00fd 100644 (file)
@@ -23,10 +23,10 @@ import javax.annotation.Nullable;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarRuntime;
 import org.sonar.api.batch.rule.CheckFactory;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.FileMetadata;
-import org.sonar.api.impl.fs.SensorStrategy;
-import org.sonar.api.impl.issue.DefaultNoSonarFilter;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
+import org.sonar.api.batch.sensor.issue.internal.DefaultNoSonarFilter;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.scan.filesystem.PathResolver;
index 6beb97470af3cb7f854766405d76d937970212eb..ada80c3054eca50e1cabcac142596ca2c7590b8c 100644 (file)
@@ -24,7 +24,7 @@ import java.nio.file.Paths;
 import java.util.Optional;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.utils.MessageException;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 import static org.sonar.core.config.ScannerProperties.BRANCH_NAME;
 import static org.sonar.core.config.ScannerProperties.ORGANIZATION;
index 03b39315cc08fc3467701bcf502aa812d4b19be6..5174ea56f38392502332e349d2eb162b7aca8c61 100644 (file)
@@ -25,7 +25,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Iterator;
 import org.sonar.core.util.FileUtils;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 /**
index 495b65448d4d5bdca0900f5f1d8dd6efe7008041..95961192c6e0fd61e62fe6315b6cff2b1694fd70 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.CoreProperties;
 import org.sonar.api.utils.WildcardPattern;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 
 import static java.util.stream.Collectors.toList;
 
index 65aca8bd046463d5897dc2200146bf6af292e692..9a348fee7f50e8e6fd71f8a45d40f6b945fd5a6d 100644 (file)
@@ -28,7 +28,7 @@ import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.PathPattern;
+import org.sonar.api.batch.fs.internal.PathPattern;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 
index 299cb5a268c7fadeacce2dca2f3d65b0e36538df..b21ae759e8cbedc1c03f9f820a9f47ec265063b4 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan.filesystem;
 
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.predicates.AbstractFilePredicate;
+import org.sonar.api.batch.fs.internal.predicates.AbstractFilePredicate;
 
 /**
  * Additional {@link org.sonar.api.batch.fs.FilePredicate}s that are
index de87c63286b9175bc06eacfab17145d245b13b5d..65fbaab1766b42e42dc1f4c1e74da9a33777590b 100644 (file)
@@ -19,9 +19,9 @@
  */
 package org.sonar.scanner.scan.filesystem;
 
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.predicates.DefaultFilePredicates;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.predicates.DefaultFilePredicates;
 
 public class DefaultModuleFileSystem extends DefaultFileSystem {
 
index d04ee42d47d0cb828f2f735ef41ef0abe5e3acc3..2776d497ed40b77da35ddff40ff4265e6cd5f20a 100644 (file)
@@ -19,9 +19,9 @@
  */
 package org.sonar.scanner.scan.filesystem;
 
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.predicates.DefaultFilePredicates;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.predicates.DefaultFilePredicates;
 
 public class DefaultProjectFileSystem extends DefaultFileSystem {
 
index c01df402b0043b3269c2748ee3a527bd49e131cb..aba6c180495e9dd3d961f83e79c7d49b82d0e0b1 100644 (file)
@@ -30,16 +30,16 @@ import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
 import org.sonar.api.batch.fs.InputFileFilter;
-import org.sonar.api.impl.fs.SensorStrategy;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
 import org.sonar.api.batch.scm.IgnoreCommand;
 import org.sonar.api.notifications.AnalysisWarnings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultIndexedFile;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.util.ProgressReport;
index eb33beb7e534c24089601f91b5ce414a2d812ba5..2be7dd480567cba65340f095c6c593bbd3086457 100644 (file)
@@ -35,10 +35,10 @@ import java.util.stream.Stream;
 import javax.annotation.CheckForNull;
 import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.predicates.FileExtensionPredicate;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.predicates.FileExtensionPredicate;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 
 /**
index 7b699f2befd9a8292ac381e2785ed2a34a24edf6..57fbb86e23d39b8bab80d11e81583a3a0c5c97e0 100644 (file)
@@ -32,7 +32,7 @@ import javax.annotation.concurrent.ThreadSafe;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.impl.fs.PathPattern;
+import org.sonar.api.batch.fs.internal.PathPattern;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.repository.language.Language;
index 9954b92eee0cb756066e8259ba1d880b93c376b1..a5796756789afefe56d09b9c57d0a0b11c980838 100644 (file)
@@ -22,9 +22,9 @@ package org.sonar.scanner.scan.filesystem;
 import java.io.InputStream;
 import java.nio.charset.Charset;
 import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.FileMetadata;
-import org.sonar.api.impl.fs.Metadata;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.Metadata;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader;
index 2eb7d6805f4706052df194727e1b32a82ea2b455..5cb50568741c73cec95a35852d88787bb340639f 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan.filesystem;
 
 import javax.annotation.concurrent.Immutable;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.scan.ModuleConfiguration;
 
 @Immutable
index 23d7e257731ea697f760219f518f560d60263ba0..6899854f8666a385e780c573cc4c31646122f9ca 100644 (file)
@@ -23,8 +23,8 @@ import java.util.SortedSet;
 import org.sonar.api.batch.ScannerSide;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.impl.fs.SensorStrategy;
-import org.sonar.api.impl.fs.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
 
 @ScannerSide
 public class ModuleInputComponentStore extends DefaultFileSystem.Cache {
index e52ab6cc1bb16198c3956e62d487232087d42c2c..1cf496f1310a8c666f65b5271696338d3a37c6cd 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan.filesystem;
 
 import javax.annotation.concurrent.Immutable;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.scan.ProjectConfiguration;
 
 @Immutable
index b5633d772ebbd7e2ba3d0baba16a4b11cd9defcf..9262bb10b5b411222d2654b744d2ce64f4bed28c 100644 (file)
@@ -45,7 +45,7 @@ import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.scanner.bootstrap.GlobalConfiguration;
 import org.sonar.scanner.bootstrap.GlobalServerSettings;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.ModuleConfiguration;
 import org.sonar.scanner.scan.ModuleConfigurationProvider;
index 9de8b028234a559286f2d7a7d03f5cd6fccea674..09561999935295f3218abfcbce6b9434fcf4483f 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.scanner.scan.filesystem;
 import javax.annotation.concurrent.Immutable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.repository.FileData;
 import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
 import org.sonar.scanner.scm.ScmChangedFiles;
index 8049abe2532291146ea59b1337a3cdd081835051..0908056ed5aee812f243bccf2f2a2799876db015 100644 (file)
@@ -31,7 +31,7 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.scm.BlameCommand.BlameOutput;
 import org.sonar.api.batch.scm.BlameLine;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.scanner.protocol.output.ScannerReport;
index 4c65b2843e8067b0a5db5d1f60c2356a54b10435..dfdcb165319e8f0988050dea205b5c6162a5e5e7 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.batch.scm.ScmProvider;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.api.utils.log.Profiler;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.api.impl.utils.ScannerUtils;
 
index 834d224ec820db108dd2649195d3754f8eba1ce2..d4da27296619e32085fcefa0c4f981631a796c7f 100644 (file)
@@ -29,7 +29,7 @@ import org.sonar.api.batch.fs.InputFile.Status;
 import org.sonar.api.batch.scm.ScmProvider;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Changesets.Builder;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
index cc089182c6bc122a17b8c6c8949e7c4563563b3b..a2779b9c03dbe8fd9722267c060164a1b5558d54 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
 
 public abstract class AbstractSensorOptimizer {
 
index d5109c87943246cbf73cef1ed0a55b91be38825e..43773f1eb1d8b27173276a6ed65aa183e9c0eea6 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.sensor;
 
 import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
 import org.sonar.api.scanner.sensor.ProjectSensor;
 
 public abstract class AbstractSensorWrapper<G extends ProjectSensor> {
index 8cece1eba14abdd82b53bcdd506e77bd77feef61..360dc439b0e3753eeeff465ac301a5d1292ffa8b 100644 (file)
@@ -32,29 +32,29 @@ import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.InputDir;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.measure.Metric;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.code.NewSignificantCode;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
 import org.sonar.api.batch.sensor.coverage.NewCoverage;
+import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
 import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
+import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
 import org.sonar.api.batch.sensor.error.AnalysisError;
 import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
+import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.batch.sensor.issue.ExternalIssue;
 import org.sonar.api.batch.sensor.issue.Issue;
 import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.batch.sensor.rule.AdHocRule;
 import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
+import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.fs.DefaultInputComponent;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.sensor.DefaultCoverage;
-import org.sonar.api.impl.sensor.DefaultCpdTokens;
-import org.sonar.api.impl.sensor.DefaultHighlighting;
-import org.sonar.api.impl.sensor.DefaultMeasure;
-import org.sonar.api.impl.sensor.DefaultSignificantCode;
-import org.sonar.api.impl.sensor.DefaultSymbolTable;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.api.utils.log.Logger;
index 783c4b2720f74d404b1e6402b53bee2d243b1df3..c7edd6990e793ef5d4bfaa90077992d93aaa9166 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 @ThreadSafe
 public class ModuleSensorContext extends ProjectSensorContext {
index 7c627f3d50202d4441d9f806e053f9cd9db5fa1a..f6668ee2ce1e618364ffd80b9b2893dabcb6dd2d 100644 (file)
@@ -23,12 +23,12 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import org.sonar.api.impl.fs.SensorStrategy;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.core.util.logs.Profiler;
 import org.sonar.scanner.bootstrap.ScannerPluginRepository;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 public class ModuleSensorsExecutor {
index eae821692a052a1de9522b3c3f98a18b8279491e..05e58f8474d3338601eaac3aacc40e803693a425 100644 (file)
@@ -25,32 +25,32 @@ import org.sonar.api.SonarRuntime;
 import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.code.NewSignificantCode;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
 import org.sonar.api.batch.sensor.coverage.NewCoverage;
+import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
 import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
+import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
 import org.sonar.api.batch.sensor.error.NewAnalysisError;
 import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
+import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.batch.sensor.issue.NewExternalIssue;
 import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
 import org.sonar.api.batch.sensor.measure.NewMeasure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.batch.sensor.rule.NewAdHocRule;
+import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
 import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
+import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.issue.DefaultIssue;
-import org.sonar.api.impl.sensor.DefaultAdHocRule;
-import org.sonar.api.impl.sensor.DefaultCoverage;
-import org.sonar.api.impl.sensor.DefaultCpdTokens;
-import org.sonar.api.impl.sensor.DefaultExternalIssue;
-import org.sonar.api.impl.sensor.DefaultHighlighting;
-import org.sonar.api.impl.sensor.DefaultMeasure;
-import org.sonar.api.impl.sensor.DefaultSignificantCode;
-import org.sonar.api.impl.sensor.DefaultSymbolTable;
 import org.sonar.api.scanner.fs.InputProject;
 import org.sonar.api.utils.Version;
 import org.sonar.scanner.sensor.noop.NoOpNewAnalysisError;
index 20b3d3e586952ec7fc5b304084f34a7605d73ace..ad82238825bf3e7f8a21e69c390e14a989b75ed3 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
 import org.sonar.api.batch.sensor.coverage.NewCoverage;
 import org.sonar.api.scanner.sensor.ProjectSensor;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.report.ReportPublisher;
 
 @Phase(name = Phase.Name.POST)
index 5f789670c6a40e5eb4a99b3ce8a0dfaee1286564..d5a5698b48e2a9fa10a1164596168554841fdb36 100644 (file)
@@ -27,9 +27,9 @@ import org.junit.rules.ExpectedException;
 import org.mockito.ArgumentCaptor;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultMeasure;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
 
 import static org.assertj.core.api.Assertions.assertThat;
index b43f101cdd1e3343f006d9791660681f69655ac9..a882ca0afcf865369b2b9da60c595bb7791364c4 100644 (file)
@@ -35,7 +35,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
index 620e3f703c179fbf02cea08991beb904f50f6468..065864daa6e01d6b8507a1680ece8f7faf915709 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.utils.TempFolder;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 17e4b72f4b06fcef588a997335bd4f8a8bab8457..d060367750d5e6c88cfd6a04dc928810e3f38351 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.ExtensionProvider;
 import org.sonar.api.Plugin;
 import org.sonar.api.SonarRuntime;
 import org.sonar.api.batch.ScannerSide;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginInfo;
 
index 68070e636b516176f907f81547cea8aa85a9ee72..4d63704cae061dac9099d8929d584e8bc23c4214 100644 (file)
@@ -33,7 +33,7 @@ import org.sonar.api.batch.ScannerSide;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.scanner.sensor.ModuleSensorContext;
 import org.sonar.scanner.sensor.ModuleSensorExtensionDictionnary;
index 004528a98ebabb38aab79b16a01ddaa96239cef7..21291652028e8d2db173e832c700fbb9c32fef98 100644 (file)
@@ -50,7 +50,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.scanner.bootstrap.ScannerPluginInstaller.InstalledPlugin;
 import org.sonarqube.ws.client.HttpConnector;
 import org.sonarqube.ws.client.WsClientFactories;
index c81893378b8cbcb5f449f7bfd6c08cbfc49b06f5..15cf84a2a18407619ba35ca385166dd60f8fecc3 100644 (file)
@@ -25,7 +25,7 @@ import org.sonar.api.batch.Phase;
 import org.sonar.api.batch.postjob.PostJob;
 import org.sonar.api.batch.postjob.PostJobContext;
 import org.sonar.api.batch.postjob.PostJobDescriptor;
-import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
index b372dd2bc978c3e328fcb628dc637742be90c399..57e1aa0efd4f7de2e532c1d7b6adaf0704b8b4ed 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.ci;
 
 import org.junit.Test;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 9767f60dedfde7dd6eaadf13063079bd5845d95d..1597f30759d6e65030f9bc18ae3bcc4c723504ee 100644 (file)
@@ -44,9 +44,9 @@ import org.sonar.duplications.block.ByteArray;
 import org.sonar.duplications.index.CloneGroup;
 import org.sonar.duplications.index.ClonePart;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReport.Duplicate;
 import org.sonar.scanner.protocol.output.ScannerReport.Duplication;
 import org.sonar.scanner.protocol.output.ScannerReportReader;
index 80a8e4b61f9e9c33865d5a94278bb3088a499324..dee2542644fef741350383723992ab757a770f96 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Optional;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.config.Configuration;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.anyString;
index 3b567a3846b2a4b54d7a83a32163c0e0b31e7e05..fccdfa2b221fdcfaca6aa148737d243467803412 100644 (file)
@@ -34,9 +34,9 @@ import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.sonar.duplications.block.Block;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.eq;
index 3659faec62f13949a06131f397c7c8fdb82c1189..e54309584e61916b39c5763acf618ec941ddd75d 100644 (file)
@@ -31,9 +31,9 @@ import org.sonar.api.batch.rule.Severity;
 import org.sonar.api.batch.sensor.issue.ExternalIssue;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.commons.lang.ObjectUtils.defaultIfNull;
index 777c85a924b3548b143f9ab58cf5e88dbcceecfa..50fd91deb047946c5b009b2c178dbd9c2fb7f963 100644 (file)
@@ -28,9 +28,9 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.utils.MessageException;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index a13c2a7e88ac2a394aa4e370edf2c4e5dc766e35..34dcf68b92be3f56f55ca10a161cd6e15e280ea6 100644 (file)
@@ -31,9 +31,9 @@ import org.sonar.api.test.MutableTestCase;
 import org.sonar.api.test.MutableTestPlan;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.deprecated.test.TestPlanBuilder;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
index fcd36806b4f273467b1850a91994b58937c982e7..295870732068218872339b0e0ac048d348e6b221 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.scanner.config.DefaultConfiguration;
 import org.sonar.scanner.deprecated.test.TestPlanBuilder;
 import org.sonar.scanner.scan.ProjectConfiguration;
-import org.sonar.api.impl.sensor.SensorContextTester;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index cf1b13c9fd8e4d179d8fda50c5254d4ea28214a5..c18c3cba503a7fbe5e869c93cba47b9014c57eef 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.scanner.ProjectInfo;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.protocol.Constants.Severity;
 import org.sonar.scanner.protocol.output.ScannerReport.Issue;
 import org.sonar.scanner.protocol.output.ScannerReport.TextRange;
index 3bd71931f2dd6e80c1ea1795ae4eaa7cc070b48f..19faeded6ed17a4fd6dec4d3335366d5c07650e9 100644 (file)
@@ -32,20 +32,20 @@ import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.rule.NewActiveRule;
-import org.sonar.api.impl.rule.RulesBuilder;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.issue.DefaultIssue;
-import org.sonar.api.impl.issue.DefaultIssueLocation;
-import org.sonar.api.impl.sensor.DefaultExternalIssue;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
+import org.sonar.api.batch.rule.internal.RulesBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
+import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.report.ReportPublisher;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
index 770bfc94806c58f82bd758c803968f7c45d3df7a..80ce4f25eb2dcfc06ae86f3929232a201f849b7e 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.api.notifications.AnalysisWarnings;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.scan.issue.filter.IssueFilterChain;
index 4f514205e43ff1be78e8618ffd91e72c85cdfe2f..653efeb6b5f0b7796c98206d14412d1072650bed 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Test;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.scan.issue.filter.IssueFilterChain;
 import org.sonar.api.utils.WildcardPattern;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.issue.DefaultFilterableIssue;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 70a6a486db77d42aa5cac7b118e142df9fbd146a..50096cc117fd8709d1db5955fcb9db793bf39cf8 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.scanner.issue.ignore.pattern;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.core.config.IssueExclusionProperties;
 
index 7932972af78256cfa417f0e3428130a5eabc7d1e..c6cc5777bda1f23aa981fec975e328300669760b 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.scanner.issue.ignore.pattern;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.core.config.IssueExclusionProperties;
 
 import static org.assertj.core.api.Assertions.assertThat;
index ea148567732f114f344b2bd14d479c881b5096e7..c12698aec1604ef1859c3e6c91edcd716cedd758 100644 (file)
@@ -28,8 +28,8 @@ import org.junit.rules.ExpectedException;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.sonar.api.notifications.AnalysisWarnings;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.issue.ignore.IgnoreIssuesFilter;
 import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
 import org.sonar.scanner.issue.ignore.pattern.IssuePattern;
index e6c757a92d37abded0d74cea3dd8fea52e2c30c7..ab54b184c7d4c2f75e6a2c018b665757b2b68be8 100644 (file)
@@ -34,9 +34,9 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.FileMetadata;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader.DoubleRegexpMatcher;
 
index 96b69e81ff183a8a6f48575f0de087184be1d0ec..a8769acd7a595c5b4d7116a45404d9045429b19d 100644 (file)
@@ -45,7 +45,7 @@ import org.sonar.api.SonarProduct;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
 import org.sonar.api.batch.rule.LoadedActiveRule;
-import org.sonar.api.impl.server.RuleDefinitionContext;
+import org.sonar.api.impl.server.RulesDefinitionContext;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.rule.RuleKey;
@@ -169,7 +169,7 @@ public class ScannerMediumTester extends ExternalResource {
   }
 
   public ScannerMediumTester addRules(RulesDefinition rulesDefinition) {
-    RulesDefinition.Context context = new RuleDefinitionContext();
+    RulesDefinition.Context context = new RulesDefinitionContext();
     rulesDefinition.define(context);
     List<Repository> repositories = context.repositories();
     for (Repository repo : repositories) {
index bb77fdd9001c487887abd1c00d5f99722cb96857..f376d56999eb9c2a463238316e1a4ea23c205cc6 100644 (file)
@@ -30,8 +30,8 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.FileMetadata;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.protocol.output.ScannerReport;
index 27b0c75eb391c5eed7418b1a2053e409f4dd85d9..627e285af3a0710aa3fce7a4a9ad6de0245ebd7a 100644 (file)
@@ -32,7 +32,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.SonarEdition;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
index aeab443969487a905c7b2f2ce5782dfc2645135f..fbf775cbcb939cdc9d75566a7d4daf792bc022a2 100644 (file)
@@ -41,7 +41,7 @@ import org.sonar.api.utils.PathUtils;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.xoo.XooPlugin;
index eff17f8ca83e65a39aa47538d10088414f9ee66d..63239c0924a1c44c921df9d0396aba82b7c119a0 100644 (file)
@@ -25,8 +25,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.scan.ModuleConfiguration;
 import org.sonar.scanner.scan.filesystem.ModuleCoverageAndDuplicationExclusions;
 
index fb7cf2ccea13579247718e54211f4a69a39ac0ec..e0e5880afc6f7c2765a43656e9bee994999a334e 100644 (file)
@@ -26,12 +26,12 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.impl.fs.SensorStrategy;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.scanner.bootstrap.ScannerPluginRepository;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.sensor.ModuleSensorExtensionDictionnary;
 import org.sonar.scanner.sensor.ModuleSensorWrapper;
 import org.sonar.scanner.sensor.ModuleSensorsExecutor;
index f95fa930015467d1e03dd2aaa53360b1baa6e125..ea27f1cd1f8781f4e74efc360088e4ce3d9b23f8 100644 (file)
@@ -25,8 +25,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.scan.ProjectConfiguration;
 import org.sonar.scanner.scan.filesystem.ProjectCoverageAndDuplicationExclusions;
 
index d34cfb43c1280b72e7edc2d9dd806fc699c3a838..97326bc05bf6777656510910237db4535fc7750c 100644 (file)
@@ -24,8 +24,8 @@ import org.junit.Test;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.config.Settings;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
 import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 
index 27a4f7bbd9eebf751eb724addcb83a69b3a49183..6399495c410d305417c35bce4f43199305164634 100644 (file)
@@ -23,7 +23,7 @@ import java.io.IOException;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index c10ffd5c23761bd64a57daea32a2283d7e6a56a2..e2f675aade11752aa40a1ad6f123e62d3123efb3 100644 (file)
@@ -23,8 +23,8 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 2dce5ea77306e3c691e4914a505014db5b8ef297..5042436ac0078d0cdf9d9e87a8ca23095575d73b 100644 (file)
@@ -24,8 +24,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.impl.rule.DefaultActiveRules;
-import org.sonar.api.batch.rule.NewActiveRule;
+import org.sonar.api.batch.rule.internal.DefaultActiveRules;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.scanner.protocol.Constants;
index 5299672f6fd0bb724bd3d3abf4ee1f6350f9a7c0..141d619240a5b3dd08ddd5de0c2b56584fc364b4 100644 (file)
@@ -38,7 +38,7 @@ import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.core.platform.PluginInfo;
 import org.sonar.scanner.bootstrap.GlobalServerSettings;
 import org.sonar.scanner.bootstrap.ScannerPluginRepository;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.ProjectServerSettings;
index d3b7a0b4936e67c4f9710ead5f5008f8b5c129ca..d06e33f611174619ece4e6751b608e1149785835 100644 (file)
@@ -31,10 +31,10 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.scm.ScmProvider;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.fs.InputModuleHierarchy;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
index 0561c6076e3b72215c02419a1792cd6b8c0d2c99..c43378e2973a593741ba3f67a59d38c99698ce24 100644 (file)
@@ -33,9 +33,9 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Type;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.scanner.ProjectInfo;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.FileStructure;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Component;
index 9bbe982e9fcd5d98b6864eddb4013d32f9adf93f..1e6c8f908eb50b9f4a1a08d301ad5ba3b60034f1 100644 (file)
@@ -44,9 +44,9 @@ import org.sonar.scanner.ProjectInfo;
 import org.sonar.scanner.bootstrap.ScannerPlugin;
 import org.sonar.scanner.bootstrap.ScannerPluginRepository;
 import org.sonar.scanner.cpd.CpdSettings;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
index e81e23e2f3bee2a3f6c617127b79f798796cb465..11781cc6b2533f50f8d184f6cc6d2d47dff2c845 100644 (file)
@@ -41,7 +41,7 @@ import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
 import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
index e1239caab09c9b83f660a699e77293e1d1240b97..4028bdae0afb253056edc2b43264c43c1557114c 100644 (file)
@@ -27,9 +27,9 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
index 567079db5853541735dde93946c537fd054ed4f3..f879c237303a5958574ac0d938896679cf68a625 100644 (file)
@@ -32,7 +32,7 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.WsTestUtil;
 import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
-import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonarqube.ws.Batch.WsProjectResponse;
 import org.sonarqube.ws.client.HttpException;
 import org.sonarqube.ws.client.WsRequest;
index c48b0dc8aeb7289f0b8277d41408fe9201279ce4..acacf7eef32c6c24f9b9584ef1cded734d2f573d 100644 (file)
@@ -24,8 +24,8 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.batch.rule.ActiveRule;
 import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
-import org.sonar.api.batch.rule.NewActiveRule;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 
index e81930bf234ea7209acbff405780bf4bbeb567ad..b811f5e1008757da8e1ff2055b6250653596f8ad 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.slf4j.Logger;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
index 1bdce821151f21aa38226faacc2f224fec6202ea..87da83b2cd573b6f41c5ad7e02ee48f9397cb91f 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 18da6ddf5bff961a638471278bccef4d030c2203..f31bf8e60c0db05d3d51e3b3fed325965f8f0078 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.scanner.scan;
 import java.util.Arrays;
 import org.junit.Test;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
index 9ebc2cea34efa7664bf6e4a4d6fe6346626a0c25..4a1b0b5a4a2deac4d9a7a5e99b2c261d17f3f045 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 7241ab7b03a2122fc86f9b1470333dbea2a457fa..1b3221070534620310ce149df5f012d8794cb794 100644 (file)
@@ -27,9 +27,9 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 19797c845bd9f964e4400b94095152002b5d7add..ba7be118179dec8d53318dfaad98c0b96c3c1c15 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 4974350faf7fe87d7efc25656a0b13e003876d15..be8da961f4021e122cd2e793f13d464211c82b0d 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.scanner.scan.filesystem;
 import org.junit.Test;
 import org.sonar.api.batch.fs.FilePredicate;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 709b5960b9f05fbf8447cdc09b60a98ce0938306..98785e06e62febbcc052ba5815ee975fe59197a2 100644 (file)
@@ -32,10 +32,10 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputFile.Status;
 import org.sonar.api.batch.fs.InputFile.Type;
 import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 30a3a20d713a075656239247a27cf936e4084c57..7b8cd0c259da7d21339b7329fbc03b9c9c83d420 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.utils.MessageException;
index 8ec05f3294e8060cf4225462ef92c64c8f904d48..b3a2a09fe29ebc8025e0924ac360d80022078619 100644 (file)
@@ -34,9 +34,9 @@ import org.mockito.MockitoAnnotations;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.notifications.AnalysisWarnings;
 import org.sonar.api.utils.PathUtils;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.FileMetadata;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.issue.ignore.IgnoreIssuesFilter;
 import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader;
index 57386cb65e9a7d092061c575a643f83d09c57c44..44f5793df8f7259c57686f351a22444e17b2c8b1 100644 (file)
@@ -26,9 +26,9 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputModule;
-import org.sonar.api.impl.fs.SensorStrategy;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.SensorStrategy;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 
 import static org.assertj.core.api.Assertions.assertThat;
index af8c8156613d989cedf3a95a3741410dcc044aab..7e6540f69f1e87799308d90b8bc4599a08ae245e 100644 (file)
@@ -30,8 +30,8 @@ import org.junit.rules.TemporaryFolder;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.fs.IndexedFile;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.DefaultIndexedFile;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.batch.fs.internal.DefaultIndexedFile;
+import org.sonar.api.config.internal.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 10fc2c68e1ad710c0cbd9dd8573814dabb215ea5..857f12e9f69e9d8af4151374a5f202c5d4dd2671 100644 (file)
@@ -26,8 +26,8 @@ import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.scanner.repository.FileData;
 import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
 import org.sonar.scanner.repository.SingleProjectRepository;
index 5ea2bc5464c964f3669e0be90caf64e1891e04c4..78a9c53a4f36a15b0b24339b358c385eadc8348c 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.api.batch.scm.BlameLine;
 
 public class DefaultBlameOutputTest {
index 6304dcbd82f17b495975a9fcbaa1c9ac96604cea..0e4205c45e8700c95bb4aca8f941ad7d3a6be059 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.rules.ExpectedException;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.sonar.api.batch.scm.ScmProvider;
-import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 
index fe82b6429026b6f133127756e5701a876fb55105..264e666429f6a4bf2d74b807fa5a1192df522c07 100644 (file)
@@ -29,26 +29,26 @@ import org.junit.rules.TemporaryFolder;
 import org.mockito.ArgumentCaptor;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
 import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode;
 import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
 import org.sonar.api.batch.sensor.issue.ExternalIssue;
 import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
+import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.core.metric.ScannerMetrics;
-import org.sonar.api.impl.fs.DefaultInputDir;
-import org.sonar.api.impl.fs.DefaultInputFile;
-import org.sonar.api.impl.fs.DefaultInputModule;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultExternalIssue;
-import org.sonar.api.impl.sensor.DefaultHighlighting;
-import org.sonar.api.impl.sensor.DefaultMeasure;
-import org.sonar.api.impl.sensor.DefaultSignificantCode;
-import org.sonar.api.impl.sensor.DefaultSymbolTable;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
-import org.sonar.api.impl.issue.DefaultIssue;
-import org.sonar.api.impl.issue.DefaultIssueLocation;
 import org.sonar.scanner.issue.IssuePublisher;
 import org.sonar.scanner.protocol.output.FileStructure;
 import org.sonar.scanner.protocol.output.ScannerReport;
index dea7f4176d5a904b5aad230eae18f54290359cac..b1ef9c8bc9c595d97f0155fdde89b37d327b9e5e 100644 (file)
@@ -31,13 +31,13 @@ import org.sonar.api.batch.fs.InputModule;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.DefaultInputProject;
-import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.internal.SonarRuntimeImpl;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.Version;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 197749532c879de00c5752c47fb7939bc10a679f..1adbc0936b2967746831374f3f20a81ed627323e 100644 (file)
@@ -26,13 +26,13 @@ import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.NewActiveRule;
-import org.sonar.api.impl.config.MapSettings;
-import org.sonar.api.impl.fs.DefaultFileSystem;
-import org.sonar.api.impl.fs.TestInputFileBuilder;
-import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.batch.rule.internal.NewActiveRule;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.api.impl.rule.ActiveRulesBuilder;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;