]> 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>
Wed, 19 Jun 2019 18:56:51 +0000 (13:56 -0500)
committerSonarTech <sonartech@sonarsource.com>
Fri, 12 Jul 2019 18:21:14 +0000 (20:21 +0200)
746 files changed:
plugins/sonar-xoo-plugin/build.gradle
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-common/src/test/java/org/sonar/ce/queue/CeQueueImplTest.java
server/sonar-ce-task-projectanalysis/build.gradle
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/analysis/ProjectConfigurationFactory.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/filesystem/ComputationTempFolderProvider.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/batch/BatchReportReaderImplTest.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/source/SourceLinesHashCacheTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/SourceLinesHashRepositoryImplTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStepTest.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/queue/InternalCeQueueImplTest.java
server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskInterrupterProviderTest.java
server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorModuleTest.java
server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeWorkerImplTest.java
server/sonar-db-core/build.gradle
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/build.gradle
server/sonar-db-dao/src/test/java/org/sonar/db/alm/OrganizationAlmBindingDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeQueueDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/AnalysisPropertiesDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/BranchDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/ProjectLinkDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/es/EsQueueDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueMapperTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileChangeDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditGroupsDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditUsersDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleRepositoryDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/user/UserPropertiesDaoTest.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/v62/PopulateOrganizationUuidOfGroupsTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v63/UnsetUserRootFlagsTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/PopulateOrgQProfilesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/PopulateTableDefaultQProfilesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v65/PopulateUsersOnboardedTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v66/FixEmptyIdentityProviderInUsersTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v66/PopulateMainProjectBranchesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v67/CleanupDisabledUsersTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateBuiltInQualityGateTest.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/v70/PopulateDefaultQualityGateTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateLiveMeasuresTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateQualityGatesIsBuiltInTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/PopulateUuidOnQualityGatesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrgTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGateTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/PopulateTableProjectLinks2Test.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/SetKeyTypeToBranchInProjectBranchesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/FixDuplicationInExternalLoginOnUsersTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/PopulateHashMethodOnUsersTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/PopulateOrganizationUuidOnUsersTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/PopulateUUIDOnUsersTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/UpdateNullValuesFromExternalColumnsAndLoginOfUsersTest.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/PopulateMainApplicationBranchesTest.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/v74/PopulateDefaultPermTemplateOnOrganizationsTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateIsAdHocOnRulesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/PopulateNullValuesOfIsExternalOnRulesTest.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/v76/MigrateModulePropertiesTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v76/MigrateNoMoreUsedQualityGateConditionsTest.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/build.gradle
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/platform/TempFolderProvider.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/BulkIndexerTest.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/l18n/ServerI18nTest.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/rule/index/RuleIndexTest.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/build.gradle
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultDebtRemediationFunctions.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewParam.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewRepository.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewRule.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultParam.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRepository.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRule.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionContext.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionsLoader.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/UpdateAction.java
server/sonar-server/src/main/java/org/sonar/server/util/TempFolderCleaner.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ws/LocalRequestAdapter.java
server/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java
server/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.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/UserLastConnectionDatesUpdaterImplTest.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/ce/ws/CancelActionTest.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/WebIssueStorageTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityHotspotsTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexSecurityReportsTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexSortTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/AssignActionTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/BulkChangeActionTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/DoTransitionActionTest.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/custom/ws/UpdateActionTest.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/PermissionTemplateServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndexDefinition.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/CreateTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.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/project/ws/UpdateDefaultVisibilityActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ProjectsInWarningDaemonTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileInsertImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesUpdateListenerTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileBackuperImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileCopierTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileExportersTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileResetImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRuleImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileTreeImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangelogActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CopyActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileReferenceTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/CachingRuleFinderTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/DeprecatedRulesDefinitionLoaderTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.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/DeactivateActionTest.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/usergroups/ws/AddUserActionTest.java
server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java
server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/RemoveUserActionTest.java
server/sonar-server/src/test/java/org/sonar/server/ws/TestRequest.java
server/sonar-server/src/test/java/org/sonar/server/ws/WebServiceFilterTest.java
server/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java
settings.gradle
sonar-application/build.gradle
sonar-application/src/main/java/org/sonar/application/App.java
sonar-core/build.gradle
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/i18n/DefaultI18nTest.java
sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java
sonar-plugin-api-impl/build.gradle [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultActiveRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/rule/DefaultRuleParam.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/ConfigurationBridge.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MapSettings.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/MultivalueProperty.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/MetadataLoader.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/PluginContextImpl.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/SonarRuntimeImpl.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/context/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/AbstractProjectOrModule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultFileSystem.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultIndexedFile.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputComponent.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputDir.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputFile.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputModule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultInputProject.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextPointer.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/DefaultTextRange.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/FileMetadata.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/Metadata.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/PathPattern.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/SensorStrategy.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/TestInputFileBuilder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/CharHandler.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/FileHashComputer.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/IntArrayList.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineCounter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineHashComputer.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/LineOffsetCounter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/charhandler/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbsolutePathPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AbstractFilePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/AndPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicates.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FalsePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/FilenamePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/LanguagePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/NotPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OperatorPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OptimizedFilePredicateAdapter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/OrPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/PathPatternPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/RelativePathPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/StatusPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TruePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/TypePredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/URIPredicate.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/fs/predicates/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/AbstractDefaultIssue.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssue.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultIssueLocation.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/DefaultNoSonarFilter.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/issue/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/ActiveRulesBuilder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultActiveRules.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/DefaultRules.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/rule/RulesBuilder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAdHocRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultAnalysisError.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCoverage.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultCpdTokens.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultExternalIssue.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultHighlighting.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultMeasure.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultPostJobDescriptor.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSensorDescriptor.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSignificantCode.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultStorable.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/DefaultSymbolTable.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/InMemorySensorStorage.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SensorContextTester.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/SyntaxHighlightingRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/sensor/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultDebtRemediationFunctions.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewParam.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewRepository.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultParam.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultRepository.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultRule.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/RuleDefinitionContext.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/AlwaysIncreasingSystem2.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/JUnitTempFolder.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/ScannerUtils.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/TestSystem2.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/WorkDuration.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/PartImpl.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/SimpleGetRequest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/ValidatingRequest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/package-info.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MapSettingsTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/config/MultivaluePropertyTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/MetadataLoaderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/context/SonarRuntimeImplTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultFileSystemTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputDirTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputFileTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputModuleTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/DefaultInputProjectTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/FileMetadataTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/MetadataTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/PathPatternTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/TestInputFileBuilderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/charhandler/IntArrayListTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/AndPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/DefaultFilePredicatesTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FileExtensionPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/FilenamePredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/OrPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/fs/predicates/RelativePathPredicateTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/DefaultRulesTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/rule/RulesBuilderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAdHocRuleTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultAnalysisErrorTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultCpdTokensTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultExternalIssueTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultHighlightingTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueLocationTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultIssueTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultMeasureTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSensorDescriptorTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSignificantCodeTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/DefaultSymbolTableTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/InMemorySensorStorageTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/sensor/SensorContextTesterTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/server/DefaultNewRuleTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/AlwaysIncreasingSystem2Test.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/DefaultTempFolderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/JUnitTempFolderTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/ScannerUtilsTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/WorkDurationTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/ws/SimpleGetRequestTest.java [new file with mode: 0644]
sonar-plugin-api-impl/src/test/resources/org/sonar/api/impl/fs/glyphicons-halflings-regular.woff [new file with mode: 0644]
sonar-plugin-api/build.gradle
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java
sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/internal/MetadataLoader.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/internal/PluginContextImpl.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/internal/package-info.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/rules/Rule.java
sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/PartImpl.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/package-info.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/utils/Preconditions.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TempFolderCleaner.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TestSystem2.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/WorkDuration.java [deleted file]
sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/package-info.java [deleted file]
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/fs/internal/MetadataTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java [deleted file]
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 [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/config/EmailSettingsTest.java
sonar-plugin-api/src/test/java/org/sonar/api/config/internal/MapSettingsTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/config/internal/MultivaluePropertyTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/internal/MetadataLoaderTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/issue/NoSonarFilterTest.java
sonar-plugin-api/src/test/java/org/sonar/api/rules/RuleTest.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-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java
sonar-plugin-api/src/test/java/org/sonar/api/server/ws/internal/SimpleGetRequestTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2Test.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/DefaultTempFolderTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/JUnitTempFolderTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/WorkDurationTest.java [deleted file]
sonar-scanner-engine/build.gradle
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/DefaultScannerWsClient.java [new file with mode: 0644]
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/bootstrap/GlobalTempFolderProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginInstaller.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClient.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.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/AbstractProjectOrModule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultFileSystem.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultIndexedFile.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputComponent.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputDir.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputFile.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputModule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputProject.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultTextPointer.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultTextRange.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/FileMetadata.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/InputModuleHierarchy.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/TestInputFileBuilder.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/CharHandler.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/FileHashComputer.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/IntArrayList.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineCounter.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineHashComputer.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineOffsetCounter.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/package-info.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AbsolutePathPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AbstractFilePredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AndPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/DefaultFilePredicates.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FalsePredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FileExtensionPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FilenamePredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/LanguagePredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/NotPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OperatorPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OptimizedFilePredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OptimizedFilePredicateAdapter.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OrPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/PathPatternPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/RelativePathPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/StatusPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/TruePredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/TypePredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/URIPredicate.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/AbstractDefaultIssue.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultIssue.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultIssueLocation.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultNoSonarFilter.java [deleted file]
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/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/platform/DefaultServer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/DefaultPostJobDescriptor.java [deleted file]
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/ReportPublisher.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/DefaultMetricsRepositoryLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ProjectRepositories.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/AbstractSettingsLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/DefaultProjectSettingsLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesBuilder.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRules.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRulesLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRuleParam.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRules.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRulesLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/LoadedActiveRule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/NewActiveRule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/NewRule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/NewRuleParam.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesBuilder.java [deleted file]
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/DefaultAdHocRule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAnalysisError.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultCoverage.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultCpdTokens.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultExternalIssue.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultHighlighting.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultMeasure.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorDescriptor.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSignificantCode.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultStorable.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSymbolTable.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java [deleted file]
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/sensor/SensorContextTester.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SyntaxHighlightingRule.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/ZeroCoverageSensor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/util/ScannerUtils.java [deleted file]
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/WsTestUtil.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisTempFolderProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/DefaultScannerWsClientTest.java [new file with mode: 0644]
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/bootstrap/ScannerPluginInstallerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientTest.java [deleted file]
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/fs/DefaultFileSystemTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputDirTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputFileTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputModuleTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputProjectTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/FileMetadataTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/TestInputFileBuilderTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/charhandler/IntArrayListTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/AndPredicateTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/DefaultFilePredicatesTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/FileExtensionPredicateTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/FilenamePredicateTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/OrPredicateTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/RelativePathPredicateTest.java [deleted file]
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/mediumtest/issues/ChecksMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/IssuesMediumTest.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/DefaultMetricsRepositoryLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultProjectSettingsLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesBuilderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultRulesLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultRulesTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/NewActiveRuleTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/RulesBuilderTest.java [deleted file]
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/DefaultAdHocRuleTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultAnalysisErrorTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultCpdTokensTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultExternalIssueTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultHighlightingTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultIssueLocationTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultIssueTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultMeasureTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorDescriptorTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSignificantCodeTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSymbolTableTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/InMemorySensorStorageTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorOptimizerTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/SensorContextTesterTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ScannerUtilsTest.java
sonar-scanner-engine/src/test/resources/org/sonar/scanner/fs/glyphicons-halflings-regular.woff [deleted file]

index eb6a3c603b5828ab2ee03be4253064e7fcaed12c..675726d0a6eefd65bade66a5b891700ad58c0fc5 100644 (file)
@@ -11,11 +11,10 @@ dependencies {
   runtime project(path: ':sonar-plugin-api', configuration: 'shadow')
   compileOnly project(path: ':sonar-plugin-api')
 
-  testCompile project(path: ':sonar-scanner-engine')
   testCompile 'junit:junit'
   testCompile 'org.assertj:assertj-core'
   testCompile 'org.mockito:mockito-core'
-  testCompile project(':server:sonar-server')
+  testCompile project(':sonar-plugin-api-impl')
 }
 
 jar {
index 892081dc202eacad0a60354a01df736046a78284..7455f077caa6e007d95ce743a94742f6e4be020a 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.internal.PluginContextImpl;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.PluginContextImpl;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
 import org.sonar.xoo.global.GlobalProjectSensor;
 import org.sonar.xoo.rule.OneExternalIssuePerLineSensor;
index 1f5128ddc7985dacc576c1faaa4b845207202d47..161cac8649f29d246bf4f9f14fd82b4dea2a10b1 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.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index a6c8878084001700aba7064564860b7b0f4b82ff..71c336163f2e898af8580f23d0e91187ea2442f1 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.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 429a64722fdfa4db24bb9a669129d82d1ecf5e0b..dde6eddac2c475ca476e69d4c3617439621c65c4 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.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 5474f266af63059ffe46c1ff832dd8b0ba84fc59..0754cdc12c0bda41e497d88ded9bcd20610ca33d 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.scanner.postjob.DefaultPostJobDescriptor;
+import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 1464eaa8e626553dbd3c744f1a36afe98aa7d223..aaad31d3da411206fecd62b2c1ae127a6e2c68ee 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.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.DefaultSensorDescriptor;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
index 5d36dcf4097ad862a5dff59a4bdb260fd553213e..bc6e6b0050038b7f65a4a9e5f329f3c49de9e761 100644 (file)
@@ -30,11 +30,11 @@ 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.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 5bd1c1377a5c903620ffa46a8dcc6cb1b013faeb..6acb0ed39e1322253808c74320eab153bbf1abcb 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.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.fs.DefaultTextRange;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
+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 static org.assertj.core.api.Assertions.assertThat;
 
index a15596379af2445aee10ea26a1f9863d28bcbdc5..1e91363bbed78f2f02be7a6214c17da9b1876c61 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.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.fs.DefaultTextRange;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
+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.xoo.Xoo;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 8cc02238d0acf6a275164ebd7569e38e64a3127f..fc4e865dc018cd1d934e09993b417efe38ceef01 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
+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 static org.assertj.core.api.Assertions.assertThat;
 
index 2f7d074ca101d7048325fbeb87d58d8bc6851e35..060925067e47523027dd96b0131888d59ad8fdab 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.SensorContextTester;
+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 static org.assertj.core.api.Assertions.assertThat;
 
index 67f9325575c07b59796f48f68a9012d0662dd59c..24bec8caf7db080ba1949b221a5aa998996d170a 100644 (file)
@@ -27,12 +27,12 @@ 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.internal.SonarRuntimeImpl;
+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.utils.Version;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
-import org.sonar.scanner.sensor.SensorContextTester;
 import org.sonar.xoo.Xoo;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 2a4c1eda98b5a81ede05c53aa11f3898c05d1a92..e37c8f5df6a668846058bb9fe21c67d0cb8082fa 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.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.rule.RulesDefinition;
 import org.sonar.api.utils.Version;
-import org.sonar.server.rule.RuleDefinitionContext;
+import org.sonar.api.impl.server.RuleDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 2b02d2df949971ae61700ebc247ebc9ec7db2550..13a780e7dc7ac836862372a8b116ac66d3cd954e 100644 (file)
@@ -31,10 +31,10 @@ 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.utils.DateUtils;
-import org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
 import org.sonar.xoo.Xoo;
 
 import static java.util.Collections.singletonList;
index 6f44b7e42b018cba6d87c2b6350c79bdb552fbe4..099da826dea454b0c83432ea05bffff95c8b3d60 100644 (file)
@@ -28,8 +28,8 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.ce.queue.CeTaskSubmit.Component;
 import org.sonar.ce.task.CeTask;
 import org.sonar.core.util.UuidFactory;
@@ -215,7 +215,6 @@ public class CeQueueImplTest {
     CeTaskSubmit taskSubmit2 = createTaskSubmit("some type");
     UserDto userDto1 = db.getDbClient().userDao().selectByUuid(db.getSession(), taskSubmit1.getSubmitterUuid());
 
-
     List<CeTask> tasks = underTest.massSubmit(asList(taskSubmit1, taskSubmit2));
 
     assertThat(tasks).hasSize(2);
@@ -370,7 +369,7 @@ public class CeQueueImplTest {
 
     assertThat(tasks)
       .hasSize(2)
-      .extracting(task -> task.getComponent().get().getUuid(),task -> task.getMainComponent().get().getUuid())
+      .extracting(task -> task.getComponent().get().getUuid(), task -> task.getMainComponent().get().getUuid())
       .containsOnly(tuple(componentForMainComponentUuid2.getUuid(), componentForMainComponentUuid2.getMainComponentUuid()),
         tuple(componentForMainComponentUuid4.getUuid(), componentForMainComponentUuid4.getMainComponentUuid()));
     assertThat(db.getDbClient().ceQueueDao().selectAllInAscOrder(db.getSession()))
@@ -609,6 +608,7 @@ public class CeQueueImplTest {
   }
 
   private static int newComponentIdGenerator = new Random().nextInt(8_999_333);
+
   private static Component newComponent(String mainComponentUuid) {
     return new Component("uuid_" + newComponentIdGenerator++, mainComponentUuid);
   }
index 82d6f4af8429661dba28d062ee9b23515f33125f..62914da5e86a1eaa0ef88fbfd8013f3212b693e2 100644 (file)
@@ -33,6 +33,7 @@ dependencies {
   compileOnly project(':server:sonar-process')
   compileOnly project(':server:sonar-server-common')
   compileOnly project(':sonar-plugin-api')
+  compileOnly project(':sonar-plugin-api-impl')
   compileOnly project(':sonar-duplications')
 
   testCompile 'com.google.code.findbugs:jsr305'
index 75f7c85218714740388335b19730fd622e5686f2..1c7af5ed99c12033685ae51743d6c8f6b27e7d46 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.config.internal.ConfigurationBridge;
+import org.sonar.api.impl.config.ConfigurationBridge;
 import org.sonar.db.DbClient;
 import org.sonar.db.component.BranchType;
 import org.sonar.server.setting.ChildSettings;
index 718329b630250efb61ac22419d243920a388f853..be955030af4c662076586cd91b962870d819f65d 100644 (file)
@@ -26,8 +26,8 @@ import org.apache.commons.io.FileUtils;
 import org.picocontainer.ComponentLifecycle;
 import org.picocontainer.PicoContainer;
 import org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.impl.utils.DefaultTempFolder;
 import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.internal.DefaultTempFolder;
 import org.sonar.server.platform.ServerFileSystem;
 
 /**
index 8b91d9fe5b55d866695fca1779a471978feca468..1587d3f49bf7553c9825758b62ddb57ee0a3cf7b 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.ce.task.projectanalysis.component.DefaultBranchImpl;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
index 783adc1ab6c358ed0b1e52da482943426bec1b3f..ad305a455ce4f8b1d6d5cd9bf3d604749c5d94df 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.Duration;
index 8c44a3418e8e633404450b656479314b0e1005d1..dec49ef29d743e9fc6b0ad21df3060d72f4e50c5 100644 (file)
@@ -26,7 +26,7 @@ import org.apache.commons.io.FileUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.utils.internal.JUnitTempFolder;
+import org.sonar.api.impl.utils.JUnitTempFolder;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
index 240637cc3e6c59601e897fcf8bac16d84f39a46e..948f94f4fde8dbe043c00776a142504029d267f6 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
 import org.sonar.ce.task.projectanalysis.analysis.Branch;
index a2a66c69f7cfd33882ca5987c746747c852e7721..dfd6311e802d1d78b4bcda1df4343bd6ea96b544 100644 (file)
@@ -25,8 +25,8 @@ import java.util.Collection;
 import java.util.Collections;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.ce.task.log.CeTaskMessages;
index 63d6cd19a90472a9866567e9fdf12b10b5b4cea7..00d9a76ac190bc9238d940a73e43255eaf0c0beb 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.ce.task.CeTask;
 import org.sonar.ce.task.projectanalysis.filemove.ScoreMatrix.ScoreFile;
 
index 5224fe99cba57f13fac44505a6e8e5252c631a29..cd7249ce51fabe59c0266fc00ec7872c871e3532 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.utils.System2;
 import org.sonar.core.issue.DefaultIssue;
index 934a2546730d74536324b9a28d06374fba264ac0..1bcc1485405e1a5d88b9a5555666f2a57427adad 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.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 4c4ba86943e99ec340c77642499bd192974e293d..9be4ccbc5b023f1f1492b629651a94bf230529c0 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
index 44dc2af2e1fced572ff0a332d0758bd6b8d1e7f4..ecec80844796554a615b1ea143569062211715a8 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
 import org.sonar.ce.task.projectanalysis.component.Component;
index 16e7419b6288aae503b911c2e456b90f9d3501cf..fbafc6ba2576330b079772acb92ed3bfa02d97f0 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.System2;
index 01178f2275ed9aacb9ce8e0551cc3cff497ff156..0672bf65c120f1b13b993a178c786b59d2da8548 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository;
index 1315ab2f7d637de5bcf9cb7bcbf09d22d3b63b7f..d1cef3b521e131f7d6d3638739a1e0a01bd998f9 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.config.PurgeConstants;
 import org.sonar.core.config.PurgeProperties;
 import org.sonar.db.DbSession;
index dbf8227eaee88ef540999e558ac31b83ba3bf05e..877fa6965a96ff064bb41c2d3f72b52abfe3d1d8 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.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 583315747569e1d25598a0d13b50913e3206edce..6e83dd97d6167c42ee23a1e0f28f2e4d2e893be7 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.MessageException;
 import org.sonar.core.config.CorePropertyDefinitions;
index e361c519083b5693f676a82e38f3bb44077313db..34de2e3717093fc2c199ae0d7b679a900a6f767c 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.internal.JUnitTempFolder;
+import org.sonar.api.impl.utils.JUnitTempFolder;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
 
index 67bce16c807c87e08dd947da1f41c8ab482911ba..0d7f00d10f9f4177310f3315adad4f6b67a556a4 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.utils.internal.JUnitTempFolder;
+import org.sonar.api.impl.utils.JUnitTempFolder;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.Component.Type;
 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
index a31a5ddbb79bb60b3139af9affa7b4931ecb8123..0e565f84b85664f37283e502276da6230bf6c649 100644 (file)
@@ -26,10 +26,10 @@ import org.apache.commons.io.FileUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.JUnitTempFolder;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.ZipUtils;
-import org.sonar.api.utils.internal.JUnitTempFolder;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.ce.task.CeTask;
index c2b3b13c679044092831770abf7aeb37fd6eca64..a5389373f8e2ce2397e745f858bf4a192f58595e 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.LogAndArguments;
index 809c2505fd6038dd8f5287aa4efe9ecdae56b1c6..eaee9b9da1b62ab24473fd43d071457b87741cf1 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.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 2358876fb0e92ef4999ae497f6e59f4f7fddc162..51eabf72207db263db7cf7b7c4469266e199893f 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.internal.MetadataLoader;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.MetadataLoader;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.profiles.AnnotationProfileParser;
 import org.sonar.api.profiles.XMLProfileParser;
 import org.sonar.api.profiles.XMLProfileSerializer;
index ac9b41655fbd8d975043999ba376351ed0ad9b87..eb6c5923d5991977f3f1166e50553727dbf72ca5 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.config.internal.ConfigurationBridge;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.ConfigurationBridge;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
 
 import static java.lang.Math.abs;
index d308f13ae07db78aa86e41fbbc42e18055c0e2ef..a271c5747ddcb028b2753c0ab91b3a2a17d9d3e1 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.ce.configuration;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 
index 771b13c21a25823c231fa7bfabb11329441cb8bd..fd96fe75b70bc6162f72cddbeba7919db41a9fc6 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.ServerUpgradeStatus;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
index e54545f41811fe7c4e0f923e04e95bcd5e4eae69..fc24e02b9f9af39fdb064da2f8a382d6362bf592 100644 (file)
@@ -29,8 +29,8 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.ce.container.ComputeEngineStatus;
 import org.sonar.ce.monitoring.CEQueueStatus;
 import org.sonar.ce.monitoring.CEQueueStatusImpl;
index 284c8efc3f0124b47a18e8a9e42453b8ae792094..3bb899e9ff2027df911159fff7a835dc1df60355 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.task.CeTaskInterrupter;
 
index cd2240402564589aef25c7da2ae95176c7134372..6f31cabdf4718e1c6385ee7371da1f55d246abe6 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.ce.taskprocessor;
 
 import org.junit.Test;
 import org.picocontainer.ComponentAdapter;
-import org.sonar.api.config.internal.MapSettings;
 import org.sonar.ce.notification.ReportAnalysisFailureNotificationExecutionListener;
 import org.sonar.ce.task.CeTaskInterrupter;
 import org.sonar.core.platform.ComponentContainer;
index 08d19ce3ad5919221d6eaabf5c2b42c9b22f7d93..a84aa27024b36e7a0b536848efc8dd2ee68f675e 100644 (file)
@@ -38,9 +38,9 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mockito;
 import org.mockito.stubbing.Answer;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.api.utils.log.LogAndArguments;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
index 34228167f41021aecfc935b48a2ddf9c44dabb3e..5e1cfc7b748108b0567200491b20039e9972a40b 100644 (file)
@@ -20,6 +20,7 @@ dependencies {
   compile project(':sonar-core')
   compile project(':sonar-scanner-protocol')
   compile project(path: ':sonar-plugin-api', configuration: 'shadow')
+  compile project(':sonar-plugin-api-impl')
 
   compileOnly 'com.google.code.findbugs:jsr305'
 
index e673d167ac4457096316584be7ba5d7f66a1b429..035c4049ed46e3e5919887dba2edf79b6f791fe4 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.db.dialect.H2;
index 45a55796ff553583fcc89c7365745dfeb93f48b2..6c27183b9540ec465cd98742e0033a9e0f92a003 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.db.dialect.PostgreSql;
 import org.sonar.process.logging.LogbackHelper;
 
index 01cc6e29841809d4e8af1f6cfdfbacf83826197a..12e9ed4500f96ca062eabfbd4c5f08545cdd3591 100644 (file)
@@ -21,6 +21,7 @@ dependencies {
   testCompile 'org.mockito:mockito-core'
   testCompile project(':sonar-testing-harness')
   testCompile project(':server:sonar-db-core').sourceSets.test.output
+  testCompile project(':sonar-plugin-api-impl')
 
   testCompileOnly 'com.google.code.findbugs:jsr305'
 
index b104f9a6dd4cac962ba9039c9211fa1f8bd1057b..7e16fe3471341786084c0a71a00a7eb7ba919aad 100644 (file)
@@ -24,7 +24,7 @@ import java.util.Optional;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
index 549f3bb20e2961e8506d6873a1dc2a5bac3ee6e6..5478d3ab9690c1ae162dba21c7dcff72814613cf 100644 (file)
@@ -39,7 +39,7 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.core.util.stream.MoreCollectors;
index 7e6bce920e5a7573d2a14b169c66c1f993eb18e0..dd2b3a3aab863703e248b1720ac05e2c05abc2f2 100644 (file)
@@ -34,9 +34,9 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.DbTester;
 
 import static com.google.common.collect.FluentIterable.from;
@@ -178,7 +178,7 @@ public class CeQueueDaoTest {
     long time = alwaysIncreasingSystem2.now() + 10_000;
     insertPending("p1", dto -> {
       dto.setCreatedAt(time);
-      dto.setUpdatedAt(time+500);
+      dto.setUpdatedAt(time + 500);
       dto.setMainComponentUuid("c1");
     });
     insertPending("p2", dto -> {
@@ -198,7 +198,7 @@ public class CeQueueDaoTest {
     long time = alwaysIncreasingSystem2.now() + 10_000;
     insertPending("p1", dto -> {
       dto.setCreatedAt(time);
-      dto.setUpdatedAt(time+500);
+      dto.setUpdatedAt(time + 500);
       dto.setMainComponentUuid("c2");
     });
     insertPending("p2", dto -> {
@@ -215,7 +215,7 @@ public class CeQueueDaoTest {
     makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1", dto -> dto.setMainComponentUuid("c1")));
 
     assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), "c1"))
-      .isEqualTo(Optional.of(time+2000));
+      .isEqualTo(Optional.of(time + 2000));
   }
 
   @Test
index 2ddbc0c36c6366d033b1a1ce2c4017dc6513b520..cd739ae558e00c7b6294bf4ec9240e00270b00ac 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 
index e43fca45abd2ffdce6bcfa02b7d3854d367c53ef..08ef36f8c54fcd6dd0298a16d756660ab9b57910 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.protobuf.DbProjectBranches;
index 17bb6b45f245c52396c75749be92ed38111472de..3c8509ee85185d264abff1b5a2bec9da7cf99073 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Collections;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 
 import static java.util.Arrays.asList;
index 41707c4e73c5cbd67d9e3cca2252075a1723519e..00776044ce655cbd1bb6715f37fa578c7aff045c 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Random;
 import java.util.stream.IntStream;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index ed19baa0efb5b6ecb82eb41f1b04edd1ab7a0534..04bd0f63e8bbe99812ffe30b5acd81597edd3cc7 100644 (file)
@@ -35,11 +35,11 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.issue.FieldDiffs;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.DbSession;
index 849dd53dfe7dedb4d4a680277e617a250f02359d..716c1e303376d62283018e268f72c3a2d292f3bf 100644 (file)
@@ -23,8 +23,8 @@ import java.util.List;
 import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
@@ -36,7 +36,6 @@ import static com.google.common.collect.Lists.newArrayList;
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
 
-
 public class PurgeCommandsTest {
 
   @Rule
@@ -106,7 +105,6 @@ public class PurgeCommandsTest {
     assertThat(dbTester.countRowsOfTable("issue_changes")).isEqualTo(1);
   }
 
-
   @Test
   public void shouldDeleteAnalyses() {
     dbTester.prepareDbUnit(getClass(), "shouldDeleteResource.xml");
@@ -122,7 +120,6 @@ public class PurgeCommandsTest {
     assertThat(dbTester.countRowsOfTable("issue_changes")).isEqualTo(1);
   }
 
-
   @Test
   public void shouldDeleteIssuesAndIssueChanges() {
     dbTester.prepareDbUnit(getClass(), "shouldDeleteResource.xml");
index 4d83aa022e7eaeca177de9d6b0adc995c206669d..fe0d5668a7699b7736132378fff58d8bc9de9cd2 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Scopes;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
index abfb197c9808a2961ec9a5220d897aa7f22c5813..a9db8b7a3678943e11995d061d66538452b0fc0c 100644 (file)
@@ -32,7 +32,7 @@ import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.rule.RuleParamType;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
index 530239bc91a0ab67a55e4dcbb44eec0546a9b31c..4d26dcc207a0be5033112dc3f4fb2f1cc4d6b5de 100644 (file)
@@ -25,8 +25,8 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.util.SequenceUuidFactory;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.DbSession;
index c95aeca5fe090a888874e05d357cd26b7740bb85..06b3aa1cceed7a71e2a17c0e17cb1a8be88fade3 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.db.qualityprofile;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.Pagination;
 import org.sonar.db.organization.OrganizationDto;
index cb915cd8044a1591a0c66d6a432e05ec437cd921..5331f8d309841a39a414dcc68a62caaa556af136 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.Pagination;
 import org.sonar.db.organization.OrganizationDto;
index 520636d1eaf7d4cedebf842bcee30b964ae1d3d6..d011fa394cb2a4b8a967dc449444c08e2286776f 100644 (file)
@@ -27,8 +27,8 @@ import java.util.stream.IntStream;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 
index 5e55b7a7706d501d0b6acdbc77875090193645bd..e739b57e69a2ea6dbbf577c3bb229259591a2e36 100644 (file)
@@ -27,7 +27,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.user.UserQuery;
 import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DatabaseUtils;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
index 89029d67899557389a2de249e08b9262b4e96f32..8fba61e47b43d3782811133717a87f48a529370d 100644 (file)
@@ -23,7 +23,7 @@ import java.util.List;
 import java.util.Map;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 9f02622b7a8bd6f0b0be0871c40d031604fc05dc..cab3aa7752e67c71adc380d858e062e8b18db198 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.config.internal.ConfigurationBridge;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.ConfigurationBridge;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.process.ProcessProperties;
 import org.sonar.server.platform.db.migration.SupportsBlueGreen;
index 5ce23f921d9e585cfa742ca370c993ab9e0363ae..aeaf1e615b8a21b470760a73698afea19d16dd8e 100644 (file)
@@ -23,8 +23,8 @@ import java.sql.SQLException;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index c35da8cec847efef4a22289e368cc992b02460d3..e26d65919a2a32ef116fe8ee6c89fb0fca4fcf03 100644 (file)
@@ -24,7 +24,7 @@ import java.util.Map;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index d143144ed0b311b8b207d15d2b351d7bb2dd1d32..1ba1f93d07d6dfeb7708276b9220d3e4934bdabe 100644 (file)
@@ -27,8 +27,8 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static java.lang.String.format;
index 3b2842b00ac52d8a85d19161ae516fd6915533d0..63441a8b0ffc707a3b10792650e23e8f6102aaa1 100644 (file)
@@ -23,8 +23,8 @@ import java.sql.SQLException;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
index 08026834445921c97faf3bd7097f76382c999539..32f20211fa9b34251a8ade3bf0919ec0d63664c7 100644 (file)
@@ -24,8 +24,8 @@ import java.util.stream.Collectors;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 1d217b274609a0e1036bfe1edbaef5f5e4228588..b66f41554ce5b714b4948cc84465750c994c558b 100644 (file)
@@ -26,8 +26,8 @@ import javax.annotation.Nullable;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 84ee674eeda9fefeb055ce60008787ae9074a151..19ba119e1eace6e385f7e4098426b3737b60e4d0 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.CoreDbTester;
 
index 1a8bbc3fabaed32d330b93da2d79f6f01181e9d6..67b31d2f00d7f26ebb473c8183325c9caedf16ef 100644 (file)
@@ -31,8 +31,8 @@ import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
index fcec9f0a7242683a0a0a38e393eb683b8622d9bd..0cf211714909cd1cb1461445b62dec9b5f00e3b0 100644 (file)
@@ -25,8 +25,8 @@ import java.util.List;
 import java.util.Map;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.CoreDbTester;
index e0d21418e1628abc6e1b3ecba6967cdc24327a5c..35bf49c836309673106b7287bc7b30ca890caad6 100644 (file)
@@ -24,6 +24,7 @@ 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 58a4d4f2103d31bdc97bb749bbab33e3f1f9b601..878af9a627f1237d4022f22ff972d5e7207bef91 100644 (file)
@@ -24,8 +24,8 @@ import java.util.Date;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.CoreDbTester;
 
index f125ad3f0fbb5a5b176f577d2455489053ef383f..6368c94bfaf8c300116f892b9c4c598295a88d47 100644 (file)
@@ -26,8 +26,8 @@ import java.util.function.Function;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index e06f71fb0cb94a16f8467fbb2406d00ecd03c5fe..b0b29531c76454b7e9b7e5fe17ab0ac67c8444b4 100644 (file)
@@ -27,8 +27,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 24063694929e265807fa5ef36fb1d6c7257f2bc7..103c1012ee405f72f992c4eba0fdd037532988cd 100644 (file)
@@ -24,13 +24,12 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import javax.annotation.Nullable;
-import org.assertj.core.api.AbstractListAssert;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
 
index 0365cc03dd190736035ab347f2044ffd34511006..f75e4689705475ba75e789064cbcbac987848ff9 100644 (file)
@@ -27,8 +27,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.CoreDbTester;
 import org.sonar.server.platform.db.migration.step.DataChange;
index 21859785b138168038665d94d6411f486dc05fb0..2caa9acb40e8797acb5cb67f5d2f2e0b5ddef23f 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.db.CoreDbTester;
 
index 4f20285bf162f8dfb1798ba2edc79e3516fd5b70..6781b442b39408406e954f92b6dbb74c209fc09e 100644 (file)
@@ -25,8 +25,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.SequenceUuidFactory;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.CoreDbTester;
index c82890e4fa2d92bb68eae27da8ade81fc743a893..42eb8745fb4333ab6afdae6b4878b7d13e87f892 100644 (file)
@@ -24,8 +24,8 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index c3f9c827e315b5e1c9b9517294925123afc90c50..9212a8b2d1357360b15b1e3ccf4657706b495eeb 100644 (file)
@@ -25,8 +25,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index eb39027bc76e50bade914f72b6e145aba1b1a4f4..21d33f7e27cf29145ce76610ef5ea9316f88de23 100644 (file)
@@ -25,8 +25,8 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
index b67086a24ecec117572b3fa7fabe725b428d3e88..a80ce88316ca18a24c7cf36f2f845e83ef8a169c 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -127,4 +127,4 @@ public class PopulateOrganizationUuidOnUsersTest {
       "UPDATED_AT", PAST);
   }
 
-}
\ No newline at end of file
+}
index a3acdbdedc404f3abe30964bfd9ad6e18d6b9346..fc8f82b864d2cb08cd862d98c348a93e3e01969b 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
index f0287e2a1e7b2aae22b2792c0393a1bf3fc085c8..313ad1b2dbbf08e82b02e747951d508381b9eb78 100644 (file)
@@ -25,8 +25,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.core.util.SequenceUuidFactory;
index 3d9cc81d15104b4ea8688fd102f9de6e3a0e8348..787dec23b9318b7615d4f4720b7da2a72b7586c6 100644 (file)
@@ -25,9 +25,9 @@ import java.util.stream.Collectors;
 import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.CoreDbTester;
index 65bcc39bfc01a8f76ce5291a7391695296244448..83a78d80bebffde35860c1252257c8d410d2296e 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.CoreDbTester;
 
index 80d62cff865400f91d3b664ba07c49c807b2865a..de32e5f073024fa1757546127c2759230763c961 100644 (file)
@@ -26,9 +26,9 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.CoreDbTester;
 
index f50108a334df87602552615cda712240bce00279..82077969b155e14893c0f203271015f397af4474 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
 import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidProvider;
index 51361b81e2bc8e7e1aa39e57dcb346f04d801a37..06193a6f394c68c8be7df9945ef68e8444b61e38 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
 
index d0e5a6db821c44a75c675b93427db1bddebb5791..70f4b3844d7262c3d1eb03495f24e5944193d989 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index da1b1f07136ba178315773aef870543ca1ebef6a..17282511c539849efe4d6586795bdc1f53719cdb 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
index a67bcfbaa0fabc1d64add0244e611f544824d1cf..72104c6da71363006d19bd394634cc33212c7c5b 100644 (file)
@@ -26,8 +26,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
index 5c69599cd7a3e66f01141005ba97eb853c8ed8e8..c29ac6af95e352e1e41f4333cd4e7239445074a9 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.db.CoreDbTester;
 
 import static java.lang.String.valueOf;
index aba95537cce3f09dfae6a543cb8c20572cf2dd11..155663653e80ef38f34b610b989e6845375a4410 100644 (file)
@@ -25,10 +25,10 @@ import java.util.Map;
 import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.SequenceUuidFactory;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.CoreDbTester;
index c725577ec8a7bb709c8a4d42ad1f26c90d7342bc..06b384ce19cf214e72cc7079c4868ec2e3b116ae 100644 (file)
@@ -30,8 +30,8 @@ import org.assertj.core.groups.Tuple;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.db.CoreDbTester;
 
 import static java.util.stream.Collectors.toList;
index a3b10a97883a31e978b2cc9b4ac41a241a69c141..05f63284b71c9ede82d6fe66cbf24596b3dc57e0 100644 (file)
@@ -26,8 +26,8 @@ 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.config.internal.MapSettings;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.CoreDbTester;
 import org.sonar.server.platform.db.migration.es.MigrationEsClient;
index be656e9750a9c4680a4a88002c9d3f4f398906e0..1175dae3ce671c86ff4c3a77de4558fc25defc61 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.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 bbf75de41b5834380613753c7a804a5920d098e9..32537555a28a8c5b80c49666998e75a7fd03162f 100644 (file)
@@ -25,8 +25,8 @@ dependencies {
   compile project(':sonar-markdown')
   compile project(':sonar-ws')
 
-  compileOnly project(path: ':sonar-plugin-api')
-  compileOnly project(path: ':server:sonar-process')
+  compileOnly project(':sonar-plugin-api')
+  compileOnly project(':server:sonar-process')
 
   compileOnly 'com.google.code.findbugs:jsr305'
 
@@ -46,6 +46,7 @@ dependencies {
   testCompile 'org.assertj:assertj-guava'
   testCompile 'org.mockito:mockito-core'
   testCompile project(':server:sonar-db-testing')
+  testCompile project(':sonar-plugin-api-impl')
 }
 
 task testJar(type: Jar) {
index dde34c989a09f3f5568c4a0bac2891cad34e6b8e..4a9cc66d6b9b783b37503dee3d1d485036ba87ef 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.component.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index bd3ff03f8f88e517f8ff45c0a2db146c899a6073..8ed3a8044c4ce4b8f3c6f55b66d7b30b51558dc9 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.config.internal.MultivalueProperty.parseAsCsv;
+import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
 
 public class ConfigurationProvider extends ProviderAdapter {
 
index aafb2941f8e8a78a25d20a0ad18556a2bd302bf5..c34bdf1863ae4ec98f29383c0bfc987c5bf9b4dd 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.issue.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index ed1c40ea8b878db8de753a038f0362ba4b90e1dc..2f5b24d0d342d8bdbb64a8907f3aa89cc53aecd3 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.measure.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 169f89c18a3631671588ed893f3e201d2584a9aa..df2b15f57140e4cbf989bb4f2790dae6d9dba9d4 100644 (file)
@@ -23,8 +23,8 @@ import java.io.File;
 import java.io.IOException;
 import org.apache.commons.io.FileUtils;
 import org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.impl.utils.DefaultTempFolder;
 import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.internal.DefaultTempFolder;
 
 public class TempFolderProvider extends ProviderAdapter {
 
index 97a8b68d1cc18177cb2b5b0f186317c88e36c16f..9e4e4382532c39239fc38bca82d16ea93630a590 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.internal.PluginContextImpl;
+import org.sonar.api.impl.context.PluginContextImpl;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginInfo;
index f1cf0f9ab5999d661a6c68f904a07ac2319a3e53..81fba7331d3357979e0598170afde123e688c3ed 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 60ff20dca26c2c4167a4ff901e2168d6740808ea..63b91d0f8bb8e266c9fd6b6d391e03bfa3d8a689 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.config.internal.ConfigurationBridge;
+import org.sonar.api.impl.config.ConfigurationBridge;
 
 import static java.util.Objects.requireNonNull;
 
index a887b55ffdc7286db08577f2818acfe47349a11e..4e88707992a2971cb1d6f26421849d01498f82a0 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.user.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 2abc9030b7b662a97561b1373c82433cc844a410..f4ddef479ef9d12c01b9d92758d1baba04b5da15 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.view.index;
 
 import org.sonar.api.config.Configuration;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index 3d09555029ec4cf8886defdc59fb6091ae64dacc..83691ad734979fd196bf52bd288be44be0da0748 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.config.PropertyDefinition.builder;
index 3a49dfdaf8a0913f2d1f0bf5a0b61de1f668c818..1635995263d971c8dc90040d3f4e5b2984fb611a 100644 (file)
@@ -29,7 +29,7 @@ import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.db.DbTester;
index d78d03734a8865b33fc6ae818bca10507486c37b..d0195af76a0e56fca1306333a40bec78db6d0d78 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 
index ed7adadab3e1d7e19b0a79b0141590967f647a86..149f67ad33fb1a1ef2b41ffc3e2facd75fb75da6 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.newindex.SettingsConfiguration;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
index c746a57f812e09f3052a92ab798a66272375ddd4..705b8054bb24854960e1fc4fb8a8e2119e8aa014 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.IndexType.IndexMainType;
 import org.sonar.server.es.newindex.SettingsConfiguration;
 import org.sonar.server.es.newindex.TestNewIndex;
index a86914e28f98fe5a299e61796e9f9c2699819e2f..542a89545b769cc842b354cb7debe34ff62f1f01 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.server.es.metadata;
 
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.IndexDefinition;
 
 class MetadataIndexDefinitionBridge implements IndexDefinition {
index d6dfd760540492b8a406bd0e298e593fb0347ac0..e6a8fb116317990b75fbc317ca5db4ca5b508f08 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.es.newindex;
 
 import org.elasticsearch.cluster.metadata.IndexMetaData;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.FakeDoc;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
index 4628a01025fea1a827fa17b0f606c16c95878491..90170c90d6d798cafcbde435087b69d7efe6b9f2 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexType;
 
index 835fe681d4ce9afd38deb3eeffb946c65160d0a3..8f5f29e4b5209259b78152e731de0c1a1435b9e8 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexType;
 import org.sonar.server.es.IndexType.IndexMainType;
@@ -52,7 +52,6 @@ public class NewIndexTest {
   private MapSettings settings = new MapSettings();
   private SettingsConfiguration defaultSettingsConfiguration = newBuilder(settings.asConfig()).build();
 
-
   @Test
   @UseDataProvider("indexWithAndWithoutRelations")
   public void getRelations_returns_empty_if_no_relation_added(Index index) {
index 928943090052ead7985a08b8254ba8080903f3b7..b63225dceca0b81f9caac60ff77f5dfb8522e1b3 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexType;
 
index 43bd47022fb828a21155267eb9cc34acd8c48106..5d253e97247b92646457adfd06bc3779f3864b7c 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.issue.index;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index ec1fc186f3963e6c373d25a019d15dc48e332d8a..07bc93ec941717502ecc90502ff74de608b64c00 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.platform.Server;
 import org.sonar.server.l18n.I18nRule;
index df611026d05e220febc7c45af69f05daa9c1f5d3..1aa43d4f3d98bb69018606d13918b38ba7876435 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.platform.Server;
 import org.sonar.server.l18n.I18nRule;
index e6d90285013cb632e51a6074e02e5e0ce8eb526b..6845ebe99fa56232b549d0e73dafc2e88efb7eac 100644 (file)
@@ -24,7 +24,7 @@ import java.util.Locale;
 import java.util.stream.Stream;
 import org.junit.Before;
 import org.junit.Test;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.extension.CoreExtension;
 import org.sonar.core.extension.CoreExtensionRepository;
 import org.sonar.core.platform.PluginInfo;
index f96745ffc27e120ec4bdcffcd52a1e0c4eb228ce..e08a3991f7beda1c814fe4f0732b9500b099156c 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.db.Database;
index 050fc56cbac94d6c0aac5e905869e5054575872c..b3fed77da5e01d1960831f432784445bd316360c 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.config.internal.ConfigurationBridge;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.ConfigurationBridge;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.platform.db.migration.step.MigrationSteps;
 import org.sonar.server.platform.db.migration.version.DatabaseVersion;
 
index 1c9797aad40d85a2b6c85bc4a21410e3fe35b69b..c0fc2330255af06aef3cd680f5ac7036e268454d 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.Version;
 
 import static org.assertj.core.api.Assertions.assertThat;
index deaca33baf2284d5e8520c6a0f4245fc73a36b58..27fd0c40f5dd17b92a50a359dd27469b94fdf143 100644 (file)
  */
 package org.sonar.server.platform;
 
-import org.sonar.api.SonarEdition;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
 import org.sonar.db.DbTester;
index cb4f0c3dbb1b3e8cdbc7946ff0700c24364d84c6..e3758bb181faa80500b6720c792c8f9c51750ebf 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.config.CorePropertyDefinitions;
 
 import static org.assertj.core.api.Assertions.assertThat;
index ae97dd927d3e3e639beaa48b275576563403f271..da41c4238be8f0428f36501931de206b2f93cab4 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index fd7aac44d4d5cc3ff4be2c7359d72d6d015b3cd1..8192345a929c220a31424a290569eff590343d42 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 81bd2172c7477085036fbe5e6b1879fdd42e3666..782480eade47bc91adb06e815f83c640586f8411 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
index d11ab122cadbe49b86a8cfb49379594a744cc0e1..3c854ffef635d62b68029a29d43890dd5ebed78d 100644 (file)
@@ -29,10 +29,10 @@ import org.elasticsearch.search.SearchHit;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.qualityprofile.QProfileDto;
index 1e68ad3ecd5f308807fe821855938246feecc47f..e3fa70e6f9e909e4f7c42ceea3cce5dfa70563c8 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -58,7 +58,7 @@ public class ChildSettingsTest {
     parent.setProperty(randomAlphanumeric(16), new Date(RANDOM.nextInt()));
     parent.setProperty(randomAlphanumeric(17), new Date(RANDOM.nextInt()), true);
     parent.setProperty(randomAlphanumeric(18), new Date(RANDOM.nextInt()), false);
-    parent.setProperty(multipleValuesKey, new String[] { randomAlphanumeric(10), randomAlphanumeric(20) });
+    parent.setProperty(multipleValuesKey, new String[] {randomAlphanumeric(10), randomAlphanumeric(20)});
 
     assertThat(underTest.getProperties()).isEqualTo(parent.getProperties());
   }
@@ -71,7 +71,6 @@ public class ChildSettingsTest {
     underTest.set(null, "");
   }
 
-
   @Test
   public void set_will_throw_NPE_if_value_is_null() {
     expectedException.expect(NullPointerException.class);
index 4e7e8fedc093d5faea5afc32737b4daf495b5308..cac317cb0740cce41facb951b2d956917d9780ab 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.user.index;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index b5c880269bb54a62ef89f7f7dcd5212e9a24d647..b495b63b4e7abc3588fc40a62cb39d4724776a89 100644 (file)
@@ -28,13 +28,13 @@ import okhttp3.Response;
 import okhttp3.mockwebserver.MockResponse;
 import okhttp3.mockwebserver.MockWebServer;
 import okhttp3.mockwebserver.RecordedRequest;
-import org.sonar.api.SonarEdition;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
 
 import static org.assertj.core.api.Assertions.assertThat;
index e18c49b422f3dba5b960e46b64f86ff66682c023..fece8070b3ce92a7ed85464d42f6a768fa314144 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.view.index;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index ee8b5cf1e03a211f5a3750b4a79eb51169bd2748..4ad418c9d4a953c5a21bbc0647f0353a74f7d283 100644 (file)
@@ -32,11 +32,11 @@ import org.junit.rules.Timeout;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.server.util.OkHttpClientProvider;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
index 11001b42e03e1f11364f41cb0290c4d69dee3563..1ba49c4c7daf15b59a0354ca1a4352b073f03298 100644 (file)
@@ -60,6 +60,7 @@ dependencies {
   compile project(':sonar-duplications')
   runtime project(path: ':sonar-plugin-api', configuration: 'shadow')
   compileOnly project(path: ':sonar-plugin-api')
+  compile project(':sonar-plugin-api-impl')
   compile project(':sonar-ws')
 
   compileOnly 'com.google.code.findbugs:jsr305'
index a9082abcdc336a5e23055cdd1e618fca29522010..cbbf90342101a2f19f7a563d5036909a8c6cd820 100644 (file)
@@ -25,11 +25,11 @@ import javax.annotation.Nullable;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.SonarQubeVersion;
-import org.sonar.api.internal.MetadataLoader;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.MetadataLoader;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
-import org.sonar.api.utils.internal.TempFolderCleaner;
+import org.sonar.server.util.TempFolderCleaner;
 import org.sonar.core.config.CorePropertyDefinitions;
 import org.sonar.core.extension.CoreExtensionRepositoryImpl;
 import org.sonar.core.extension.CoreExtensionsLoader;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultDebtRemediationFunctions.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultDebtRemediationFunctions.java
deleted file mode 100644 (file)
index 933aa36..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.server.rule;
-
-import javax.annotation.Nullable;
-import org.sonar.api.server.debt.DebtRemediationFunction;
-import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
-import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.api.utils.MessageException;
-
-/**
- * Factory of {@link org.sonar.api.server.debt.DebtRemediationFunction} that keeps
- * a context of rule for better error messages. Used only when declaring rules.
- *
- * @see org.sonar.api.server.rule.RulesDefinition
- */
-class DefaultDebtRemediationFunctions implements RulesDefinition.DebtRemediationFunctions {
-
-  private final String repoKey;
-  private final String key;
-
-  DefaultDebtRemediationFunctions(String repoKey, String key) {
-    this.repoKey = repoKey;
-    this.key = key;
-  }
-
-  @Override
-  public DebtRemediationFunction linear(String gapMultiplier) {
-    return create(DefaultDebtRemediationFunction.Type.LINEAR, gapMultiplier, null);
-  }
-
-  @Override
-  public DebtRemediationFunction linearWithOffset(String gapMultiplier, String baseEffort) {
-    return create(DefaultDebtRemediationFunction.Type.LINEAR_OFFSET, gapMultiplier, baseEffort);
-  }
-
-  @Override
-  public DebtRemediationFunction constantPerIssue(String baseEffort) {
-    return create(DefaultDebtRemediationFunction.Type.CONSTANT_ISSUE, null, baseEffort);
-  }
-
-  @Override
-  public DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String gapMultiplier, @Nullable String baseEffort) {
-    try {
-      return new DefaultDebtRemediationFunction(type, gapMultiplier, baseEffort);
-    } catch (Exception e) {
-      throw MessageException.of(String.format("The rule '%s:%s' is invalid : %s ", this.repoKey, this.key, e.getMessage()));
-    }
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewParam.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewParam.java
deleted file mode 100644 (file)
index ea27402..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.server.rule;
-
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.api.server.rule.RulesDefinition;
-
-import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
-
-public class DefaultNewParam implements RulesDefinition.NewParam {
-  private final String key;
-  private String name;
-  private String description;
-  private String defaultValue;
-  private RuleParamType type = RuleParamType.STRING;
-
-  DefaultNewParam(String key) {
-    this.key = this.name = key;
-  }
-
-  @Override
-  public String key() {
-    return key;
-  }
-
-  @Override
-  public DefaultNewParam setName(@Nullable String s) {
-    // name must never be null.
-    this.name = StringUtils.defaultIfBlank(s, key);
-    return this;
-  }
-
-  @Override
-  public DefaultNewParam setType(RuleParamType t) {
-    this.type = t;
-    return this;
-  }
-
-  @Override
-  public DefaultNewParam setDescription(@Nullable String s) {
-    this.description = StringUtils.defaultIfBlank(s, null);
-    return this;
-  }
-
-  @Override
-  public DefaultNewParam setDefaultValue(@Nullable String s) {
-    this.defaultValue = defaultIfEmpty(s, null);
-    return this;
-  }
-
-  public String name() {
-    return name;
-  }
-
-  public String description() {
-    return description;
-  }
-
-  public String defaultValue() {
-    return defaultValue;
-  }
-
-  public RuleParamType type() {
-    return type;
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewRepository.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewRepository.java
deleted file mode 100644 (file)
index 3607e60..0000000
+++ /dev/null
@@ -1,113 +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.server.rule;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-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 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) {
-    this.context = context;
-    this.key = key;
-    this.name = key;
-    this.language = language;
-    this.isExternal = isExternal;
-  }
-
-  @Override
-  public boolean isExternal() {
-    return isExternal;
-  }
-
-  @Override
-  public String key() {
-    return key;
-  }
-
-  String language() {
-    return language;
-  }
-
-  Map<String, RulesDefinition.NewRule> newRules() {
-    return newRules;
-  }
-
-  String name() {
-    return name;
-  }
-
-  @Override
-  public DefaultNewRepository setName(@Nullable String s) {
-    if (StringUtils.isNotEmpty(s)) {
-      this.name = s;
-    }
-    return this;
-  }
-
-  @Override
-  public RulesDefinition.NewRule createRule(String ruleKey) {
-    checkArgument(!newRules.containsKey(ruleKey), "The rule '%s' of repository '%s' is declared several times", ruleKey, key);
-    RulesDefinition.NewRule newRule = new DefaultNewRule(context.currentPluginKey(), key, ruleKey);
-    newRules.put(ruleKey, newRule);
-    return newRule;
-  }
-
-  @CheckForNull
-  @Override
-  public RulesDefinition.NewRule rule(String ruleKey) {
-    return newRules.get(ruleKey);
-  }
-
-  @Override
-  public Collection<RulesDefinition.NewRule> rules() {
-    return newRules.values();
-  }
-
-  @Override
-  public void done() {
-    // note that some validations can be done here, for example for
-    // verifying that at least one rule is declared
-
-    context.registerRepository(this);
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder("NewRepository{");
-    sb.append("key='").append(key).append('\'');
-    sb.append(", language='").append(language).append('\'');
-    sb.append('}');
-    return sb.toString();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewRule.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultNewRule.java
deleted file mode 100644 (file)
index 3496d2d..0000000
+++ /dev/null
@@ -1,350 +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.server.rule;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleScope;
-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.server.rule.RuleTagFormat;
-import org.sonar.api.server.rule.RulesDefinition;
-
-import static java.lang.String.format;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.commons.lang.StringUtils.isEmpty;
-import static org.apache.commons.lang.StringUtils.trimToNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-import static org.sonar.api.utils.Preconditions.checkState;
-
-class DefaultNewRule implements RulesDefinition.NewRule {
-  private final String pluginKey;
-  private final String repoKey;
-  private final String key;
-  private RuleType type;
-  private String name;
-  private String htmlDescription;
-  private String markdownDescription;
-  private String internalKey;
-  private String severity = Severity.MAJOR;
-  private boolean template;
-  private RuleStatus status = RuleStatus.defaultStatus();
-  private DebtRemediationFunction debtRemediationFunction;
-  private String gapDescription;
-  private final Set<String> tags = new TreeSet<>();
-  private final Set<String> securityStandards = new TreeSet<>();
-  private final Map<String, RulesDefinition.NewParam> paramsByKey = new HashMap<>();
-  private final RulesDefinition.DebtRemediationFunctions functions;
-  private boolean activatedByDefault;
-  private RuleScope scope;
-  private final Set<RuleKey> deprecatedRuleKeys = new TreeSet<>();
-
-  DefaultNewRule(@Nullable String pluginKey, String repoKey, String key) {
-    this.pluginKey = pluginKey;
-    this.repoKey = repoKey;
-    this.key = key;
-    this.functions = new DefaultDebtRemediationFunctions(repoKey, key);
-  }
-
-  @Override
-  public String key() {
-    return this.key;
-  }
-
-  @CheckForNull
-  @Override
-  public RuleScope scope() {
-    return this.scope;
-  }
-
-  @Override
-  public DefaultNewRule setScope(RuleScope scope) {
-    this.scope = scope;
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setName(String s) {
-    this.name = trimToNull(s);
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setTemplate(boolean template) {
-    this.template = template;
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setActivatedByDefault(boolean activatedByDefault) {
-    this.activatedByDefault = activatedByDefault;
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setSeverity(String s) {
-    checkArgument(Severity.ALL.contains(s), "Severity of rule %s is not correct: %s", this, s);
-    this.severity = s;
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setType(RuleType t) {
-    this.type = t;
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setHtmlDescription(@Nullable String s) {
-    checkState(markdownDescription == null, "Rule '%s' already has a Markdown description", this);
-    this.htmlDescription = trimToNull(s);
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setHtmlDescription(@Nullable URL classpathUrl) {
-    if (classpathUrl != null) {
-      try {
-        setHtmlDescription(IOUtils.toString(classpathUrl, UTF_8));
-      } catch (IOException e) {
-        throw new IllegalStateException("Fail to read: " + classpathUrl, e);
-      }
-    } else {
-      this.htmlDescription = null;
-    }
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setMarkdownDescription(@Nullable String s) {
-    checkState(htmlDescription == null, "Rule '%s' already has an HTML description", this);
-    this.markdownDescription = trimToNull(s);
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setMarkdownDescription(@Nullable URL classpathUrl) {
-    if (classpathUrl != null) {
-      try {
-        setMarkdownDescription(IOUtils.toString(classpathUrl, UTF_8));
-      } catch (IOException e) {
-        throw new IllegalStateException("Fail to read: " + classpathUrl, e);
-      }
-    } else {
-      this.markdownDescription = null;
-    }
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setStatus(RuleStatus status) {
-    checkArgument(RuleStatus.REMOVED != status, "Status 'REMOVED' is not accepted on rule '%s'", this);
-    this.status = status;
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setDebtSubCharacteristic(@Nullable String s) {
-    return this;
-  }
-
-  @Override
-  public RulesDefinition.DebtRemediationFunctions debtRemediationFunctions() {
-    return functions;
-  }
-
-  @Override
-  public DefaultNewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn) {
-    this.debtRemediationFunction = fn;
-    return this;
-  }
-
-  @Deprecated
-  @Override
-  public DefaultNewRule setEffortToFixDescription(@Nullable String s) {
-    return setGapDescription(s);
-  }
-
-  @Override
-  public DefaultNewRule setGapDescription(@Nullable String s) {
-    this.gapDescription = s;
-    return this;
-  }
-
-  @Override
-  public RulesDefinition.NewParam createParam(String paramKey) {
-    checkArgument(!paramsByKey.containsKey(paramKey), "The parameter '%s' is declared several times on the rule %s", paramKey, this);
-    DefaultNewParam param = new DefaultNewParam(paramKey);
-    paramsByKey.put(paramKey, param);
-    return param;
-  }
-
-  @CheckForNull
-  @Override
-  public RulesDefinition.NewParam param(String paramKey) {
-    return paramsByKey.get(paramKey);
-  }
-
-  @Override
-  public Collection<RulesDefinition.NewParam> params() {
-    return paramsByKey.values();
-  }
-
-  @Override
-  public DefaultNewRule addTags(String... list) {
-    for (String tag : list) {
-      RuleTagFormat.validate(tag);
-      tags.add(tag);
-    }
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setTags(String... list) {
-    tags.clear();
-    addTags(list);
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule addOwaspTop10(RulesDefinition.OwaspTop10... standards) {
-    for (RulesDefinition.OwaspTop10 owaspTop10 : standards) {
-      String standard = "owaspTop10:" + owaspTop10.name().toLowerCase(Locale.ENGLISH);
-      securityStandards.add(standard);
-    }
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule addCwe(int... nums) {
-    for (int num : nums) {
-      String standard = "cwe:" + num;
-      securityStandards.add(standard);
-    }
-    return this;
-  }
-
-  @Override
-  public DefaultNewRule setInternalKey(@Nullable String s) {
-    this.internalKey = s;
-    return this;
-  }
-
-  void validate() {
-    if (isEmpty(name)) {
-      throw new IllegalStateException(format("Name of rule %s is empty", this));
-    }
-    if (isEmpty(htmlDescription) && isEmpty(markdownDescription)) {
-      throw new IllegalStateException(format("One of HTML description or Markdown description must be defined for rule %s", this));
-    }
-  }
-
-  @Override
-  public DefaultNewRule addDeprecatedRuleKey(String repository, String key) {
-    deprecatedRuleKeys.add(RuleKey.of(repository, key));
-    return this;
-  }
-
-  String pluginKey() {
-    return pluginKey;
-  }
-
-  String repoKey() {
-    return repoKey;
-  }
-
-  RuleType type() {
-    return type;
-  }
-
-  String name() {
-    return name;
-  }
-
-  String htmlDescription() {
-    return htmlDescription;
-  }
-
-  String markdownDescription() {
-    return markdownDescription;
-  }
-
-  @CheckForNull
-  String internalKey() {
-    return internalKey;
-  }
-
-  String severity() {
-    return severity;
-  }
-
-  boolean template() {
-    return template;
-  }
-
-  RuleStatus status() {
-    return status;
-  }
-
-  DebtRemediationFunction debtRemediationFunction() {
-    return debtRemediationFunction;
-  }
-
-  String gapDescription() {
-    return gapDescription;
-  }
-
-  Set<String> tags() {
-    return tags;
-  }
-
-  Set<String> securityStandards() {
-    return securityStandards;
-  }
-
-  Map<String, RulesDefinition.NewParam> paramsByKey() {
-    return paramsByKey;
-  }
-
-  boolean activatedByDefault() {
-    return activatedByDefault;
-  }
-
-  Set<RuleKey> deprecatedRuleKeys() {
-    return deprecatedRuleKeys;
-  }
-
-  @Override
-  public String toString() {
-    return format("[repository=%s, key=%s]", repoKey, key);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultParam.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultParam.java
deleted file mode 100644 (file)
index 3e18fd7..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.server.rule;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.api.server.rule.RulesDefinition;
-
-@Immutable
-public class DefaultParam implements RulesDefinition.Param {
-  private final String key;
-  private final String name;
-  private final String description;
-  private final String defaultValue;
-  private final RuleParamType type;
-
-  DefaultParam(DefaultNewParam newParam) {
-    this.key = newParam.key();
-    this.name = newParam.name();
-    this.description = newParam.description();
-    this.defaultValue = newParam.defaultValue();
-    this.type = newParam.type();
-  }
-
-  @Override
-  public String key() {
-    return key;
-  }
-
-  @Override
-  public String name() {
-    return name;
-  }
-
-  @Override
-  @Nullable
-  public String description() {
-    return description;
-  }
-
-  @Override
-  @Nullable
-  public String defaultValue() {
-    return defaultValue;
-  }
-
-  @Override
-  public RuleParamType type() {
-    return type;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    RulesDefinition.Param that = (RulesDefinition.Param) o;
-    return key.equals(that.key());
-  }
-
-  @Override
-  public int hashCode() {
-    return key.hashCode();
-  }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRepository.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRepository.java
deleted file mode 100644 (file)
index 5723aa9..0000000
+++ /dev/null
@@ -1,128 +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.server.rule;
-
-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 javax.annotation.concurrent.Immutable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.api.utils.log.Loggers;
-
-import static java.lang.String.format;
-import static java.util.Collections.unmodifiableList;
-import static java.util.Collections.unmodifiableMap;
-
-@Immutable
-class DefaultRepository implements RulesDefinition.Repository {
-  private final String key;
-  private final String language;
-  private final String name;
-  private final boolean isExternal;
-  private final Map<String, RulesDefinition.Rule> rulesByKey;
-
-  DefaultRepository(DefaultNewRepository newRepository, @Nullable RulesDefinition.Repository mergeInto) {
-    this.key = newRepository.key();
-    this.language = newRepository.language();
-    this.isExternal = newRepository.isExternal();
-    Map<String, RulesDefinition.Rule> ruleBuilder = new HashMap<>();
-    if (mergeInto != null) {
-      if (!StringUtils.equals(newRepository.language(), mergeInto.language()) || !StringUtils.equals(newRepository.key(), mergeInto.key())) {
-        throw new IllegalArgumentException(format("Bug - language and key of the repositories to be merged should be the sames: %s and %s", newRepository, mergeInto));
-      }
-      this.name = StringUtils.defaultIfBlank(mergeInto.name(), newRepository.name());
-      for (RulesDefinition.Rule rule : mergeInto.rules()) {
-        if (!newRepository.key().startsWith("common-") && ruleBuilder.containsKey(rule.key())) {
-          Loggers.get(getClass()).warn("The rule '{}' of repository '{}' is declared several times", rule.key(), mergeInto.key());
-        }
-        ruleBuilder.put(rule.key(), rule);
-      }
-    } else {
-      this.name = newRepository.name();
-    }
-    for (RulesDefinition.NewRule newRule : newRepository.newRules().values()) {
-      DefaultNewRule defaultNewRule = (DefaultNewRule) newRule;
-      defaultNewRule.validate();
-      ruleBuilder.put(newRule.key(), new DefaultRule(this, defaultNewRule));
-    }
-    this.rulesByKey = unmodifiableMap(ruleBuilder);
-  }
-
-  @Override
-  public String key() {
-    return key;
-  }
-
-  @Override
-  public String language() {
-    return language;
-  }
-
-  @Override
-  public String name() {
-    return name;
-  }
-
-  @Override
-  public boolean isExternal() {
-    return isExternal;
-  }
-
-  @Override
-  @CheckForNull
-  public RulesDefinition.Rule rule(String ruleKey) {
-    return rulesByKey.get(ruleKey);
-  }
-
-  @Override
-  public List<RulesDefinition.Rule> rules() {
-    return unmodifiableList(new ArrayList<>(rulesByKey.values()));
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    DefaultRepository that = (DefaultRepository) o;
-    return key.equals(that.key);
-  }
-
-  @Override
-  public int hashCode() {
-    return key.hashCode();
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder("Repository{");
-    sb.append("key='").append(key).append('\'');
-    sb.append(", language='").append(language).append('\'');
-    sb.append('}');
-    return sb.toString();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRule.java b/server/sonar-server/src/main/java/org/sonar/server/rule/DefaultRule.java
deleted file mode 100644 (file)
index 8465110..0000000
+++ /dev/null
@@ -1,238 +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.server.rule;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleScope;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rules.RuleType;
-import org.sonar.api.server.debt.DebtRemediationFunction;
-import org.sonar.api.server.rule.RuleTagsToTypeConverter;
-import org.sonar.api.server.rule.RulesDefinition;
-
-import static java.lang.String.format;
-import static java.util.Collections.unmodifiableList;
-
-@Immutable
-public class DefaultRule implements RulesDefinition.Rule {
-  private final String pluginKey;
-  private final RulesDefinition.Repository repository;
-  private final String repoKey;
-  private final String key;
-  private final String name;
-  private final RuleType type;
-  private final String htmlDescription;
-  private final String markdownDescription;
-  private final String internalKey;
-  private final String severity;
-  private final boolean template;
-  private final DebtRemediationFunction debtRemediationFunction;
-  private final String gapDescription;
-  private final Set<String> tags;
-  private final Set<String> securityStandards;
-  private final Map<String, RulesDefinition.Param> params;
-  private final RuleStatus status;
-  private final boolean activatedByDefault;
-  private final RuleScope scope;
-  private final Set<RuleKey> deprecatedRuleKeys;
-
-  DefaultRule(DefaultRepository repository, DefaultNewRule newRule) {
-    this.pluginKey = newRule.pluginKey();
-    this.repository = repository;
-    this.repoKey = newRule.repoKey();
-    this.key = newRule.key();
-    this.name = newRule.name();
-    this.htmlDescription = newRule.htmlDescription();
-    this.markdownDescription = newRule.markdownDescription();
-    this.internalKey = newRule.internalKey();
-    this.severity = newRule.severity();
-    this.template = newRule.template();
-    this.status = newRule.status();
-    this.debtRemediationFunction = newRule.debtRemediationFunction();
-    this.gapDescription = newRule.gapDescription();
-    this.scope = newRule.scope() == null ? RuleScope.MAIN : newRule.scope();
-    this.type = newRule.type() == null ? RuleTagsToTypeConverter.convert(newRule.tags()) : newRule.type();
-    Set<String> tagsBuilder = new TreeSet<>(newRule.tags());
-    tagsBuilder.removeAll(RuleTagsToTypeConverter.RESERVED_TAGS);
-    this.tags = Collections.unmodifiableSet(tagsBuilder);
-    this.securityStandards = Collections.unmodifiableSet(new TreeSet<>(newRule.securityStandards()));
-    Map<String, RulesDefinition.Param> paramsBuilder = new HashMap<>();
-    for (RulesDefinition.NewParam newParam : newRule.paramsByKey().values()) {
-      paramsBuilder.put(newParam.key(), new DefaultParam((DefaultNewParam) newParam));
-    }
-    this.params = Collections.unmodifiableMap(paramsBuilder);
-    this.activatedByDefault = newRule.activatedByDefault();
-    this.deprecatedRuleKeys = Collections.unmodifiableSet(new TreeSet<>(newRule.deprecatedRuleKeys()));
-  }
-
-  public RulesDefinition.Repository repository() {
-    return repository;
-  }
-
-  @Override
-  @CheckForNull
-  public String pluginKey() {
-    return pluginKey;
-  }
-
-  @Override
-  public String key() {
-    return key;
-  }
-
-  @Override
-  public String name() {
-    return name;
-  }
-
-  @Override
-  public RuleScope scope() {
-    return scope;
-  }
-
-  @Override
-  public RuleType type() {
-    return type;
-  }
-
-  @Override
-  public String severity() {
-    return severity;
-  }
-
-  @Override
-  @CheckForNull
-  public String htmlDescription() {
-    return htmlDescription;
-  }
-
-  @Override
-  @CheckForNull
-  public String markdownDescription() {
-    return markdownDescription;
-  }
-
-  @Override
-  public boolean template() {
-    return template;
-  }
-
-  @Override
-  public boolean activatedByDefault() {
-    return activatedByDefault;
-  }
-
-  @Override
-  public RuleStatus status() {
-    return status;
-  }
-
-  @CheckForNull
-  @Deprecated
-  @Override
-  public String debtSubCharacteristic() {
-    return null;
-  }
-
-  @CheckForNull
-  @Override
-  public DebtRemediationFunction debtRemediationFunction() {
-    return debtRemediationFunction;
-  }
-
-  @Deprecated
-  @CheckForNull
-  @Override
-  public String effortToFixDescription() {
-    return gapDescription();
-  }
-
-  @CheckForNull
-  @Override
-  public String gapDescription() {
-    return gapDescription;
-  }
-
-  @CheckForNull
-  @Override
-  public RulesDefinition.Param param(String key) {
-    return params.get(key);
-  }
-
-  @Override
-  public List<RulesDefinition.Param> params() {
-    return unmodifiableList(new ArrayList<>(params.values()));
-  }
-
-  @Override
-  public Set<String> tags() {
-    return tags;
-  }
-
-  @Override
-  public Set<String> securityStandards() {
-    return securityStandards;
-  }
-
-  @Override
-  public Set<RuleKey> deprecatedRuleKeys() {
-    return deprecatedRuleKeys;
-  }
-
-  @CheckForNull
-  @Override
-  public String internalKey() {
-    return internalKey;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    DefaultRule other = (DefaultRule) o;
-    return key.equals(other.key) && repoKey.equals(other.repoKey);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = repoKey.hashCode();
-    result = 31 * result + key.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return format("[repository=%s, key=%s]", repoKey, key);
-  }
-}
-
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionContext.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleDefinitionContext.java
deleted file mode 100644 (file)
index 69a876d..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.server.rule;
-
-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 implements 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;
-  }
-}
index ebe02c77f9862414f8fafbd39a6d95ace872f0d6..b503863846b3b887b1eef11d4cd6eba3b567869c 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.rule;
 
 import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.impl.server.RuleDefinitionContext;
 import org.sonar.server.plugins.ServerPluginRepository;
 
 /**
index b71f3fe2f49fd9c72f102667d465541b675f087f..84ad9580067e465d6e800ae51fff8e3e39508591 100644 (file)
  */
 package org.sonar.server.user.ws;
 
+import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.sonar.api.internal.google.common.base.Preconditions;
 import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/util/TempFolderCleaner.java b/server/sonar-server/src/main/java/org/sonar/server/util/TempFolderCleaner.java
new file mode 100644 (file)
index 0000000..812af0e
--- /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.server.util;
+
+import org.sonar.api.Startable;
+import org.sonar.api.impl.utils.DefaultTempFolder;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.TempFolder;
+
+@ServerSide
+public class TempFolderCleaner implements Startable {
+
+  private TempFolder defaultTempFolder;
+
+  public TempFolderCleaner(TempFolder defaultTempFolder) {
+    this.defaultTempFolder = defaultTempFolder;
+  }
+
+  /**
+   * This method should not be renamed. It follows the naming convention
+   * defined by IoC container.
+   */
+  @Override
+  public void start() {
+    // Nothing to do
+  }
+
+  /**
+   * This method should not be renamed. It follows the naming convention
+   * defined by IoC container.
+   */
+  @Override
+  public void stop() {
+    ((DefaultTempFolder) defaultTempFolder).clean();
+  }
+}
index 09716e0b961fe597ad91351153a747690fffee76..849ce4752404712f724c23eb8b3b0ab1b9aed74c 100644 (file)
@@ -26,7 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import org.sonar.api.server.ws.LocalConnector;
-import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.api.impl.ws.ValidatingRequest;
 
 public class LocalRequestAdapter extends ValidatingRequest {
 
index 7a44984050744dcbc36072dda07f8d01d7ec847f..966e04223151a66fff4b6cbe0818787e34e9bfe3 100644 (file)
@@ -31,8 +31,8 @@ import java.util.Map;
 import java.util.Optional;
 import javax.annotation.CheckForNull;
 import javax.servlet.http.HttpServletRequest;
-import org.sonar.api.server.ws.internal.PartImpl;
-import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.api.impl.ws.PartImpl;
+import org.sonar.api.impl.ws.ValidatingRequest;
 import org.sonar.api.utils.log.Loggers;
 import org.sonarqube.ws.MediaTypes;
 
index b9871f8b0c2eeaee7af5e482ec8f186f56a70e97..e7569e603501f0ea4a49bb9a6165903ae2c1aea2 100644 (file)
@@ -33,7 +33,7 @@ import org.sonar.api.server.ws.LocalConnector;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.api.impl.ws.ValidatingRequest;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.api.utils.text.JsonWriter;
index de5f24347fc483782a73ce1b2fa27a03f69701f5..2ad32ba933373bab062b669e532c4fceb7a6d2c8 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.process.sharedmemoryfile.DefaultProcessCommands;
 
 import static org.assertj.core.api.Assertions.assertThat;
index ee90eb0d0940b919d8e3ad86f04fb841f6cf6f13..290e5309433de9353e6660f7f43c81484f231caf 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.security.Authenticator;
 import org.sonar.api.security.ExternalGroupsProvider;
 import org.sonar.api.security.ExternalUsersProvider;
index 9f26430ab8cf6576ddbe02a959957858a7061851..05fe52566e329a08afd96886d2923c94e6980277 100644 (file)
@@ -31,9 +31,9 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbTester;
 import org.sonar.db.user.GroupDto;
index ed1f5c220844fc7e3bce54265f1e81cc20fae999..f7b68650c27fce2e43605e3303966f3481a3f14e 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
index 08aae1e567e24347f355ace18f7dd7ac31f10dd0..e4ae8ff6bcf0bbf8ab6050acc2c205f1027c5f21 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
index cc3501e4fc0e0cd935bb6551a7708108b41a05f3..f20e6c6bdf0625d2b67d47a3a0254b7790b978d9 100644 (file)
@@ -23,7 +23,7 @@ package org.sonar.server.authentication;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.user.UserDto;
 import org.sonar.db.user.UserTokenDto;
index f37b861518a693f4e76e3a511b1344da96f711b2..3a633f733bc987c95bd391a53bdfb5280b320f6d 100644 (file)
@@ -23,12 +23,12 @@ import com.google.common.collect.ImmutableSet;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.authentication.UserIdentity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.alm.AlmAppInstallDto;
 import org.sonar.db.component.ResourceTypesRule;
index 5b73341128292850c33c8601bb01f41cc7216e33..d81029a2c54640265a2a644ac913230398492407 100644 (file)
@@ -24,10 +24,10 @@ import java.util.stream.Collectors;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.server.authentication.UserIdentity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
index cac1b7ceaf7b08517bf1b47fa317d9cc7750d106..14dc0e5fa118e458c8816f1c0852873015edad5c 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.server.authentication.BaseIdentityProvider;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
index 649818cbc643cfd513e6af1c9874af280bf8dc45..cc6376e9a3a5e0786e512cd790f1120b310a0219 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.authentication.BasicAuthentication;
 import org.sonar.server.authentication.JwtHttpHandler;
 import org.sonar.server.authentication.event.AuthenticationException;
index 59ddc6217ab9181e06a79baf04b2c97b771d2874..fbfc5ccabf79ca8d6c42acb91d8cea63391faf3a 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.server.ws.WebService;
index d189746349364fccac815d4701af1896b6cc77f4..924462809fd4488b2c3e72d56637fa1a79a7a84d 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
index d34710a619e8dc4adad32116f78c7c83dd387b70..5706c2699fa9aee0d5bcd5d4f319deb99f9279cc 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.measures.Metric;
 import org.sonar.db.DbTester;
 import org.sonar.server.tester.UserSessionRule;
index c357b96495c72cfe66ce43e2e899e31225690b86..480ac6fc207dfd78ca21a26dd685f3f0cc8c5a32 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
 import org.sonar.api.web.UserRole;
index c53cf871bf4c54ab1a71a8401ae1e349bbfd5b33..227bf05fd8ae0e4cb5b8062bffd4289b7e31b008 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.process.sharedmemoryfile.DefaultProcessCommands;
 import org.sonar.process.ProcessEntryPoint;
index 62994f1e5037c460a79345d1d8cc7af35c3f0e6d..002d03aba0fe544046a41b2d822b8b5c24061c31 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.web.UserRole;
 import org.sonar.ce.queue.CeQueue;
 import org.sonar.ce.queue.CeQueueImpl;
index b2b26d951a7595620ee023273a41ef083daabcd7..319683819e606000a27c962114342e1ad88a7acc 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.server.es.IndexType.IndexMainType;
index de10b8e190502708d82b53fd30038339d5038525..515056beb856a7c3b3bee84584ad7c44422022ed 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.metadata.MetadataIndex;
 import org.sonar.server.es.metadata.MetadataIndexImpl;
 import org.sonar.server.es.newindex.FakeIndexDefinition;
index 4f6633793b6cfb3cf82a3efa0e05032d733f39cc..8394828fffe924a2591b5ff5609e2df60401d25d 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.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 cad24375750a8a79733389a13f7d5985685a10a3..9c898e9611e0770902c54daa0d3d1f669156261e 100644 (file)
@@ -35,9 +35,9 @@ 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.db.DbSession;
index 4e278877baddf670238c61054dbe436554039756..c0a61c8f573c98044cd3fda380f61d36203c3a3c 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.System2;
 import org.sonar.core.platform.ComponentContainer;
index 72366851eb6700c773d42867b7c909d57686a688..015d5f62db732fd2ef5c8e46f52987ca8fef0eea 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.process.NetworkUtils;
 import org.sonar.process.cluster.health.NodeDetails;
index 91ef4b627094c8bec6c57ff611f7e20792bb5980..f103c91017eadfaa3a44335ae9f71a8a7c725dd2 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.rules.RuleType;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.Duration;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.core.issue.DefaultIssueComment;
 import org.sonar.core.issue.IssueChangeContext;
index 62bd3b09a36df1dccb2fad235c101f794daf2759..e46f938784c5b8de2cbfae511d14b3926744ae6c 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
index bbf2838cea62e8a1c25d354fdaa71bad3c78afbc..e72f44a18b74879c5622f658a808cf2a5437b3c3 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
index 94e91c8067697ab84f5bc1c3135146b3b7e4c07e..7bdb1edfdae2d9eb8b8279483cddee3d90e7ece5 100644 (file)
@@ -32,7 +32,7 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
index 426243cd7d6693c44528d52d122c33dfe9deee1d..46ba1e80a12378d6b944b15fe9d73af1901e6540 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.server.es.EsTester;
index 577c835d4906b510b1caf6c3ef257159ac42b917..facee47775b81b499d3514015fe511cefb3f0b0a 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
index ae7f70540a8b89183a7bb52a0add356ff890bf5e..e5c1ec193dd74f6726eeeb73879095c15138d6c4 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
index 336d049ba0516851ecdd3bb69d373075fcbd14c1..e34a915f808e802ef1ab60430e2514a33ee0af30 100644 (file)
@@ -34,7 +34,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
index 412b33110371d631ebb2cb5f434f0682eabef3f4..aa81a36fdc9400629bc32ae7e4775e197526245e 100644 (file)
@@ -24,7 +24,7 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index edcfca9ce0f1539cb2bbeefe7549a371b4cc700d..d4d4bc6375e262be53428c63c36b311bdf1834f0 100644 (file)
@@ -33,7 +33,7 @@ import org.mockito.ArgumentCaptor;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.BranchType;
index 9634f8ee931864be90470560cd2aa2e19d7df9d8..4c755e96cbc3d4959f2e5258d7afd52cfe0c14c6 100644 (file)
@@ -28,7 +28,7 @@ import org.mockito.ArgumentCaptor;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
index 9a4bacc317dad51d753392ae741ec5599f620a59..6f97d04f0e3f32b02a70adf8d05b15ca1ebdce44 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.rule.RuleKey;
index 1d5d65750a9892802ecd4813bd519e3d2a4ed46d..1d5abf53edce643c9b53acdf54180c158c9c9c63 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.ws.WebService;
index 07ded448839da1cdbf79ba706c37b489b8db07dd..d1287a495f392f911c3d8032315207e6c3c8fd8f 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rules.RuleType;
index b029c512d7e166cc5ba3b44a77afb90d7e6029d0..a12c5715697232c00a56c57757d8a54b70ab95ef 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.Durations;
index 872c5777b2cbf71bec7e9fe6299ead1de6f7d098..63257d007b97477d8b30360ec43cbbf1a151629c 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.custom.CustomMeasureDto;
index df8fff10315e381988777fa66d038e4debed0de9..1dc8030a2941164a940966fa9bb045ddcfc3cf77 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.resources.Qualifiers;
index 8a24e6b092c50b5837ce0e9605da642abfc780fd..7d7fb37fc96fa96d3be6fcc7a5faf6824612b1ca 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.notifications.Notification;
 
 import static java.util.Collections.singleton;
index a8d6d52544da5184dbd1022f7fe5ccddc9c36a11..7e343ea2f28581116d12c17e0deb77c7a13acb53 100644 (file)
  */
 package org.sonar.server.notification;
 
-import com.google.common.collect.Sets;
-import java.util.Arrays;
 import org.junit.Test;
 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.notifications.NotificationChannel;
 import org.sonar.db.DbClient;
-import org.sonar.db.property.PropertiesDao;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
index a6354115e838d649e5cdf799d1e79195f66ebbd5..89f6bc086f40b5ad4891812b0334d8f1eb2e31f0 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.notification.ws;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.notifications.NotificationChannel;
 import org.sonar.server.issue.notification.FPOrWontFixNotificationHandler;
 import org.sonar.server.issue.notification.MyNewIssuesNotificationHandler;
index 75720a170165cdc788c829ca0cafc6cc2a5a6d1f..58474092b700a41164e0405248643684876cbdad 100644 (file)
@@ -27,11 +27,11 @@ import org.apache.commons.lang.RandomStringUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+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.utils.internal.TestSystem2;
+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;
index 93f3479c1857dcf816445cd38fc95097d4d03e6c..760a904b9befb3bdcc8b53f4c06fa5093e0de86b 100644 (file)
@@ -26,12 +26,12 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.core.util.UuidFactoryFast;
index ce3eaed91602612a88fdbd381343f616a575b6b4..9946f312fd4e4666c487dcc5871945d5f3464c1e 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.organization.ws;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 88ae06abbc8d9e07aab29db1627eee9c1d528da4..c859ea7c39d3f4262d5269be8cf14d42ce0cc2a6 100644 (file)
@@ -24,9 +24,9 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.api.web.UserRole;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index 2dfe93c4c29aad4bd59927e7b64ee263ce212a62..71ad3c3bb9386fa18ef981620d3da65bcdbf8690 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.server.permission.index;
 
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.es.Index;
 import org.sonar.server.es.IndexDefinition;
 import org.sonar.server.es.IndexType;
index ac233f2d6221b78a489be464d9435f042261102c..a6516b6199384142fe96eb506754533f20a27bae 100644 (file)
@@ -22,8 +22,8 @@ package org.sonar.server.permission.ws;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ResourceTypesRule;
index 80843e037bb7ac001c6a45851918dc46ab6f37ae..0efc112c1d8411db38888d7392c0294ecadce86f 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.permission.ws.template;
 import javax.annotation.Nullable;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.permission.template.PermissionTemplateDto;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
index afcca28802ae4e97b7f4d4816418f7fd5fa962ae..a0eeba405a502378e746dd4c6537f387ad356d57 100644 (file)
@@ -25,8 +25,8 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
index 3de7281760b69e6dd7f3061146bce46335ee08ee..ce8e98ccb7e700b46147c4a16dbbf7e98ab20a92 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
index 812b3d9254b8bd4681bcd7858a5e2465ec2c90b4..04cab75b3846f4520157e3a1814e979f2d86e1e1 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
 
index 7e30958d5397f7004702f5ed54ab2cd050dd365f..3d149ac81b4209119498549ef613fbe58bc603b7 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.server.platform.db;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.System2;
 
 import static org.mockito.Mockito.mock;
index 5672b7b60cf86b42aa30a59ab94f304fcea7a308..3f3520c48935482428348d5ae8e3ae47f834551d 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.process.NetworkUtilsImpl;
index 5860ed73671c9c237ce0792ef5f0d547c4ffbf51..d1010a5ad2a4c303f856ffe6eec55f385673d587 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
 
 import static org.apache.commons.lang.StringUtils.repeat;
index bc233dab4e9418818e87d172f02a9f1fc9976034..1c4495f1a9517a5c5e62d52f6269d251ba1b506d 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.security.SecurityRealm;
 import org.sonar.api.utils.log.LoggerLevel;
index 3b06b895c331ee06acb4883c6c948659434a306f..2f87bef1aadca5e7341aed0ca8dc03fb933934e6 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.server.platform.WebServer;
 
index f12c7461f1e063d69b1cb4fce0cb725bda88a855..adffc0b91a234ef0155d6abf013b2c16c658d07e 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.security.SecurityRealm;
 import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
index 9fdb245d475241e5a87d11b6d759d478896c6aa9..9e3d15d6c71d6e535f91fea066db2597b86a19ce 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
 import org.sonar.server.platform.OfficialDistribution;
index 3756ca14b5841eef36bf17764bb0f9a282ea64e2..a256be06728eb5acb4af2f9124892098a15ef7cb 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ServerId;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.core.util.Uuids;
index 0875ad0fcb242904ff80f24d77ab3da829899bd4..22a4550d8d5e16177b03d129038332d9a2d199f3 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.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
 import org.sonar.core.platform.ServerId;
index 5551c269c15484026af0bc88fe442de22fd90d1e..f9bf7d29a92e510537389b83a0ec4b16c72e965d 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.server.platform.OfficialDistribution;
 import org.sonar.server.platform.Platform;
 
index 5f52cee93c1d30cdccc81772ddae95378a8d84d5..d07cb6a34c8816418d79a9fbfee121ed6ce0b5b4 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.server.platform.WebServer;
 
index bc353f997781dac11726f29c7255af2737ada7f9..cfd4360fcfdc170aaf9ae10367818b4bbe1f192e 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.PluginInfo;
 
 import static org.assertj.core.api.Assertions.assertThat;
index b1e50cba77c11753033bbc2439869d33a1c7109a..6bd1c7dba916c069b71fe05e6967839b744f2db7 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.SonarException;
 import org.sonar.api.utils.UriReader;
 import org.sonar.process.ProcessProperties;
index 383177f51c8ed6da18a2b4ed5fd6dc62cf848942..4b558c8ce925c7fa7d1fd1211d38f7907be92ed8 100644 (file)
@@ -20,8 +20,8 @@
 package org.sonar.server.project.ws;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.ConfigurationBridge;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.ConfigurationBridge;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.process.ProcessProperties;
 
index af66710a9575576cafd345055ace0abe23ef1e1c..0013337d241f7c7d12573cbd5d3699102359606a 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.project.ws;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbTester;
index ba56ae7b267a55c0c89ae0e164d042a873d045e9..76d1c9facf625f4aaac356cddcde50bbb3c8d5fe 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.utils.System2;
index f35fb4cd915769c1515341d4f427973fb7c9dd35..c5e0685517c8e1a176f6ae1e2b7bd5e679f9d246 100644 (file)
@@ -24,11 +24,11 @@ import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
 import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.util.SequenceUuidFactory;
 import org.sonar.core.util.UuidFactory;
 import org.sonar.db.DbSession;
index f15fe281fca96e5789ca5a2ecebcbf0e02f7ba79..ee0f3fbfae852c362096741e1c522770ec945df8 100644 (file)
@@ -33,7 +33,7 @@ import org.sonar.api.rules.RulePriority;
 import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
 import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.qualityprofile.ActiveRuleDto;
index d796ff9e6fdf809f394964e07602da749a87ac76..d87e2b3fc72c8516d07f1a90d39eda18566cab58 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.notifications.Notification;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
index 6f3f63dba08e8f537c6a49ed7084fb699dbbc6c7..6bf85ee893260ed4dcf754301c555f72b5e6422f 100644 (file)
@@ -29,9 +29,9 @@ import java.util.List;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
index b5be108fc50c66a50e1be429c8b429f8c37fa446..a084f72f5b60f126edaf31809d2a418d7518d043 100644 (file)
@@ -28,9 +28,9 @@ import org.apache.commons.io.IOUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
+import org.sonar.api.impl.utils.JUnitTempFolder;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
-import org.sonar.api.utils.internal.JUnitTempFolder;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
index b6c2221b9c46d79e9556cef778dcaf8e6010c642..dd57f191db2be7ebee31859d604672e9ad15e2ba 100644 (file)
@@ -28,6 +28,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.ArgumentCaptor;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.profiles.ProfileExporter;
 import org.sonar.api.profiles.ProfileImporter;
 import org.sonar.api.profiles.RulesProfile;
@@ -36,7 +37,6 @@ import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.RulePriority;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.ValidationMessages;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.qualityprofile.QProfileDto;
index bdf494dde38fab2afd9a6b83b31858936add6f1c..176bddc24c6003a65774e37236651a745f474341 100644 (file)
@@ -27,9 +27,9 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.ArgumentCaptor;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.util.SequenceUuidFactory;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.DbSession;
index f2c5e27eafc19ab17a0046ac3dff72e0b77a1406..b53733b9cd1eddb5ddcb8e7244e07d8504fb48c4 100644 (file)
@@ -22,8 +22,8 @@ package org.sonar.server.qualityprofile;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.qualityprofile.ActiveRuleKey;
 import org.sonar.db.qualityprofile.OrgActiveRuleDto;
index 97c24b81ba128fb65a009eb93047e96c6abbe0b1..c2c813f10d8093ee13b3efef45d9308b3314af41 100644 (file)
@@ -30,10 +30,10 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.PropertyType;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.qualityprofile.ActiveRuleParamDto;
 import org.sonar.db.qualityprofile.OrgActiveRuleDto;
index cfee689625841b71ca7c5e1c4a9f30640f3647b2..77e3fcc903e3696eee3c27e5740f34d402a849d7 100644 (file)
@@ -26,10 +26,10 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.qualityprofile.ActiveRuleParamDto;
 import org.sonar.db.qualityprofile.OrgActiveRuleDto;
index ec409c97cd26f2770b35477f5c80fbab732b0a93..6b7d6a6dd732c8d53052317a153aea0e12562ef3 100644 (file)
@@ -26,9 +26,9 @@ import java.util.Optional;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Language;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.core.util.UuidFactoryFast;
index 865b237d9179e73872d58ccca8cba5e9fad06b96..7c8b2b93bcc3db9991df095ad0a33818a8b4117f 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.qualityprofile.QProfileChangeDto;
index 7de05d6229c870b0a22ea850eb6a2deee576379f..8551cdcb44f8db04749087cee83112391260b55d 100644 (file)
@@ -25,10 +25,10 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.JUnitTempFolder;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.JUnitTempFolder;
 import org.sonar.core.util.SequenceUuidFactory;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index 8320116e21648919ba7b834e5029ef07ec50aa7d..2a4d83ccc9c7dbfd8c4fdf4116903980bb026380 100644 (file)
@@ -24,7 +24,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.internal.SimpleGetRequest;
+import org.sonar.api.impl.ws.SimpleGetRequest;
 import org.sonar.server.ws.WsTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 366119aa08c94663a0bfb99341fc3db661e7e506..6c19c1a0ef0cd2b5ac4f5830f93850786394f16c 100644 (file)
@@ -26,11 +26,11 @@ import java.util.Random;
 import java.util.function.Consumer;
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleQuery;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index 3637ea757559032bb29f7e6a77d824bce49b64af..2f55c987a57b18b910c33afa7f55965efe27b398 100644 (file)
@@ -36,6 +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.server.debt.DebtModelPluginRepository;
 import org.sonar.server.debt.DebtModelXMLExporter;
 import org.sonar.server.debt.DebtRulesXMLImporter;
index e2b547cf1513f768b873283d6d25bd92a298c5db..2be421542b4d56fb1eb609503db1bb2ef5f5fc0a 100644 (file)
@@ -25,7 +25,7 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.internal.SimpleGetRequest;
+import org.sonar.api.impl.ws.SimpleGetRequest;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
index e1272f7aa5e4c6a0b1b2459d2f0b98ef84e633eb..8384d7176f0557cd6671a5aade6b8c632670805b 100644 (file)
@@ -27,6 +27,7 @@ import org.assertj.core.api.iterable.Extractor;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.RuleStatus;
@@ -34,7 +35,6 @@ import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
index bb86e37ce02b3b54be4c8d9be0f0019283b624b8..d80649148196187b9f47db54a31a702b30b647f2 100644 (file)
@@ -27,8 +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.config.Settings;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.tester.UserSessionRule;
index 59acdbde22f1701ec0af6510a6a3ce326f6ce912..230264e218cd698de867ec172d1e023485933fa7 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
index e49e7914437d861085b0187b6a719c43e04dbf88..56930de11542e2c78f06de5eac631c3f7f7f3eb3 100644 (file)
@@ -27,13 +27,11 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.config.Encryption;
-import org.sonar.api.config.Settings;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsActionTester;
-import org.sonarqube.ws.MediaTypes;
 import org.sonarqube.ws.Settings.GenerateSecretKeyWsResponse;
 
 import static org.assertj.core.api.Assertions.assertThat;
index bd778c40aed476d4183c4d5b2b3426c5c46dea17..07b05d46f3e4ff72979ec92caa848cade2b61d01 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
index 60944a2a608079d082908a1756e291815b1200ad..f3266fade4ecb131aedef651b925af2a9bb4911e 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
index 60fdc81e5d6364b181596db8b7a49cea8040797b..9dc9c21665109ca57ee97cd8d60dba2755b68830 100644 (file)
@@ -26,7 +26,7 @@ import okhttp3.Request;
 import okio.Buffer;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
index 227aff02c155e84ec3cbc57b8ef104dee94f6067..197b196328fb1225c9a6cb16500e91e25abec963 100644 (file)
@@ -29,9 +29,8 @@ import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.mockito.internal.matchers.Any;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.core.platform.EditionProvider;
index 1a20d2e87feae81588a34946e9e5bdd72e38dd3c..c55f40f90b69b1b877ac122106dffba5fc0877da 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypeTree;
index 03d177395e286fd0664af3a79d775f418ed161f9..cb92f591fdc7aab57466400f65528121ae403741 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.ui.ws;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.web.page.Page;
 import org.sonar.api.web.page.PageDefinition;
 import org.sonar.core.platform.PluginInfo;
index d680692abd6aacc2b367eee64f028a7632c1b510..9abfeb01669c27f7b4603c7cc4003343346f70d3 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.user;
 
 import org.junit.Test;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.security.LoginPasswordAuthenticator;
 import org.sonar.api.security.SecurityRealm;
 import org.sonar.api.utils.SonarException;
index 352070eacf32afb021a51d0b6c2e78ef13c46a99..8b86153904bff0de7079e124184661a7f056c6b9 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.server.ws.TestRequest;
index af9a0eca65350270e584656b730a111ef2601738..2b111c3a9e0e60af25cf5206dcf5d94cbd6a4733 100644 (file)
@@ -28,10 +28,10 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.ArgumentCaptor;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.platform.NewUserHandler;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index 2d8d686a8f289c587c37e4ba3c8a774902fe3aa1..7bf516e79c5848c5a733da5ff396d972b26881db 100644 (file)
@@ -23,9 +23,9 @@ import com.google.common.collect.Multimap;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index 8bd07c24f8aaa0747f73ce824da5cc6964658b87..f10ac9b212d3a78381004ea09dc900082cf7b4b6 100644 (file)
@@ -25,9 +25,9 @@ import org.elasticsearch.search.SearchHit;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index a20573fc2ca841b9af6c74e09e4769058d6e66f6..0c5915c47f7fd1f885e5e299dcc277e32aff5c18 100644 (file)
@@ -23,10 +23,10 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.server.authentication.CredentialsLocalAuthentication;
 import org.sonar.server.es.EsTester;
index 3cf1855426d1dc342346e00d8f27342843ed4d2b..c8a60f681d88f7872a5d7b75a531aed0ade2848b 100644 (file)
@@ -25,10 +25,10 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.core.config.CorePropertyDefinitions;
 import org.sonar.db.DbTester;
 import org.sonar.db.user.GroupDto;
index 38de2bb71af86d16e8182feda78326e746620747..cd3bb4523da0d8adcfa8b6ed0317153c7425ad83 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypeTree;
index fc3c15eae8311fad46d5973935dd2cd469adad00..b1d23d8eee5afb458251e57fd544a827e830e878 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypeTree;
index 54aac993829a6d24c7254fb9ab97958f23aacbf1..2f7bebc48fb9f7ed5cbf4e6484161eb55b4d73e0 100644 (file)
@@ -24,8 +24,8 @@ import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
index 1da5327451a329643ebe14b464afcf05e9913b81..498bf6adedb92779e1025161fba2c02f02b1f1ab 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.user.ws;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.db.DbTester;
 import org.sonar.server.organization.TestOrganizationFlags;
 
index 8901a4c7dd518af87e740bb4dd04a54e17361a8a..40bcb63f881767feeb59ea6a2e95f1640d985808 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
index c7f89fc8e423c26846d6fd90cf7bb6f8bde01463..b5696869de237fa95cc2686ece8360ae6959d735 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.config.internal.MapSettings;
+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 1fbd80a8f78db77fb05cc742101d391e7f5f6fd2..50ce373b5920d5813528dfd1dcfaf1a1457e45d6 100644 (file)
@@ -20,8 +20,8 @@
 package org.sonar.server.user.ws;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.ConfigurationBridge;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.ConfigurationBridge;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.process.ProcessProperties;
 
index 1b73b2ba8b5bf8fa5942ae04c294aca9faef893a..5050def00f0b02c63c8fc8523f3477edd9d1f55f 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.usergroups.ws;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.user.GroupDto;
index a98bbe1085d23f3f136060c0b8689c6b5d8b7872..7d96370e5cf94fe7035479152f363deb94714822 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.usergroups.ws;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.web.UserRole;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDbTester;
index 7e738bec02e0ebcaa8ecbcd51978f68d779fc909..72d8529dbb6cfa0b3176622f54c232042f444637 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.usergroups.ws;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
index 6313f12b8112119d271eb8cca60aea8adedec31f..aea0e0d69bd6637b596dbf63545f0104b5818659 100644 (file)
@@ -34,8 +34,8 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.internal.PartImpl;
-import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.api.impl.ws.PartImpl;
+import org.sonar.api.impl.ws.ValidatingRequest;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
index 1e58673735d008679d5179c41fafb91fdbe47553..c3e7f7e1596027a642a4e576eeca20784a233f1d 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.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
index fdd896fec5282bdbb305c4dd28978cdeb2562582..e69153b50338b671b27c4773c3beb644d61fdb88 100644 (file)
@@ -37,8 +37,8 @@ import javax.annotation.Nullable;
 import org.apache.commons.io.IOUtils;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.internal.PartImpl;
-import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.api.impl.ws.PartImpl;
+import org.sonar.api.impl.ws.ValidatingRequest;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.api.utils.text.XmlWriter;
 import org.sonar.server.ws.WsTester.TestResponse.TestStream;
index 87a6131a71433373fa46ef3371e3ebe9e66ee3de..669cd2dde6b1920fb83a051e1c518d9e486b03b7 100644 (file)
@@ -24,6 +24,7 @@ include 'sonar-core'
 include 'sonar-duplications'
 include 'sonar-markdown'
 include 'sonar-plugin-api'
+include 'sonar-plugin-api-impl'
 include 'sonar-scanner-engine'
 include 'sonar-scanner-engine-shaded'
 include 'sonar-scanner-protocol'
index b6ec4aae2d35e26b76fbf7a07fb22e5ead8f0bd5..edf70929c6b80b700ccc14bc4aea83a3a999b817 100644 (file)
@@ -203,8 +203,8 @@ zip.doFirst {
 }
 // Check the size of the archive
 zip.doLast {
-  def minLength = 185000000
-  def maxLength = 199000000
+  def minLength = 198000000
+  def maxLength = 206000000
   def length = archiveFile.get().asFile.length()
   if (length < minLength)
     throw new GradleException("$archiveName size ($length) too small. Min is $minLength")
index c37aff811d4a245f511b8265df21d34656dae562..b547f2cd76cf61afdd456f0ddc79c6075af97b67 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.application;
 
 import java.io.IOException;
 import org.sonar.api.SonarEdition;
-import org.sonar.api.internal.MetadataLoader;
+import org.sonar.api.impl.context.MetadataLoader;
 import org.sonar.application.command.CommandFactory;
 import org.sonar.application.command.CommandFactoryImpl;
 import org.sonar.application.command.JavaVersion;
index aad84e6dbfef64d33afd4acdbb4bb5e832b3f2ac..5a84d54207021c41aeb578049a9be8c0ac8e0d32 100644 (file)
@@ -17,6 +17,7 @@ dependencies {
   compile 'org.slf4j:slf4j-api'
   compile 'org.sonarsource.update-center:sonar-update-center-common'
   compile project(path: ':sonar-plugin-api', configuration: 'shadow')
+  compile project(':sonar-plugin-api-impl')
 
   compileOnly 'com.google.code.findbugs:jsr305'
 
index b26a382ebd17704c7fddd58d89fc478f351893ab..bd93edf4cca209ee39c98b434780da04c61c01f0 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
@@ -60,9 +60,9 @@ public abstract class CoreExtensionsInstaller {
   }
 
   /**
-   * @param container the container into which extensions will be installed
-   * @param extensionFilter filters extensions added to {@link CoreExtension.Context}. When it returns false, the
-   *                        extension is ignored as if it had never been added to the context.
+   * @param container            the container into which extensions will be installed
+   * @param extensionFilter      filters extensions added to {@link CoreExtension.Context}. When it returns false, the
+   *                             extension is ignored as if it had never been added to the context.
    * @param additionalSideFilter applied on top of filtering on {@link #supportedAnnotationType} to decide whether
    *                             extension should be added to container as an object or only as a PropertyDefinition.
    */
index 1c793f31d9b160c2535613ae57984b21318004c8..c8f5baa5bcc06100948f553465c8663a6d3526d7 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -227,7 +227,8 @@ public class CoreExtensionsInstallerTest {
 
   @Test
   @UseDataProvider("allMethodsToAddExtension")
-  public void install_adds_providers_to_container_and_install_extensions_they_provide_when_annotated_with_expected_annotation(BiConsumer<CoreExtension.Context, Collection<Object>> extensionAdder) {
+  public void install_adds_providers_to_container_and_install_extensions_they_provide_when_annotated_with_expected_annotation(
+    BiConsumer<CoreExtension.Context, Collection<Object>> extensionAdder) {
     List<Object> extensions = ImmutableList.of(WestSideProvider.class, PartiallyWestSideProvider.class, EastSideProvider.class);
     CoreExtension coreExtension = newCoreExtension(context -> extensionAdder.accept(context, extensions));
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
index aedf30248af0cf76fba2c523c5c232b7ac979662..0c764b62e3698beeb6feb8cd461a336ac3c7ece8 100644 (file)
@@ -26,10 +26,10 @@ import java.util.Locale;
 import java.util.TimeZone;
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.platform.PluginInfo;
 import org.sonar.core.platform.PluginRepository;
 
index 62bc8f33338526f6ad52e7ebadae04b152ffdb4f..8944bfbf181729ba4e5b6512258fdd99787715cd 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.SonarException;
 
@@ -138,10 +138,10 @@ public class DefaultHttpDownloaderTest {
       @Override
       public boolean matches(Object ex) {
         return
-        // Java 8
-        ex instanceof NoRouteToHostException || ex instanceof SocketException
-        // Java 7 or before
-          || ex instanceof SocketTimeoutException;
+          // Java 8
+          ex instanceof NoRouteToHostException || ex instanceof SocketException
+            // Java 7 or before
+            || ex instanceof SocketTimeoutException;
       }
 
       @Override
diff --git a/sonar-plugin-api-impl/build.gradle b/sonar-plugin-api-impl/build.gradle
new file mode 100644 (file)
index 0000000..6046e6e
--- /dev/null
@@ -0,0 +1,87 @@
+sonarqube {
+  properties {
+    property 'sonar.projectName', "${projectTitle} :: Plugin API Implementation"
+  }
+}
+
+apply plugin: 'com.github.johnrengelman.shadow'
+
+dependencies {
+  // please keep the list grouped by configuration and ordered by name
+
+  compile 'commons-codec:commons-codec'
+  compile 'commons-io:commons-io'
+  compile 'commons-lang:commons-lang'
+  compile 'com.google.code.gson:gson'
+  compile 'org.apache.commons:commons-csv'
+
+  // shaded, but not relocated
+  compile project(':sonar-check-api')
+  compile project(':sonar-plugin-api')
+  compile project(':sonar-ws')
+
+
+  shadow 'org.codehaus.staxmate:staxmate'
+  shadow 'org.codehaus.woodstox:stax2-api'
+  shadow 'org.codehaus.woodstox:woodstox-core-lgpl'
+
+  compileOnly 'ch.qos.logback:logback-classic'
+  compileOnly 'ch.qos.logback:logback-core'
+  compileOnly 'com.google.code.findbugs:jsr305'
+  compileOnly 'javax.servlet:javax.servlet-api'
+  compileOnly 'junit:junit'
+  compileOnly 'org.slf4j:slf4j-api'
+
+  testCompile 'com.google.guava:guava'
+  testCompile 'com.tngtech.java:junit-dataprovider'
+  testCompile 'org.assertj:assertj-core'
+  testCompile 'org.mockito:mockito-core'
+  testCompile project(':sonar-scanner-engine')
+  testCompile project(':server:sonar-server')
+
+}
+
+sourceSets {
+  // Make the compileOnly dependencies available when compiling/running tests
+  test.compileClasspath += configurations.compileOnly + configurations.shadow
+  test.runtimeClasspath += configurations.compileOnly + configurations.shadow
+}
+
+def on3Digits(version) {
+  def projectversion3digits = version - ~/-\w+/
+  projectversion3digits = projectversion3digits.tokenize('.').plus(0).take(3).join('.')
+}
+
+import org.apache.tools.ant.filters.ReplaceTokens
+processResources {
+  filter ReplaceTokens, tokens: [
+    // The build version is composed of 4 fields, including the semantic version and the build number provided by Travis.
+    'project.buildVersion': project.version.endsWith('SNAPSHOT') ? project.version : on3Digits(project.version) + '.' + System.getProperty("buildNumber"),
+    'project.version.3digits': project.version.endsWith('SNAPSHOT') ? project.version : on3Digits(project.version)
+  ]
+}
+
+shadowJar {
+  configurations = [project.configurations.default]
+  relocate('com.google', 'org.sonar.api.internal.google')
+  relocate('org.apache.commons', 'org.sonar.api.internal.apachecommons')
+  dependencies {
+      exclude(dependency('org.codehaus.woodstox:woodstox-core-lgpl'))
+      exclude(dependency('org.codehaus.woodstox:stax2-api'))
+      exclude(dependency('org.codehaus.staxmate:staxmate'))
+   }
+}
+
+artifactoryPublish.skip = false
+
+publishing {
+  publications {
+    mavenJava(MavenPublication) {
+      artifact source: shadowJar, classifier: null
+      if (release) {
+        artifact sourcesJar
+        artifact javadocJar
+      }
+    }
+  }
+}
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
new file mode 100644 (file)
index 0000000..a46bf1a
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..b893852
--- /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.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
new file mode 100644 (file)
index 0000000..eb714dc
--- /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.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/impl/config/ConfigurationBridge.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/config/ConfigurationBridge.java
new file mode 100644 (file)
index 0000000..fea9800
--- /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.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
new file mode 100644 (file)
index 0000000..61ac601
--- /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.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
new file mode 100644 (file)
index 0000000..3d7d9f0
--- /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.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
new file mode 100644 (file)
index 0000000..bcccfdd
--- /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.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
new file mode 100644 (file)
index 0000000..575fc47
--- /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.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
new file mode 100644 (file)
index 0000000..211e5ce
--- /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.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
new file mode 100644 (file)
index 0000000..4e4074e
--- /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.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
new file mode 100644 (file)
index 0000000..632005c
--- /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.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
new file mode 100644 (file)
index 0000000..2834b34
--- /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.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
new file mode 100644 (file)
index 0000000..db015d9
--- /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.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
new file mode 100644 (file)
index 0000000..5dae957
--- /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.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
new file mode 100644 (file)
index 0000000..14acba4
--- /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.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
new file mode 100644 (file)
index 0000000..53f1800
--- /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.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
new file mode 100644 (file)
index 0000000..61561b0
--- /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.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
new file mode 100644 (file)
index 0000000..476a719
--- /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.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
new file mode 100644 (file)
index 0000000..0ed1500
--- /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.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
new file mode 100644 (file)
index 0000000..541ee95
--- /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.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
new file mode 100644 (file)
index 0000000..0bf0e51
--- /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.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
new file mode 100644 (file)
index 0000000..8078db1
--- /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.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
new file mode 100644 (file)
index 0000000..e177041
--- /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.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
new file mode 100644 (file)
index 0000000..30a813d
--- /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.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
new file mode 100644 (file)
index 0000000..d956d06
--- /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.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
new file mode 100644 (file)
index 0000000..e731e7f
--- /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.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
new file mode 100644 (file)
index 0000000..06218a6
--- /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.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
new file mode 100644 (file)
index 0000000..eaa5672
--- /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.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
new file mode 100644 (file)
index 0000000..b298b05
--- /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.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
new file mode 100644 (file)
index 0000000..ba5093b
--- /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.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
new file mode 100644 (file)
index 0000000..8384258
--- /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.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
new file mode 100644 (file)
index 0000000..1b0ad31
--- /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.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
new file mode 100644 (file)
index 0000000..9c9bce6
--- /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.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
new file mode 100644 (file)
index 0000000..10a7978
--- /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.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
new file mode 100644 (file)
index 0000000..c83cc64
--- /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.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
new file mode 100644 (file)
index 0000000..1a964b4
--- /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.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
new file mode 100644 (file)
index 0000000..d2ea1f3
--- /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.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
new file mode 100644 (file)
index 0000000..fe005c6
--- /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.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
new file mode 100644 (file)
index 0000000..d6c1d78
--- /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.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
new file mode 100644 (file)
index 0000000..7775c56
--- /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.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
new file mode 100644 (file)
index 0000000..94fac58
--- /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.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
new file mode 100644 (file)
index 0000000..e553625
--- /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.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
new file mode 100644 (file)
index 0000000..4841c55
--- /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.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
new file mode 100644 (file)
index 0000000..bf8e566
--- /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.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
new file mode 100644 (file)
index 0000000..aaba4c8
--- /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.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
new file mode 100644 (file)
index 0000000..5de4fee
--- /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.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
new file mode 100644 (file)
index 0000000..3f93903
--- /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.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
new file mode 100644 (file)
index 0000000..1e27675
--- /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.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
new file mode 100644 (file)
index 0000000..a1cb9f4
--- /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.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
new file mode 100644 (file)
index 0000000..bcac4e0
--- /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.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
new file mode 100644 (file)
index 0000000..04d56ee
--- /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.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
new file mode 100644 (file)
index 0000000..f9d5705
--- /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.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
new file mode 100644 (file)
index 0000000..60fea97
--- /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.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
new file mode 100644 (file)
index 0000000..aa33a1e
--- /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.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
new file mode 100644 (file)
index 0000000..8705bf2
--- /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.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
new file mode 100644 (file)
index 0000000..aebe8f9
--- /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.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
new file mode 100644 (file)
index 0000000..6b2329c
--- /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.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
new file mode 100644 (file)
index 0000000..3bef1e9
--- /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.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
new file mode 100644 (file)
index 0000000..8d4146c
--- /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.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
new file mode 100644 (file)
index 0000000..318a473
--- /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.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
new file mode 100644 (file)
index 0000000..9add14c
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..c7c7b5e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..36c84be
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..1513fa2
--- /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.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
new file mode 100644 (file)
index 0000000..5508461
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..c4149ec
--- /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.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
new file mode 100644 (file)
index 0000000..9b789d2
--- /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.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
new file mode 100644 (file)
index 0000000..ae17adb
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..c7e133d
--- /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.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
new file mode 100644 (file)
index 0000000..d2919ab
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..152c571
--- /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.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
new file mode 100644 (file)
index 0000000..5b60ac2
--- /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.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
new file mode 100644 (file)
index 0000000..6a373ac
--- /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.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
new file mode 100644 (file)
index 0000000..c4f6ca3
--- /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.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
new file mode 100644 (file)
index 0000000..73ec864
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..26f74db
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..6877a77
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..35d4fbe
--- /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.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
new file mode 100644 (file)
index 0000000..b304d31
--- /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.impl.sensor;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultDebtRemediationFunctions.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultDebtRemediationFunctions.java
new file mode 100644 (file)
index 0000000..52bf120
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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 javax.annotation.Nullable;
+import org.sonar.api.server.debt.DebtRemediationFunction;
+import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
+import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.utils.MessageException;
+
+/**
+ * Factory of {@link org.sonar.api.server.debt.DebtRemediationFunction} that keeps
+ * a context of rule for better error messages. Used only when declaring rules.
+ *
+ * @see org.sonar.api.server.rule.RulesDefinition
+ */
+class DefaultDebtRemediationFunctions implements RulesDefinition.DebtRemediationFunctions {
+
+  private final String repoKey;
+  private final String key;
+
+  DefaultDebtRemediationFunctions(String repoKey, String key) {
+    this.repoKey = repoKey;
+    this.key = key;
+  }
+
+  @Override
+  public DebtRemediationFunction linear(String gapMultiplier) {
+    return create(DefaultDebtRemediationFunction.Type.LINEAR, gapMultiplier, null);
+  }
+
+  @Override
+  public DebtRemediationFunction linearWithOffset(String gapMultiplier, String baseEffort) {
+    return create(DefaultDebtRemediationFunction.Type.LINEAR_OFFSET, gapMultiplier, baseEffort);
+  }
+
+  @Override
+  public DebtRemediationFunction constantPerIssue(String baseEffort) {
+    return create(DefaultDebtRemediationFunction.Type.CONSTANT_ISSUE, null, baseEffort);
+  }
+
+  @Override
+  public DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String gapMultiplier, @Nullable String baseEffort) {
+    try {
+      return new DefaultDebtRemediationFunction(type, gapMultiplier, baseEffort);
+    } catch (Exception e) {
+      throw MessageException.of(String.format("The rule '%s:%s' is invalid : %s ", this.repoKey, this.key, e.getMessage()));
+    }
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewParam.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewParam.java
new file mode 100644 (file)
index 0000000..6a026db
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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 javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.server.rule.RuleParamType;
+import org.sonar.api.server.rule.RulesDefinition;
+
+import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
+
+public class DefaultNewParam extends RulesDefinition.NewParam {
+  private final String key;
+  private String name;
+  private String description;
+  private String defaultValue;
+  private RuleParamType type = RuleParamType.STRING;
+
+  DefaultNewParam(String key) {
+    this.key = this.name = key;
+  }
+
+  @Override
+  public String key() {
+    return key;
+  }
+
+  @Override
+  public DefaultNewParam setName(@Nullable String s) {
+    // name must never be null.
+    this.name = StringUtils.defaultIfBlank(s, key);
+    return this;
+  }
+
+  @Override
+  public DefaultNewParam setType(RuleParamType t) {
+    this.type = t;
+    return this;
+  }
+
+  @Override
+  public DefaultNewParam setDescription(@Nullable String s) {
+    this.description = StringUtils.defaultIfBlank(s, null);
+    return this;
+  }
+
+  @Override
+  public DefaultNewParam setDefaultValue(@Nullable String s) {
+    this.defaultValue = defaultIfEmpty(s, null);
+    return this;
+  }
+
+  public String name() {
+    return name;
+  }
+
+  public String description() {
+    return description;
+  }
+
+  public String defaultValue() {
+    return defaultValue;
+  }
+
+  public RuleParamType type() {
+    return type;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewRepository.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewRepository.java
new file mode 100644 (file)
index 0000000..9fe3584
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+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 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) {
+    this.context = context;
+    this.key = key;
+    this.name = key;
+    this.language = language;
+    this.isExternal = isExternal;
+  }
+
+  @Override
+  public boolean isExternal() {
+    return isExternal;
+  }
+
+  @Override
+  public String key() {
+    return key;
+  }
+
+  String language() {
+    return language;
+  }
+
+  Map<String, RulesDefinition.NewRule> newRules() {
+    return newRules;
+  }
+
+  String name() {
+    return name;
+  }
+
+  @Override
+  public DefaultNewRepository setName(@Nullable String s) {
+    if (StringUtils.isNotEmpty(s)) {
+      this.name = s;
+    }
+    return this;
+  }
+
+  @Override
+  public RulesDefinition.NewRule createRule(String ruleKey) {
+    checkArgument(!newRules.containsKey(ruleKey), "The rule '%s' of repository '%s' is declared several times", ruleKey, key);
+    RulesDefinition.NewRule newRule = new DefaultNewRule(context.currentPluginKey(), key, ruleKey);
+    newRules.put(ruleKey, newRule);
+    return newRule;
+  }
+
+  @CheckForNull
+  @Override
+  public RulesDefinition.NewRule rule(String ruleKey) {
+    return newRules.get(ruleKey);
+  }
+
+  @Override
+  public Collection<RulesDefinition.NewRule> rules() {
+    return newRules.values();
+  }
+
+  @Override
+  public void done() {
+    // note that some validations can be done here, for example for
+    // verifying that at least one rule is declared
+
+    context.registerRepository(this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("NewRepository{");
+    sb.append("key='").append(key).append('\'');
+    sb.append(", language='").append(language).append('\'');
+    sb.append('}');
+    return sb.toString();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultNewRule.java
new file mode 100644 (file)
index 0000000..465b8f9
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * 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.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleScope;
+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.server.rule.RuleTagFormat;
+import org.sonar.api.server.rule.RulesDefinition;
+
+import static java.lang.String.format;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.commons.lang.StringUtils.isEmpty;
+import static org.apache.commons.lang.StringUtils.trimToNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+class DefaultNewRule extends RulesDefinition.NewRule {
+  private final String pluginKey;
+  private final String repoKey;
+  private final String key;
+  private RuleType type;
+  private String name;
+  private String htmlDescription;
+  private String markdownDescription;
+  private String internalKey;
+  private String severity = Severity.MAJOR;
+  private boolean template;
+  private RuleStatus status = RuleStatus.defaultStatus();
+  private DebtRemediationFunction debtRemediationFunction;
+  private String gapDescription;
+  private final Set<String> tags = new TreeSet<>();
+  private final Set<String> securityStandards = new TreeSet<>();
+  private final Map<String, RulesDefinition.NewParam> paramsByKey = new HashMap<>();
+  private final RulesDefinition.DebtRemediationFunctions functions;
+  private boolean activatedByDefault;
+  private RuleScope scope;
+  private final Set<RuleKey> deprecatedRuleKeys = new TreeSet<>();
+
+  DefaultNewRule(@Nullable String pluginKey, String repoKey, String key) {
+    this.pluginKey = pluginKey;
+    this.repoKey = repoKey;
+    this.key = key;
+    this.functions = new DefaultDebtRemediationFunctions(repoKey, key);
+  }
+
+  @Override
+  public String key() {
+    return this.key;
+  }
+
+  @CheckForNull
+  @Override
+  public RuleScope scope() {
+    return this.scope;
+  }
+
+  @Override
+  public DefaultNewRule setScope(RuleScope scope) {
+    this.scope = scope;
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setName(String s) {
+    this.name = trimToNull(s);
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setTemplate(boolean template) {
+    this.template = template;
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setActivatedByDefault(boolean activatedByDefault) {
+    this.activatedByDefault = activatedByDefault;
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setSeverity(String s) {
+    checkArgument(Severity.ALL.contains(s), "Severity of rule %s is not correct: %s", this, s);
+    this.severity = s;
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setType(RuleType t) {
+    this.type = t;
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setHtmlDescription(@Nullable String s) {
+    checkState(markdownDescription == null, "Rule '%s' already has a Markdown description", this);
+    this.htmlDescription = trimToNull(s);
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setHtmlDescription(@Nullable URL classpathUrl) {
+    if (classpathUrl != null) {
+      try {
+        setHtmlDescription(IOUtils.toString(classpathUrl, UTF_8));
+      } catch (IOException e) {
+        throw new IllegalStateException("Fail to read: " + classpathUrl, e);
+      }
+    } else {
+      this.htmlDescription = null;
+    }
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setMarkdownDescription(@Nullable String s) {
+    checkState(htmlDescription == null, "Rule '%s' already has an HTML description", this);
+    this.markdownDescription = trimToNull(s);
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setMarkdownDescription(@Nullable URL classpathUrl) {
+    if (classpathUrl != null) {
+      try {
+        setMarkdownDescription(IOUtils.toString(classpathUrl, UTF_8));
+      } catch (IOException e) {
+        throw new IllegalStateException("Fail to read: " + classpathUrl, e);
+      }
+    } else {
+      this.markdownDescription = null;
+    }
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setStatus(RuleStatus status) {
+    checkArgument(RuleStatus.REMOVED != status, "Status 'REMOVED' is not accepted on rule '%s'", this);
+    this.status = status;
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setDebtSubCharacteristic(@Nullable String s) {
+    return this;
+  }
+
+  @Override
+  public RulesDefinition.DebtRemediationFunctions debtRemediationFunctions() {
+    return functions;
+  }
+
+  @Override
+  public DefaultNewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn) {
+    this.debtRemediationFunction = fn;
+    return this;
+  }
+
+  @Deprecated
+  @Override
+  public DefaultNewRule setEffortToFixDescription(@Nullable String s) {
+    return setGapDescription(s);
+  }
+
+  @Override
+  public DefaultNewRule setGapDescription(@Nullable String s) {
+    this.gapDescription = s;
+    return this;
+  }
+
+  @Override
+  public RulesDefinition.NewParam createParam(String paramKey) {
+    checkArgument(!paramsByKey.containsKey(paramKey), "The parameter '%s' is declared several times on the rule %s", paramKey, this);
+    DefaultNewParam param = new DefaultNewParam(paramKey);
+    paramsByKey.put(paramKey, param);
+    return param;
+  }
+
+  @CheckForNull
+  @Override
+  public RulesDefinition.NewParam param(String paramKey) {
+    return paramsByKey.get(paramKey);
+  }
+
+  @Override
+  public Collection<RulesDefinition.NewParam> params() {
+    return paramsByKey.values();
+  }
+
+  @Override
+  public DefaultNewRule addTags(String... list) {
+    for (String tag : list) {
+      RuleTagFormat.validate(tag);
+      tags.add(tag);
+    }
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setTags(String... list) {
+    tags.clear();
+    addTags(list);
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule addOwaspTop10(RulesDefinition.OwaspTop10... standards) {
+    for (RulesDefinition.OwaspTop10 owaspTop10 : standards) {
+      String standard = "owaspTop10:" + owaspTop10.name().toLowerCase(Locale.ENGLISH);
+      securityStandards.add(standard);
+    }
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule addCwe(int... nums) {
+    for (int num : nums) {
+      String standard = "cwe:" + num;
+      securityStandards.add(standard);
+    }
+    return this;
+  }
+
+  @Override
+  public DefaultNewRule setInternalKey(@Nullable String s) {
+    this.internalKey = s;
+    return this;
+  }
+
+  void validate() {
+    if (isEmpty(name)) {
+      throw new IllegalStateException(format("Name of rule %s is empty", this));
+    }
+    if (isEmpty(htmlDescription) && isEmpty(markdownDescription)) {
+      throw new IllegalStateException(format("One of HTML description or Markdown description must be defined for rule %s", this));
+    }
+  }
+
+  @Override
+  public DefaultNewRule addDeprecatedRuleKey(String repository, String key) {
+    deprecatedRuleKeys.add(RuleKey.of(repository, key));
+    return this;
+  }
+
+  String pluginKey() {
+    return pluginKey;
+  }
+
+  String repoKey() {
+    return repoKey;
+  }
+
+  RuleType type() {
+    return type;
+  }
+
+  String name() {
+    return name;
+  }
+
+  String htmlDescription() {
+    return htmlDescription;
+  }
+
+  String markdownDescription() {
+    return markdownDescription;
+  }
+
+  @CheckForNull
+  String internalKey() {
+    return internalKey;
+  }
+
+  String severity() {
+    return severity;
+  }
+
+  boolean template() {
+    return template;
+  }
+
+  RuleStatus status() {
+    return status;
+  }
+
+  DebtRemediationFunction debtRemediationFunction() {
+    return debtRemediationFunction;
+  }
+
+  String gapDescription() {
+    return gapDescription;
+  }
+
+  Set<String> tags() {
+    return tags;
+  }
+
+  Set<String> securityStandards() {
+    return securityStandards;
+  }
+
+  Map<String, RulesDefinition.NewParam> paramsByKey() {
+    return paramsByKey;
+  }
+
+  boolean activatedByDefault() {
+    return activatedByDefault;
+  }
+
+  Set<RuleKey> deprecatedRuleKeys() {
+    return deprecatedRuleKeys;
+  }
+
+  @Override
+  public String toString() {
+    return format("[repository=%s, key=%s]", repoKey, key);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultParam.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultParam.java
new file mode 100644 (file)
index 0000000..ea41445
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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 javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.server.rule.RuleParamType;
+import org.sonar.api.server.rule.RulesDefinition;
+
+@Immutable
+public class DefaultParam implements RulesDefinition.Param {
+  private final String key;
+  private final String name;
+  private final String description;
+  private final String defaultValue;
+  private final RuleParamType type;
+
+  DefaultParam(DefaultNewParam newParam) {
+    this.key = newParam.key();
+    this.name = newParam.name();
+    this.description = newParam.description();
+    this.defaultValue = newParam.defaultValue();
+    this.type = newParam.type();
+  }
+
+  @Override
+  public String key() {
+    return key;
+  }
+
+  @Override
+  public String name() {
+    return name;
+  }
+
+  @Override
+  @Nullable
+  public String description() {
+    return description;
+  }
+
+  @Override
+  @Nullable
+  public String defaultValue() {
+    return defaultValue;
+  }
+
+  @Override
+  public RuleParamType type() {
+    return type;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    RulesDefinition.Param that = (RulesDefinition.Param) o;
+    return key.equals(that.key());
+  }
+
+  @Override
+  public int hashCode() {
+    return key.hashCode();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultRepository.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultRepository.java
new file mode 100644 (file)
index 0000000..8d56b97
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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 javax.annotation.concurrent.Immutable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.utils.log.Loggers;
+
+import static java.lang.String.format;
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.unmodifiableMap;
+
+@Immutable
+class DefaultRepository implements RulesDefinition.Repository {
+  private final String key;
+  private final String language;
+  private final String name;
+  private final boolean isExternal;
+  private final Map<String, RulesDefinition.Rule> rulesByKey;
+
+  DefaultRepository(DefaultNewRepository newRepository, @Nullable RulesDefinition.Repository mergeInto) {
+    this.key = newRepository.key();
+    this.language = newRepository.language();
+    this.isExternal = newRepository.isExternal();
+    Map<String, RulesDefinition.Rule> ruleBuilder = new HashMap<>();
+    if (mergeInto != null) {
+      if (!StringUtils.equals(newRepository.language(), mergeInto.language()) || !StringUtils.equals(newRepository.key(), mergeInto.key())) {
+        throw new IllegalArgumentException(format("Bug - language and key of the repositories to be merged should be the sames: %s and %s", newRepository, mergeInto));
+      }
+      this.name = StringUtils.defaultIfBlank(mergeInto.name(), newRepository.name());
+      for (RulesDefinition.Rule rule : mergeInto.rules()) {
+        if (!newRepository.key().startsWith("common-") && ruleBuilder.containsKey(rule.key())) {
+          Loggers.get(getClass()).warn("The rule '{}' of repository '{}' is declared several times", rule.key(), mergeInto.key());
+        }
+        ruleBuilder.put(rule.key(), rule);
+      }
+    } else {
+      this.name = newRepository.name();
+    }
+    for (RulesDefinition.NewRule newRule : newRepository.newRules().values()) {
+      DefaultNewRule defaultNewRule = (DefaultNewRule) newRule;
+      defaultNewRule.validate();
+      ruleBuilder.put(newRule.key(), new DefaultRule(this, defaultNewRule));
+    }
+    this.rulesByKey = unmodifiableMap(ruleBuilder);
+  }
+
+  @Override
+  public String key() {
+    return key;
+  }
+
+  @Override
+  public String language() {
+    return language;
+  }
+
+  @Override
+  public String name() {
+    return name;
+  }
+
+  @Override
+  public boolean isExternal() {
+    return isExternal;
+  }
+
+  @Override
+  @CheckForNull
+  public RulesDefinition.Rule rule(String ruleKey) {
+    return rulesByKey.get(ruleKey);
+  }
+
+  @Override
+  public List<RulesDefinition.Rule> rules() {
+    return unmodifiableList(new ArrayList<>(rulesByKey.values()));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    DefaultRepository that = (DefaultRepository) o;
+    return key.equals(that.key);
+  }
+
+  @Override
+  public int hashCode() {
+    return key.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("Repository{");
+    sb.append("key='").append(key).append('\'');
+    sb.append(", language='").append(language).append('\'');
+    sb.append('}');
+    return sb.toString();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultRule.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/DefaultRule.java
new file mode 100644 (file)
index 0000000..d56201d
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * 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.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.annotation.CheckForNull;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleScope;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rules.RuleType;
+import org.sonar.api.server.debt.DebtRemediationFunction;
+import org.sonar.api.server.rule.RuleTagsToTypeConverter;
+import org.sonar.api.server.rule.RulesDefinition;
+
+import static java.lang.String.format;
+import static java.util.Collections.unmodifiableList;
+
+@Immutable
+public class DefaultRule implements RulesDefinition.Rule {
+  private final String pluginKey;
+  private final RulesDefinition.Repository repository;
+  private final String repoKey;
+  private final String key;
+  private final String name;
+  private final RuleType type;
+  private final String htmlDescription;
+  private final String markdownDescription;
+  private final String internalKey;
+  private final String severity;
+  private final boolean template;
+  private final DebtRemediationFunction debtRemediationFunction;
+  private final String gapDescription;
+  private final Set<String> tags;
+  private final Set<String> securityStandards;
+  private final Map<String, RulesDefinition.Param> params;
+  private final RuleStatus status;
+  private final boolean activatedByDefault;
+  private final RuleScope scope;
+  private final Set<RuleKey> deprecatedRuleKeys;
+
+  DefaultRule(DefaultRepository repository, DefaultNewRule newRule) {
+    this.pluginKey = newRule.pluginKey();
+    this.repository = repository;
+    this.repoKey = newRule.repoKey();
+    this.key = newRule.key();
+    this.name = newRule.name();
+    this.htmlDescription = newRule.htmlDescription();
+    this.markdownDescription = newRule.markdownDescription();
+    this.internalKey = newRule.internalKey();
+    this.severity = newRule.severity();
+    this.template = newRule.template();
+    this.status = newRule.status();
+    this.debtRemediationFunction = newRule.debtRemediationFunction();
+    this.gapDescription = newRule.gapDescription();
+    this.scope = newRule.scope() == null ? RuleScope.MAIN : newRule.scope();
+    this.type = newRule.type() == null ? RuleTagsToTypeConverter.convert(newRule.tags()) : newRule.type();
+    Set<String> tagsBuilder = new TreeSet<>(newRule.tags());
+    tagsBuilder.removeAll(RuleTagsToTypeConverter.RESERVED_TAGS);
+    this.tags = Collections.unmodifiableSet(tagsBuilder);
+    this.securityStandards = Collections.unmodifiableSet(new TreeSet<>(newRule.securityStandards()));
+    Map<String, RulesDefinition.Param> paramsBuilder = new HashMap<>();
+    for (RulesDefinition.NewParam newParam : newRule.paramsByKey().values()) {
+      paramsBuilder.put(newParam.key(), new DefaultParam((DefaultNewParam) newParam));
+    }
+    this.params = Collections.unmodifiableMap(paramsBuilder);
+    this.activatedByDefault = newRule.activatedByDefault();
+    this.deprecatedRuleKeys = Collections.unmodifiableSet(new TreeSet<>(newRule.deprecatedRuleKeys()));
+  }
+
+  public RulesDefinition.Repository repository() {
+    return repository;
+  }
+
+  @Override
+  @CheckForNull
+  public String pluginKey() {
+    return pluginKey;
+  }
+
+  @Override
+  public String key() {
+    return key;
+  }
+
+  @Override
+  public String name() {
+    return name;
+  }
+
+  @Override
+  public RuleScope scope() {
+    return scope;
+  }
+
+  @Override
+  public RuleType type() {
+    return type;
+  }
+
+  @Override
+  public String severity() {
+    return severity;
+  }
+
+  @Override
+  @CheckForNull
+  public String htmlDescription() {
+    return htmlDescription;
+  }
+
+  @Override
+  @CheckForNull
+  public String markdownDescription() {
+    return markdownDescription;
+  }
+
+  @Override
+  public boolean template() {
+    return template;
+  }
+
+  @Override
+  public boolean activatedByDefault() {
+    return activatedByDefault;
+  }
+
+  @Override
+  public RuleStatus status() {
+    return status;
+  }
+
+  @CheckForNull
+  @Deprecated
+  @Override
+  public String debtSubCharacteristic() {
+    return null;
+  }
+
+  @CheckForNull
+  @Override
+  public DebtRemediationFunction debtRemediationFunction() {
+    return debtRemediationFunction;
+  }
+
+  @Deprecated
+  @CheckForNull
+  @Override
+  public String effortToFixDescription() {
+    return gapDescription();
+  }
+
+  @CheckForNull
+  @Override
+  public String gapDescription() {
+    return gapDescription;
+  }
+
+  @CheckForNull
+  @Override
+  public RulesDefinition.Param param(String key) {
+    return params.get(key);
+  }
+
+  @Override
+  public List<RulesDefinition.Param> params() {
+    return unmodifiableList(new ArrayList<>(params.values()));
+  }
+
+  @Override
+  public Set<String> tags() {
+    return tags;
+  }
+
+  @Override
+  public Set<String> securityStandards() {
+    return securityStandards;
+  }
+
+  @Override
+  public Set<RuleKey> deprecatedRuleKeys() {
+    return deprecatedRuleKeys;
+  }
+
+  @CheckForNull
+  @Override
+  public String internalKey() {
+    return internalKey;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    DefaultRule other = (DefaultRule) o;
+    return key.equals(other.key) && repoKey.equals(other.repoKey);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = repoKey.hashCode();
+    result = 31 * result + key.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return format("[repository=%s, key=%s]", repoKey, 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
new file mode 100644 (file)
index 0000000..7d47fc2
--- /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 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/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/server/package-info.java
new file mode 100644 (file)
index 0000000..42efaa6
--- /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.impl.server;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/AlwaysIncreasingSystem2.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/AlwaysIncreasingSystem2.java
new file mode 100644 (file)
index 0000000..ab25411
--- /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.impl.utils;
+
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
+import org.sonar.api.utils.System2;
+
+import static org.sonar.api.utils.Preconditions.checkArgument;
+
+/**
+ * A subclass of {@link System2} which implementation of {@link System2#now()} always return a bigger value than the
+ * previous returned value.
+ * <p>
+ * This class is intended to be used in Unit tests.
+ * </p>
+ */
+public class AlwaysIncreasingSystem2 extends System2 {
+  private final AtomicLong now;
+  private final long increment;
+
+  private AlwaysIncreasingSystem2(Supplier<Long> initialValueSupplier, long increment) {
+    checkArgument(increment > 0, "increment must be > 0");
+    long initialValue = initialValueSupplier.get();
+    checkArgument(initialValue >= 0, "Initial value must be >= 0");
+    this.now = new AtomicLong(initialValue);
+    this.increment = increment;
+  }
+
+  public AlwaysIncreasingSystem2(long increment) {
+    this(AlwaysIncreasingSystem2::randomInitialValue, increment);
+  }
+
+  public AlwaysIncreasingSystem2(long initialValue, int increment) {
+    this(() -> initialValue, increment);
+  }
+
+  /**
+   * Values returned by {@link #now()} will start with a random value and increment by 100.
+   */
+  public AlwaysIncreasingSystem2() {
+    this(AlwaysIncreasingSystem2::randomInitialValue, 100);
+  }
+
+  @Override
+  public long now() {
+    return now.getAndAdd(increment);
+  }
+
+  private static long randomInitialValue() {
+    return (long) Math.abs(new Random().nextInt(2_000_000));
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java
new file mode 100644 (file)
index 0000000..369058f
--- /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.impl.utils;
+
+import java.nio.file.FileVisitResult;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import org.apache.commons.io.FileUtils;
+import org.sonar.api.utils.TempFolder;
+
+import javax.annotation.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+public class DefaultTempFolder implements TempFolder {
+  private static final Logger LOG = Loggers.get(DefaultTempFolder.class);
+
+  private final File tempDir;
+  private final boolean deleteOnExit;
+
+  public DefaultTempFolder(File tempDir) {
+    this(tempDir, false);
+  }
+
+  public DefaultTempFolder(File tempDir, boolean deleteOnExit) {
+    this.tempDir = tempDir;
+    this.deleteOnExit = deleteOnExit;
+  }
+
+  @Override
+  public File newDir() {
+    return createTempDir(tempDir.toPath()).toFile();
+  }
+
+  private static Path createTempDir(Path baseDir) {
+    try {
+      return Files.createTempDirectory(baseDir, null);
+    } catch (IOException e) {
+      throw new IllegalStateException("Failed to create temp directory", e);
+    }
+  }
+
+  @Override
+  public File newDir(String name) {
+    File dir = new File(tempDir, name);
+    try {
+      FileUtils.forceMkdir(dir);
+    } catch (IOException e) {
+      throw new IllegalStateException("Failed to create temp directory - " + dir, e);
+    }
+    return dir;
+  }
+
+  @Override
+  public File newFile() {
+    return newFile(null, null);
+  }
+
+  @Override
+  public File newFile(@Nullable String prefix, @Nullable String suffix) {
+    return createTempFile(tempDir.toPath(), prefix, suffix).toFile();
+  }
+
+  private static Path createTempFile(Path baseDir, String prefix, String suffix) {
+    try {
+      return Files.createTempFile(baseDir, prefix, suffix);
+    } catch (IOException e) {
+      throw new IllegalStateException("Failed to create temp file", e);
+    }
+  }
+
+  public void clean() {
+    try {
+      if (tempDir.exists()) {
+        Files.walkFileTree(tempDir.toPath(), DeleteRecursivelyFileVisitor.INSTANCE);
+      }
+    } catch (IOException e) {
+      LOG.error("Failed to delete temp folder", e);
+    }
+  }
+
+  public void stop() {
+    if (deleteOnExit) {
+      clean();
+    }
+  }
+
+  private static final class DeleteRecursivelyFileVisitor extends SimpleFileVisitor<Path> {
+    public static final DeleteRecursivelyFileVisitor INSTANCE = new DeleteRecursivelyFileVisitor();
+
+    @Override
+    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+      Files.deleteIfExists(file);
+      return FileVisitResult.CONTINUE;
+    }
+
+    @Override
+    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+      Files.deleteIfExists(dir);
+      return FileVisitResult.CONTINUE;
+    }
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/JUnitTempFolder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/JUnitTempFolder.java
new file mode 100644 (file)
index 0000000..a52da93
--- /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.impl.utils;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.rules.ExternalResource;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.sonar.api.utils.TempFolder;
+
+import javax.annotation.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Implementation of {@link org.sonar.api.utils.TempFolder} to be used
+ * only in JUnit tests. It wraps {@link org.junit.rules.TemporaryFolder}.
+ * <br>
+ * Example:
+ * <pre>
+ * public class MyTest {
+ *   &#064;@org.junit.Rule
+ *   public JUnitTempFolder temp = new JUnitTempFolder();
+ *
+ *   &#064;@org.junit.Test
+ *   public void myTest() throws Exception {
+ *     File dir = temp.newDir();
+ *     // ...
+ *   }
+ * }
+ * </pre>
+ *
+ * @since 5.1
+ */
+public class JUnitTempFolder extends ExternalResource implements TempFolder {
+
+  private final TemporaryFolder junit = new TemporaryFolder();
+
+  @Override
+  public Statement apply(Statement base, Description description) {
+    return junit.apply(base, description);
+  }
+
+  @Override
+  protected void before() throws Throwable {
+    junit.create();
+  }
+
+  @Override
+  protected void after() {
+    junit.delete();
+  }
+
+  @Override
+  public File newDir() {
+    try {
+      return junit.newFolder();
+    } catch (IOException e) {
+      throw new IllegalStateException("Fail to create temp dir", e);
+    }
+  }
+
+  @Override
+  public File newDir(String name) {
+    try {
+      return junit.newFolder(name);
+    } catch (IOException e) {
+      throw new IllegalStateException("Fail to create temp dir", e);
+    }
+  }
+
+  @Override
+  public File newFile() {
+    try {
+      return junit.newFile();
+    } catch (IOException e) {
+      throw new IllegalStateException("Fail to create temp file", e);
+    }
+  }
+
+  @Override
+  public File newFile(@Nullable String prefix, @Nullable String suffix) {
+    try {
+      return junit.newFile(StringUtils.defaultString(prefix) + "-" + StringUtils.defaultString(suffix));
+    } catch (IOException e) {
+      throw new IllegalStateException("Fail to create temp file", e);
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/ScannerUtils.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/ScannerUtils.java
new file mode 100644 (file)
index 0000000..f23bfba
--- /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.impl.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+
+public class ScannerUtils {
+
+  private ScannerUtils() {
+  }
+
+  /**
+   * Clean provided string to remove chars that are not valid as file name.
+   *
+   * @param projectKey e.g. my:file
+   */
+  public static String cleanKeyForFilename(String projectKey) {
+    String cleanKey = StringUtils.deleteWhitespace(projectKey);
+    return StringUtils.replace(cleanKey, ":", "_");
+  }
+
+  public static String encodeForUrl(@Nullable String url) {
+    try {
+      return URLEncoder.encode(url == null ? "" : url, StandardCharsets.UTF_8.name());
+
+    } catch (UnsupportedEncodingException e) {
+      throw new IllegalStateException("Encoding not supported", e);
+    }
+  }
+
+  public static String describe(Object o) {
+    try {
+      if (o.getClass().getMethod("toString").getDeclaringClass() != Object.class) {
+        String str = o.toString();
+        if (str != null) {
+          return str;
+        }
+      }
+    } catch (Exception e) {
+      // fallback
+    }
+
+    return o.getClass().getName();
+  }
+
+  public static String pluralize(String str, int i) {
+    if (i == 1) {
+      return str;
+    }
+    return str + "s";
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/TestSystem2.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/TestSystem2.java
new file mode 100644 (file)
index 0000000..b1005d5
--- /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.impl.utils;
+
+import java.util.TimeZone;
+import org.sonar.api.utils.System2;
+
+public class TestSystem2 extends System2 {
+
+  private long now = 0L;
+  private TimeZone defaultTimeZone = getDefaultTimeZone();
+
+  public TestSystem2 setNow(long l) {
+    this.now = l;
+    return this;
+  }
+
+  @Override
+  public long now() {
+    if (now <= 0L) {
+      throw new IllegalStateException("Method setNow() was not called by test");
+    }
+    return now;
+  }
+
+  public TestSystem2 setDefaultTimeZone(TimeZone defaultTimeZone) {
+    this.defaultTimeZone = defaultTimeZone;
+    return this;
+  }
+
+  @Override
+  public TimeZone getDefaultTimeZone() {
+    return defaultTimeZone;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/WorkDuration.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/WorkDuration.java
new file mode 100644 (file)
index 0000000..20349ba
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * 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.utils;
+
+import java.io.Serializable;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+/**
+ * @since 4.2
+ */
+public class WorkDuration implements Serializable {
+
+  static final int DAY_POSITION_IN_LONG = 10_000;
+  static final int HOUR_POSITION_IN_LONG = 100;
+  static final int MINUTE_POSITION_IN_LONG = 1;
+
+  public enum UNIT {
+    DAYS, HOURS, MINUTES
+  }
+
+  private int hoursInDay;
+
+  private long durationInMinutes;
+  private int days;
+  private int hours;
+  private int minutes;
+
+  private WorkDuration(long durationInMinutes, int days, int hours, int minutes, int hoursInDay) {
+    this.durationInMinutes = durationInMinutes;
+    this.days = days;
+    this.hours = hours;
+    this.minutes = minutes;
+    this.hoursInDay = hoursInDay;
+  }
+
+  public static WorkDuration create(int days, int hours, int minutes, int hoursInDay) {
+    long durationInSeconds = 60L * days * hoursInDay;
+    durationInSeconds += 60L * hours;
+    durationInSeconds += minutes;
+    return new WorkDuration(durationInSeconds, days, hours, minutes, hoursInDay);
+  }
+
+  public static WorkDuration createFromValueAndUnit(int value, UNIT unit, int hoursInDay) {
+    switch (unit) {
+      case DAYS:
+        return create(value, 0, 0, hoursInDay);
+      case HOURS:
+        return create(0, value, 0, hoursInDay);
+      case MINUTES:
+        return create(0, 0, value, hoursInDay);
+      default:
+        throw new IllegalStateException("Cannot create work duration");
+    }
+  }
+
+  static WorkDuration createFromLong(long duration, int hoursInDay) {
+    int days = 0;
+    int hours = 0;
+    int minutes = 0;
+
+    long time = duration;
+    Long currentTime = time / WorkDuration.DAY_POSITION_IN_LONG;
+    if (currentTime > 0) {
+      days = currentTime.intValue();
+      time = time - (currentTime * WorkDuration.DAY_POSITION_IN_LONG);
+    }
+
+    currentTime = time / WorkDuration.HOUR_POSITION_IN_LONG;
+    if (currentTime > 0) {
+      hours = currentTime.intValue();
+      time = time - (currentTime * WorkDuration.HOUR_POSITION_IN_LONG);
+    }
+
+    currentTime = time / WorkDuration.MINUTE_POSITION_IN_LONG;
+    if (currentTime > 0) {
+      minutes = currentTime.intValue();
+    }
+    return WorkDuration.create(days, hours, minutes, hoursInDay);
+  }
+
+  static WorkDuration createFromMinutes(long duration, int hoursInDay) {
+    int days = (int)(duration / (double)hoursInDay / 60.0);
+    Long currentDurationInMinutes = duration - (60L * days * hoursInDay);
+    int hours = (int)(currentDurationInMinutes / 60.0);
+    currentDurationInMinutes = currentDurationInMinutes - (60L * hours);
+    return new WorkDuration(duration, days, hours, currentDurationInMinutes.intValue(), hoursInDay);
+  }
+
+  /**
+   * Return the duration in number of working days.
+   * For instance, 3 days and 4 hours will return 3.5 days (if hoursIndDay is 8).
+   */
+  public double toWorkingDays() {
+    return durationInMinutes / 60d / hoursInDay;
+  }
+
+  /**
+   * Return the duration using the following format DDHHMM, where DD is the number of days, HH is the number of months, and MM the number of minutes.
+   * For instance, 3 days and 4 hours will return 030400 (if hoursIndDay is 8).
+   */
+  public long toLong() {
+    int workingDays = days;
+    int workingHours = hours;
+    if (hours >= hoursInDay) {
+      int nbAdditionalDays = hours / hoursInDay;
+      workingDays += nbAdditionalDays;
+      workingHours = hours - (nbAdditionalDays * hoursInDay);
+    }
+    return 1L * workingDays * DAY_POSITION_IN_LONG + workingHours * HOUR_POSITION_IN_LONG + minutes * MINUTE_POSITION_IN_LONG;
+  }
+
+  public long toMinutes() {
+    return durationInMinutes;
+  }
+
+  public WorkDuration add(@Nullable WorkDuration with) {
+    if (with != null) {
+      return WorkDuration.createFromMinutes(this.toMinutes() + with.toMinutes(), this.hoursInDay);
+    } else {
+      return this;
+    }
+  }
+
+  public WorkDuration subtract(@Nullable WorkDuration with) {
+    if (with != null) {
+      return WorkDuration.createFromMinutes(this.toMinutes() - with.toMinutes(), this.hoursInDay);
+    } else {
+      return this;
+    }
+  }
+
+  public WorkDuration multiply(int factor) {
+    return WorkDuration.createFromMinutes(this.toMinutes() * factor, this.hoursInDay);
+  }
+
+  public int days() {
+    return days;
+  }
+
+  public int hours() {
+    return hours;
+  }
+
+  public int minutes() {
+    return minutes;
+  }
+
+  int hoursInDay() {
+    return hoursInDay;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    WorkDuration that = (WorkDuration) o;
+    return durationInMinutes == that.durationInMinutes;
+
+  }
+
+  @Override
+  public int hashCode() {
+    return (int) (durationInMinutes ^ (durationInMinutes >>> 32));
+  }
+
+  @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/utils/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/package-info.java
new file mode 100644 (file)
index 0000000..335c370
--- /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.impl.utils;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/PartImpl.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/PartImpl.java
new file mode 100644 (file)
index 0000000..ed16126
--- /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.impl.ws;
+
+import java.io.InputStream;
+import org.sonar.api.server.ws.Request;
+
+public class PartImpl implements Request.Part {
+
+  private final InputStream inputStream;
+  private final String fileName;
+
+  public PartImpl(InputStream inputStream, String fileName) {
+    this.inputStream = inputStream;
+    this.fileName = fileName;
+  }
+
+  @Override
+  public InputStream getInputStream() {
+    return inputStream;
+  }
+
+  @Override
+  public String getFileName() {
+    return fileName;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/SimpleGetRequest.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/SimpleGetRequest.java
new file mode 100644 (file)
index 0000000..a113566
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * 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.ws;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.server.ws.LocalConnector;
+import org.sonar.api.server.ws.Request;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Fake implementation of {@link org.sonar.api.server.ws.Request} used
+ * for testing. Call the method {@link #setParam(String, String)} to
+ * emulate some parameter values.
+ */
+public class SimpleGetRequest extends Request {
+
+  private final Map<String, String[]> params = new HashMap<>();
+  private final Map<String, Part> parts = new HashMap<>();
+  private final Map<String, String> headers = new HashMap<>();
+  private String mediaType = "application/json";
+  private String path;
+
+  @Override
+  public String method() {
+    return "GET";
+  }
+
+  @Override
+  public String getMediaType() {
+    return mediaType;
+  }
+
+  public SimpleGetRequest setMediaType(String mediaType) {
+    requireNonNull(mediaType);
+    this.mediaType = mediaType;
+    return this;
+  }
+
+  @Override
+  public boolean hasParam(String key) {
+    return params.keySet().contains(key);
+  }
+
+  @Override
+  public String param(String key) {
+    String[] strings = params.get(key);
+    return strings == null || strings.length == 0 ? null : strings[0];
+  }
+
+  @Override
+  public List<String> multiParam(String key) {
+    String value = param(key);
+    return value == null ? emptyList() : singletonList(value);
+  }
+
+  @Override
+  @CheckForNull
+  public List<String> paramAsStrings(String key) {
+    String value = param(key);
+    if (value == null) {
+      return null;
+    }
+
+    return Arrays.stream(value.split(",")).map(String::trim).filter(x -> !x.isEmpty()).collect(Collectors.toList());
+  }
+
+  @Override
+  public InputStream paramAsInputStream(String key) {
+    return IOUtils.toInputStream(param(key), UTF_8);
+  }
+
+  public SimpleGetRequest setParam(String key, @Nullable String value) {
+    if (value != null) {
+      params.put(key, new String[] {value});
+    }
+    return this;
+  }
+
+  @Override
+  public Map<String, String[]> getParams() {
+    return params;
+  }
+
+  @Override
+  public Part paramAsPart(String key) {
+    return parts.get(key);
+  }
+
+  public SimpleGetRequest setPart(String key, InputStream input, String fileName) {
+    parts.put(key, new PartImpl(input, fileName));
+    return this;
+  }
+
+  @Override
+  public LocalConnector localConnector() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String getPath() {
+    return path;
+  }
+
+  public SimpleGetRequest setPath(String path) {
+    this.path = path;
+    return this;
+  }
+
+  @Override
+  public Optional<String> header(String name) {
+    return Optional.ofNullable(headers.get(name));
+  }
+
+  public SimpleGetRequest setHeader(String name, String value) {
+    headers.put(name, value);
+    return this;
+  }
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/ValidatingRequest.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/ValidatingRequest.java
new file mode 100644 (file)
index 0000000..6e7d90b
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * 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.ws;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.server.ws.LocalConnector;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+
+import static java.lang.String.format;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.lang.StringUtils.defaultString;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+
+/**
+ * @since 4.2
+ */
+public abstract class ValidatingRequest extends Request {
+
+  private static final String COMMA_SPLITTER = ",";
+  private WebService.Action action;
+  private LocalConnector localConnector;
+
+  public void setAction(WebService.Action action) {
+    this.action = action;
+  }
+
+  public WebService.Action action() {
+    return action;
+  }
+
+  @Override
+  public LocalConnector localConnector() {
+    requireNonNull(localConnector, "Local connector has not been set");
+    return localConnector;
+  }
+
+  public void setLocalConnector(LocalConnector lc) {
+    this.localConnector = lc;
+  }
+
+  @Override
+  @CheckForNull
+  public String param(String key) {
+    WebService.Param definition = action.param(key);
+    String rawValue = readParam(key, definition);
+    String rawValueOrDefault = defaultString(rawValue, definition.defaultValue());
+    String value = rawValueOrDefault == null ? null : trim(rawValueOrDefault);
+    validateRequiredValue(key, definition, rawValue);
+    if (value == null) {
+      return null;
+    }
+    validatePossibleValues(key, value, definition);
+    validateMaximumLength(key, definition, rawValueOrDefault);
+    validateMinimumLength(key, definition, rawValueOrDefault);
+    validateMaximumValue(key, definition, value);
+    return value;
+  }
+
+  @Override
+  public List<String> multiParam(String key) {
+    WebService.Param definition = action.param(key);
+    List<String> values = readMultiParamOrDefaultValue(key, definition);
+    return validateValues(values, definition);
+  }
+
+  private static String trim(String s) {
+    int begin;
+    for (begin = 0; begin < s.length(); begin++) {
+      if (!Character.isWhitespace(s.charAt(begin))) {
+        break;
+      }
+    }
+
+    int end;
+    for (end = s.length(); end > begin; end--) {
+      if (!Character.isWhitespace(s.charAt(end - 1))) {
+        break;
+      }
+    }
+    return s.substring(begin, end);
+  }
+
+  @Override
+  @CheckForNull
+  public InputStream paramAsInputStream(String key) {
+    return readInputStreamParam(key);
+  }
+
+  @Override
+  @CheckForNull
+  public Part paramAsPart(String key) {
+    return readPart(key);
+  }
+
+  @CheckForNull
+  @Override
+  public List<String> paramAsStrings(String key) {
+    WebService.Param definition = action.param(key);
+    String value = defaultString(readParam(key, definition), definition.defaultValue());
+    if (value == null) {
+      return null;
+    }
+    List<String> values = Arrays.stream(value.split(COMMA_SPLITTER))
+      .map(String::trim)
+      .filter(s -> !s.isEmpty())
+      .collect(Collectors.toList());
+    return validateValues(values, definition);
+  }
+
+  @CheckForNull
+  @Override
+  public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) {
+    List<String> values = paramAsStrings(key);
+    if (values == null) {
+      return null;
+    }
+    return values.stream()
+      .filter(s -> !s.isEmpty())
+      .map(value -> Enum.valueOf(enumClass, value))
+      .collect(Collectors.toList());
+  }
+
+  @CheckForNull
+  private String readParam(String key, @Nullable WebService.Param definition) {
+    checkArgument(definition != null, "BUG - parameter '%s' is undefined for action '%s'", key, action.key());
+    String deprecatedKey = definition.deprecatedKey();
+    return deprecatedKey != null ? defaultString(readParam(deprecatedKey), readParam(key)) : readParam(key);
+  }
+
+  private List<String> readMultiParamOrDefaultValue(String key, @Nullable WebService.Param definition) {
+    checkArgument(definition != null, "BUG - parameter '%s' is undefined for action '%s'", key, action.key());
+
+    List<String> keyValues = readMultiParam(key);
+    if (!keyValues.isEmpty()) {
+      return keyValues;
+    }
+
+    String deprecatedKey = definition.deprecatedKey();
+    List<String> deprecatedKeyValues = deprecatedKey == null ? emptyList() : readMultiParam(deprecatedKey);
+    if (!deprecatedKeyValues.isEmpty()) {
+      return deprecatedKeyValues;
+    }
+
+    String defaultValue = definition.defaultValue();
+    return defaultValue == null ? emptyList() : singletonList(defaultValue);
+  }
+
+  @CheckForNull
+  protected abstract String readParam(String key);
+
+  protected abstract List<String> readMultiParam(String key);
+
+  @CheckForNull
+  protected abstract InputStream readInputStreamParam(String key);
+
+  @CheckForNull
+  protected abstract Part readPart(String key);
+
+  private static List<String> validateValues(List<String> values, WebService.Param definition) {
+    Integer maximumValues = definition.maxValuesAllowed();
+    checkArgument(maximumValues == null || values.size() <= maximumValues, "'%s' can contains only %s values, got %s", definition.key(), maximumValues, values.size());
+    values.forEach(value -> validatePossibleValues(definition.key(), value, definition));
+    return values;
+  }
+
+  private static void validatePossibleValues(String key, String value, WebService.Param definition) {
+    Set<String> possibleValues = definition.possibleValues();
+    if (possibleValues == null) {
+      return;
+    }
+    checkArgument(possibleValues.contains(value), "Value of parameter '%s' (%s) must be one of: %s", key, value, possibleValues);
+  }
+
+  private static void validateMaximumLength(String key, WebService.Param definition, String valueOrDefault) {
+    Integer maximumLength = definition.maximumLength();
+    if (maximumLength == null) {
+      return;
+    }
+    int valueLength = valueOrDefault.length();
+    checkArgument(valueLength <= maximumLength, "'%s' length (%s) is longer than the maximum authorized (%s)", key, valueLength, maximumLength);
+  }
+
+  private static void validateMinimumLength(String key, WebService.Param definition, String valueOrDefault) {
+    Integer minimumLength = definition.minimumLength();
+    if (minimumLength == null) {
+      return;
+    }
+    int valueLength = valueOrDefault.length();
+    checkArgument(valueLength >= minimumLength, "'%s' length (%s) is shorter than the minimum authorized (%s)", key, valueLength, minimumLength);
+  }
+
+  private static void validateMaximumValue(String key, WebService.Param definition, String value) {
+    Integer maximumValue = definition.maximumValue();
+    if (maximumValue == null) {
+      return;
+    }
+    int valueAsInt = validateAsNumeric(key, value);
+    checkArgument(valueAsInt <= maximumValue, "'%s' value (%s) must be less than %s", key, valueAsInt, maximumValue);
+  }
+
+  private static void validateRequiredValue(String key, WebService.Param definition, String value) {
+    boolean required = definition.isRequired();
+    if (required) {
+      checkArgument(value != null, format(MSG_PARAMETER_MISSING, key));
+    }
+  }
+
+  private static int validateAsNumeric(String key, String value) {
+    try {
+      return Integer.parseInt(value);
+    } catch (NumberFormatException exception) {
+      throw new IllegalArgumentException(format("'%s' value '%s' cannot be parsed as an integer", key, value), exception);
+    }
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/package-info.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/ws/package-info.java
new file mode 100644 (file)
index 0000000..306c7a7
--- /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.impl.ws;
+
+import javax.annotation.ParametersAreNonnullByDefault;
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
new file mode 100644 (file)
index 0000000..922d767
--- /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.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
new file mode 100644 (file)
index 0000000..63e3c44
--- /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.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
new file mode 100644 (file)
index 0000000..e6106a3
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..617dbaf
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..552387c
--- /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.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
new file mode 100644 (file)
index 0000000..263032b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..7e22203
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..ac1a2c4
--- /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.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
new file mode 100644 (file)
index 0000000..bd3f493
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..0f3f1d5
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..49ecf89
--- /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.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
new file mode 100644 (file)
index 0000000..c214469
--- /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.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
new file mode 100644 (file)
index 0000000..4fb37a2
--- /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.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
new file mode 100644 (file)
index 0000000..50c37d8
--- /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.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
new file mode 100644 (file)
index 0000000..e02d5e4
--- /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.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
new file mode 100644 (file)
index 0000000..6d9cd4e
--- /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.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
new file mode 100644 (file)
index 0000000..0f60f6b
--- /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.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
new file mode 100644 (file)
index 0000000..052ff51
--- /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.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
new file mode 100644 (file)
index 0000000..489d636
--- /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.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
new file mode 100644 (file)
index 0000000..e7e2efd
--- /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.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
new file mode 100644 (file)
index 0000000..c555516
--- /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.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
new file mode 100644 (file)
index 0000000..1330f90
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..fd766c2
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..9f6be9d
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..fd2c60d
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..06ff406
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..99beb98
--- /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.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
new file mode 100644 (file)
index 0000000..540a0bb
--- /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.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
new file mode 100644 (file)
index 0000000..f88a099
--- /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.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
new file mode 100644 (file)
index 0000000..0c7ece2
--- /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.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
new file mode 100644 (file)
index 0000000..b09b5ed
--- /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.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
new file mode 100644 (file)
index 0000000..f6d7f45
--- /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.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
new file mode 100644 (file)
index 0000000..affd87b
--- /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.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
new file mode 100644 (file)
index 0000000..25b44f5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..9684c7c
--- /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.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/impl/server/DefaultNewRuleTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/server/DefaultNewRuleTest.java
new file mode 100644 (file)
index 0000000..361785b
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleScope;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.server.rule.RulesDefinition;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultNewRuleTest {
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
+  private DefaultNewRule rule = new DefaultNewRule("plugin", "repo", "key");
+
+  @Test
+  public void testSimpleSetGet() {
+    assertThat(rule.pluginKey()).isEqualTo("plugin");
+    assertThat(rule.repoKey()).isEqualTo("repo");
+    assertThat(rule.key()).isEqualTo("key");
+
+    rule.setScope(RuleScope.MAIN);
+    assertThat(rule.scope()).isEqualTo(RuleScope.MAIN);
+
+    rule.setName("   name  ");
+    assertThat(rule.name()).isEqualTo("name");
+
+    rule.setHtmlDescription("   html  ");
+    assertThat(rule.htmlDescription()).isEqualTo("html");
+
+    rule.setTemplate(true);
+    assertThat(rule.template()).isTrue();
+
+    rule.setActivatedByDefault(true);
+    assertThat(rule.activatedByDefault()).isTrue();
+
+    RulesDefinition.NewParam param1 = rule.createParam("param1");
+    assertThat(rule.param("param1")).isEqualTo(param1);
+    assertThat(rule.params()).containsOnly(param1);
+
+    rule.setTags("tag1", "tag2");
+    rule.addTags("tag3");
+    assertThat(rule.tags()).containsExactly("tag1", "tag2", "tag3");
+
+    rule.setEffortToFixDescription("effort");
+    assertThat(rule.gapDescription()).isEqualTo("effort");
+
+    rule.setGapDescription("gap");
+    assertThat(rule.gapDescription()).isEqualTo("gap");
+
+    rule.setInternalKey("internal");
+    assertThat(rule.internalKey()).isEqualTo("internal");
+
+    rule.addDeprecatedRuleKey("deprecatedrepo", "deprecatedkey");
+    assertThat(rule.deprecatedRuleKeys()).containsOnly(RuleKey.of("deprecatedrepo", "deprecatedkey"));
+  }
+
+  @Test
+  public void fail_if_severity_is_invalid() {
+    exception.expect(IllegalArgumentException.class);
+    rule.setSeverity("invalid");
+  }
+
+  @Test
+  public void fail_setting_markdown_if_html_is_set() {
+    exception.expect(IllegalStateException.class);
+    rule.setHtmlDescription("html");
+    rule.setMarkdownDescription("markdown");
+  }
+
+  @Test
+  public void fail_if_set_status_to_removed() {
+    exception.expect(IllegalArgumentException.class);
+    rule.setStatus(RuleStatus.REMOVED);
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/AlwaysIncreasingSystem2Test.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/AlwaysIncreasingSystem2Test.java
new file mode 100644 (file)
index 0000000..30953e6
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.utils;
+
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AlwaysIncreasingSystem2Test {
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void default_constructor_makes_now_start_with_random_number_and_increase_returned_value_by_100_with_each_call() {
+    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2();
+    verifyValuesReturnedByNow(underTest, null, 100);
+  }
+
+  @Test
+  public void constructor_with_increment_makes_now_start_with_random_number_and_increase_returned_value_by_specified_value_with_each_call() {
+    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2(663);
+
+    verifyValuesReturnedByNow(underTest, null, 663);
+  }
+
+  @Test
+  public void constructor_with_initial_value_and_increment_makes_now_start_with_specified_value_and_increase_returned_value_by_specified_value_with_each_call() {
+    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2(777777L, 96);
+
+    verifyValuesReturnedByNow(underTest, 777777L, 96);
+  }
+
+  @Test
+  public void constructor_with_initial_value_and_increment_throws_IAE_if_initial_value_is_less_than_0() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Initial value must be >= 0");
+    
+    new AlwaysIncreasingSystem2(-1, 100);
+  }
+
+  @Test
+  public void constructor_with_initial_value_and_increment_accepts_initial_value_0() {
+    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2(0, 100);
+
+    verifyValuesReturnedByNow(underTest, 0L, 100);
+  }
+
+  @Test
+  public void constructor_with_initial_value_and_increment_throws_IAE_if_increment_is_0() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("increment must be > 0");
+
+    new AlwaysIncreasingSystem2(10, 0);
+  }
+
+  @Test
+  public void constructor_with_initial_value_and_increment_throws_IAE_if_increment_is_less_than_0() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("increment must be > 0");
+
+    new AlwaysIncreasingSystem2(10, -66);
+  }
+
+  @Test
+  public void constructor_with_increment_throws_IAE_if_increment_is_0() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("increment must be > 0");
+
+    new AlwaysIncreasingSystem2(0);
+  }
+
+  @Test
+  public void constructor_with_increment_throws_IAE_if_increment_is_less_than_0() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("increment must be > 0");
+
+    new AlwaysIncreasingSystem2(-20);
+  }
+
+  private void verifyValuesReturnedByNow(AlwaysIncreasingSystem2 underTest, @Nullable Long initialValue, int increment) {
+    long previousValue = -1;
+    for (int i = 0; i < 333; i++) {
+      if (previousValue == -1) {
+        long now = underTest.now();
+        if (initialValue != null) {
+          assertThat(now).isEqualTo(initialValue);
+        } else {
+          assertThat(now).isGreaterThan(0);
+        }
+        previousValue = now;
+      } else {
+        long now = underTest.now();
+        assertThat(now).isEqualTo(previousValue + increment);
+        previousValue = now;
+      }
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/DefaultTempFolderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/DefaultTempFolderTest.java
new file mode 100644 (file)
index 0000000..b21d207
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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.utils;
+
+import java.io.File;
+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 org.sonar.server.util.TempFolderCleaner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DefaultTempFolderTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public LogTester logTester = new LogTester();
+
+  @Test
+  public void createTempFolderAndFile() throws Exception {
+    File rootTempFolder = temp.newFolder();
+    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
+    File dir = underTest.newDir();
+    assertThat(dir).exists().isDirectory();
+    File file = underTest.newFile();
+    assertThat(file).exists().isFile();
+
+    new TempFolderCleaner(underTest).stop();
+    assertThat(rootTempFolder).doesNotExist();
+  }
+
+  @Test
+  public void createTempFolderWithName() throws Exception {
+    File rootTempFolder = temp.newFolder();
+    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
+    File dir = underTest.newDir("sample");
+    assertThat(dir).exists().isDirectory();
+    assertThat(new File(rootTempFolder, "sample")).isEqualTo(dir);
+
+    new TempFolderCleaner(underTest).stop();
+    assertThat(rootTempFolder).doesNotExist();
+  }
+
+  @Test
+  public void newDir_throws_ISE_if_name_is_not_valid() throws Exception {
+    File rootTempFolder = temp.newFolder();
+    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
+    String tooLong = "tooooolong";
+    for (int i = 0; i < 50; i++) {
+      tooLong += "tooooolong";
+    }
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Failed to create temp directory");
+
+    underTest.newDir(tooLong);
+  }
+
+  @Test
+  public void newFile_throws_ISE_if_name_is_not_valid() throws Exception {
+    File rootTempFolder = temp.newFolder();
+    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
+    String tooLong = "tooooolong";
+    for (int i = 0; i < 50; i++) {
+      tooLong += "tooooolong";
+    }
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Failed to create temp file");
+
+    underTest.newFile(tooLong, ".txt");
+  }
+
+  @Test
+  public void clean_deletes_non_empty_directory() throws Exception {
+    File dir = temp.newFolder();
+    FileUtils.touch(new File(dir, "foo.txt"));
+
+    DefaultTempFolder underTest = new DefaultTempFolder(dir);
+    underTest.clean();
+
+    assertThat(dir).doesNotExist();
+  }
+
+  @Test
+  public void clean_does_not_fail_if_directory_has_already_been_deleted() throws Exception {
+    File dir = temp.newFolder();
+
+    DefaultTempFolder underTest = new DefaultTempFolder(dir);
+    underTest.clean();
+    assertThat(dir).doesNotExist();
+
+    // second call does not fail, nor log ERROR logs
+    underTest.clean();
+
+    assertThat(logTester.logs(LoggerLevel.ERROR)).isEmpty();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/JUnitTempFolderTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/JUnitTempFolderTest.java
new file mode 100644 (file)
index 0000000..5b765c3
--- /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.impl.utils;
+
+import org.junit.Test;
+
+import java.io.File;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JUnitTempFolderTest {
+
+  @Test
+  public void apply() throws Throwable {
+    JUnitTempFolder temp = new JUnitTempFolder();
+    temp.before();
+    File dir1 = temp.newDir();
+    assertThat(dir1).isDirectory().exists();
+
+    File dir2 = temp.newDir("foo");
+    assertThat(dir2).isDirectory().exists();
+
+    File file1 = temp.newFile();
+    assertThat(file1).isFile().exists();
+
+    File file2 = temp.newFile("foo", "txt");
+    assertThat(file2).isFile().exists();
+
+    temp.after();
+    assertThat(dir1).doesNotExist();
+    assertThat(dir2).doesNotExist();
+    assertThat(file1).doesNotExist();
+    assertThat(file2).doesNotExist();
+  }
+
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/ScannerUtilsTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/ScannerUtilsTest.java
new file mode 100644 (file)
index 0000000..0390d1f
--- /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.impl.utils;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ScannerUtilsTest {
+  @Test
+  public void test_pluralize() {
+    assertThat(ScannerUtils.pluralize("string", 0)).isEqualTo("strings");
+    assertThat(ScannerUtils.pluralize("string", 1)).isEqualTo("string");
+    assertThat(ScannerUtils.pluralize("string", 2)).isEqualTo("strings");
+  }
+
+  @Test
+  public void cleanKeyForFilename() {
+    assertThat(ScannerUtils.cleanKeyForFilename("project 1")).isEqualTo("project1");
+    assertThat(ScannerUtils.cleanKeyForFilename("project:1")).isEqualTo("project_1");
+  }
+
+  @Test
+  public void describe() {
+    assertThat(ScannerUtils.describe(new Object())).isEqualTo("java.lang.Object");
+    assertThat(ScannerUtils.describe(new TestClass())).isEqualTo("overridden");
+  }
+
+  class TestClass {
+    @Override
+    public String toString() {
+      return "overridden";
+    }
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/WorkDurationTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/utils/WorkDurationTest.java
new file mode 100644 (file)
index 0000000..3c1e2f9
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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.utils;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class WorkDurationTest {
+
+  static final int HOURS_IN_DAY = 8;
+
+  static final Long ONE_MINUTE = 1L;
+  static final Long ONE_HOUR_IN_MINUTES = ONE_MINUTE * 60;
+  static final Long ONE_DAY_IN_MINUTES = ONE_HOUR_IN_MINUTES * HOURS_IN_DAY;
+
+  @Test
+  public void create_from_days_hours_minutes() {
+    WorkDuration workDuration = WorkDuration.create(1, 1, 1, HOURS_IN_DAY);
+    assertThat(workDuration.days()).isEqualTo(1);
+    assertThat(workDuration.hours()).isEqualTo(1);
+    assertThat(workDuration.minutes()).isEqualTo(1);
+    assertThat(workDuration.toMinutes()).isEqualTo(ONE_DAY_IN_MINUTES + ONE_HOUR_IN_MINUTES + ONE_MINUTE);
+    assertThat(workDuration.hoursInDay()).isEqualTo(HOURS_IN_DAY);
+  }
+
+  @Test
+  public void create_from_value_and_unit() {
+    WorkDuration result = WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.DAYS, HOURS_IN_DAY);
+    assertThat(result.days()).isEqualTo(1);
+    assertThat(result.hours()).isEqualTo(0);
+    assertThat(result.minutes()).isEqualTo(0);
+    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
+    assertThat(result.toMinutes()).isEqualTo(ONE_DAY_IN_MINUTES);
+
+    assertThat(WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toMinutes()).isEqualTo(ONE_DAY_IN_MINUTES);
+    assertThat(WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toMinutes()).isEqualTo(ONE_HOUR_IN_MINUTES);
+    assertThat(WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toMinutes()).isEqualTo(ONE_MINUTE);
+  }
+
+  @Test
+  public void create_from_minutes() {
+    WorkDuration workDuration = WorkDuration.createFromMinutes(ONE_MINUTE, HOURS_IN_DAY);
+    assertThat(workDuration.days()).isEqualTo(0);
+    assertThat(workDuration.hours()).isEqualTo(0);
+    assertThat(workDuration.minutes()).isEqualTo(1);
+
+    workDuration = WorkDuration.createFromMinutes(ONE_HOUR_IN_MINUTES, HOURS_IN_DAY);
+    assertThat(workDuration.days()).isEqualTo(0);
+    assertThat(workDuration.hours()).isEqualTo(1);
+    assertThat(workDuration.minutes()).isEqualTo(0);
+
+    workDuration = WorkDuration.createFromMinutes(ONE_DAY_IN_MINUTES, HOURS_IN_DAY);
+    assertThat(workDuration.days()).isEqualTo(1);
+    assertThat(workDuration.hours()).isEqualTo(0);
+    assertThat(workDuration.minutes()).isEqualTo(0);
+  }
+
+  @Test
+  public void create_from_working_long() {
+    // 1 minute
+    WorkDuration workDuration = WorkDuration.createFromLong(1L, HOURS_IN_DAY);
+    assertThat(workDuration.days()).isEqualTo(0);
+    assertThat(workDuration.hours()).isEqualTo(0);
+    assertThat(workDuration.minutes()).isEqualTo(1);
+
+    // 1 hour
+    workDuration = WorkDuration.createFromLong(100L, HOURS_IN_DAY);
+    assertThat(workDuration.days()).isEqualTo(0);
+    assertThat(workDuration.hours()).isEqualTo(1);
+    assertThat(workDuration.minutes()).isEqualTo(0);
+
+    // 1 day
+    workDuration = WorkDuration.createFromLong(10000L, HOURS_IN_DAY);
+    assertThat(workDuration.days()).isEqualTo(1);
+    assertThat(workDuration.hours()).isEqualTo(0);
+    assertThat(workDuration.minutes()).isEqualTo(0);
+  }
+
+  @Test
+  public void convert_to_seconds() {
+    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toMinutes()).isEqualTo(2L * ONE_MINUTE);
+    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toMinutes()).isEqualTo(2L * ONE_HOUR_IN_MINUTES);
+    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toMinutes()).isEqualTo(2L * ONE_DAY_IN_MINUTES);
+  }
+
+  @Test
+  public void convert_to_working_days() {
+    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toWorkingDays()).isEqualTo(2d / 60d / 8d);
+    assertThat(WorkDuration.createFromValueAndUnit(240, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toWorkingDays()).isEqualTo(0.5);
+    assertThat(WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(0.5);
+    assertThat(WorkDuration.createFromValueAndUnit(8, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(1d);
+    assertThat(WorkDuration.createFromValueAndUnit(16, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(2d);
+    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(2d);
+  }
+
+  @Test
+  public void convert_to_working_long() {
+    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toLong()).isEqualTo(2l);
+    assertThat(WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toLong()).isEqualTo(400l);
+    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toLong()).isEqualTo(10200l);
+    assertThat(WorkDuration.createFromValueAndUnit(8, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toLong()).isEqualTo(10000l);
+    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toLong()).isEqualTo(20000l);
+  }
+
+  @Test
+  public void add() {
+    // 4h + 5h = 1d 1h
+    WorkDuration result = WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).add(WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.HOURS, HOURS_IN_DAY));
+    assertThat(result.days()).isEqualTo(1);
+    assertThat(result.hours()).isEqualTo(1);
+    assertThat(result.minutes()).isEqualTo(0);
+    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
+
+    // 40 m + 30m = 1h 10m
+    result = WorkDuration.createFromValueAndUnit(40, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).add(WorkDuration.createFromValueAndUnit(30, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY));
+    assertThat(result.days()).isEqualTo(0);
+    assertThat(result.hours()).isEqualTo(1);
+    assertThat(result.minutes()).isEqualTo(10);
+    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
+
+    // 10 m + 20m = 30m
+    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).add(
+      WorkDuration.createFromValueAndUnit(20, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY)
+    ).minutes()).isEqualTo(30);
+
+    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).add(null).minutes()).isEqualTo(10);
+  }
+
+  @Test
+  public void subtract() {
+    // 1d 1h - 5h = 4h
+    WorkDuration result = WorkDuration.create(1, 1, 0, HOURS_IN_DAY).subtract(WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.HOURS, HOURS_IN_DAY));
+    assertThat(result.days()).isEqualTo(0);
+    assertThat(result.hours()).isEqualTo(4);
+    assertThat(result.minutes()).isEqualTo(0);
+    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
+
+    // 1h 10m - 30m = 40m
+    result = WorkDuration.create(0, 1, 10, HOURS_IN_DAY).subtract(WorkDuration.createFromValueAndUnit(30, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY));
+    assertThat(result.days()).isEqualTo(0);
+    assertThat(result.hours()).isEqualTo(0);
+    assertThat(result.minutes()).isEqualTo(40);
+    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
+
+    // 30m - 20m = 10m
+    assertThat(WorkDuration.createFromValueAndUnit(30, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).subtract(WorkDuration.createFromValueAndUnit(20, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY))
+      .minutes()).isEqualTo(10);
+
+    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).subtract(null).minutes()).isEqualTo(10);
+  }
+
+  @Test
+  public void multiply() {
+    // 5h * 2 = 1d 2h
+    WorkDuration result = WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).multiply(2);
+    assertThat(result.days()).isEqualTo(1);
+    assertThat(result.hours()).isEqualTo(2);
+    assertThat(result.minutes()).isEqualTo(0);
+    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
+  }
+
+  @Test
+  public void test_equals_and_hashcode() throws Exception {
+    WorkDuration duration = WorkDuration.createFromLong(28800, HOURS_IN_DAY);
+    WorkDuration durationWithSameValue = WorkDuration.createFromLong(28800, HOURS_IN_DAY);
+    WorkDuration durationWithDifferentValue = WorkDuration.createFromLong(14400, HOURS_IN_DAY);
+
+    assertThat(duration).isEqualTo(duration);
+    assertThat(durationWithSameValue).isEqualTo(duration);
+    assertThat(durationWithDifferentValue).isNotEqualTo(duration);
+    assertThat(duration).isNotEqualTo(null);
+
+    assertThat(duration.hashCode()).isEqualTo(duration.hashCode());
+    assertThat(durationWithSameValue.hashCode()).isEqualTo(duration.hashCode());
+    assertThat(durationWithDifferentValue.hashCode()).isNotEqualTo(duration.hashCode());
+  }
+
+  @Test
+  public void test_toString() throws Exception {
+    assertThat(WorkDuration.createFromLong(28800, HOURS_IN_DAY).toString()).isNotNull();
+  }
+}
diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/ws/SimpleGetRequestTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/impl/ws/SimpleGetRequestTest.java
new file mode 100644 (file)
index 0000000..fb20cf2
--- /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.impl.ws;
+
+import java.io.InputStream;
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+import static org.mockito.Mockito.mock;
+
+public class SimpleGetRequestTest {
+
+  org.sonar.api.impl.ws.SimpleGetRequest underTest = new SimpleGetRequest();
+
+  @Test
+  public void method() {
+    assertThat(underTest.method()).isEqualTo("GET");
+
+    underTest.setParam("foo", "bar");
+    assertThat(underTest.param("foo")).isEqualTo("bar");
+    assertThat(underTest.param("unknown")).isNull();
+  }
+
+  @Test
+  public void has_param() {
+    assertThat(underTest.method()).isEqualTo("GET");
+
+    underTest.setParam("foo", "bar");
+    assertThat(underTest.hasParam("foo")).isTrue();
+    assertThat(underTest.hasParam("unknown")).isFalse();
+  }
+
+  @Test
+  public void get_part() {
+    InputStream inputStream = mock(InputStream.class);
+    underTest.setPart("key", inputStream, "filename");
+
+    Request.Part part = underTest.paramAsPart("key");
+    assertThat(part.getInputStream()).isEqualTo(inputStream);
+    assertThat(part.getFileName()).isEqualTo("filename");
+
+    assertThat(underTest.paramAsPart("unknown")).isNull();
+  }
+
+  @Test
+  public void getMediaType() {
+    underTest.setMediaType("JSON");
+
+    assertThat(underTest.getMediaType()).isEqualTo("JSON");
+  }
+
+  @Test
+  public void multiParam_with_one_element() {
+    underTest.setParam("foo", "bar");
+
+    assertThat(underTest.multiParam("foo")).containsExactly("bar");
+  }
+
+  @Test
+  public void multiParam_without_any_element() {
+    assertThat(underTest.multiParam("42")).isEmpty();
+  }
+
+  @Test
+  public void getParams() {
+    underTest
+      .setParam("foo", "bar")
+      .setParam("fee", "beer");
+
+    assertThat(underTest.getParams()).containsOnly(
+      entry("foo", new String[] {"bar"}),
+      entry("fee", new String[] {"beer"}));
+  }
+
+  @Test
+  public void header_returns_empty_if_header_is_not_present() {
+    assertThat(underTest.header("foo")).isEmpty();
+  }
+
+  @Test
+  public void header_returns_value_of_header_if_present() {
+    underTest.setHeader("foo", "bar");
+    assertThat(underTest.header("foo")).hasValue("bar");
+  }
+
+  @Test
+  public void header_returns_empty_string_value_if_header_is_present_without_value() {
+    underTest.setHeader("foo", "");
+    assertThat(underTest.header("foo")).hasValue("");
+  }
+}
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
new file mode 100644 (file)
index 0000000..2cc3e48
Binary files /dev/null and b/sonar-plugin-api-impl/src/test/resources/org/sonar/api/impl/fs/glyphicons-halflings-regular.woff differ
index 109d187e80b8b0af566b386f52c262590b7e8799..53160ac2c78d1f700e0e5e5c1e116b86cb9d9eb1 100644 (file)
@@ -33,8 +33,7 @@ dependencies {
   testCompile 'com.tngtech.java:junit-dataprovider'
   testCompile 'org.assertj:assertj-core'
   testCompile 'org.mockito:mockito-core'
-  testCompile project(':sonar-scanner-engine')
-  testCompile project(':server:sonar-server')
+  testCompile project(':sonar-plugin-api-impl')
 
 }
 
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java
deleted file mode 100644 (file)
index 50c0d75..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.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/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
deleted file mode 100644 (file)
index 41287d4..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.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/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java
deleted file mode 100644 (file)
index adde738..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.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/src/main/java/org/sonar/api/batch/fs/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
deleted file mode 100644 (file)
index 4af8d77..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.batch.fs.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java
new file mode 100644 (file)
index 0000000..fa22fb4
--- /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.rule;
+
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.rule.RuleKey;
+
+public class LoadedActiveRule {
+  private RuleKey ruleKey;
+  private String severity;
+  private String name;
+  private String language;
+  private Map<String, String> params;
+  private long createdAt;
+  private long updatedAt;
+  private String templateRuleKey;
+  private String internalKey;
+
+  public RuleKey getRuleKey() {
+    return ruleKey;
+  }
+
+  public void setRuleKey(RuleKey ruleKey) {
+    this.ruleKey = ruleKey;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getSeverity() {
+    return severity;
+  }
+
+  public void setSeverity(String severity) {
+    this.severity = severity;
+  }
+
+  public String getLanguage() {
+    return language;
+  }
+
+  public void setLanguage(String language) {
+    this.language = language;
+  }
+
+  public Map<String, String> getParams() {
+    return params;
+  }
+
+  public void setParams(Map<String, String> params) {
+    this.params = params;
+  }
+
+  public long getCreatedAt() {
+    return createdAt;
+  }
+
+  public void setCreatedAt(long createdAt) {
+    this.createdAt = createdAt;
+  }
+
+  public long getUpdatedAt() {
+    return updatedAt;
+  }
+
+  public void setUpdatedAt(long updatedAt) {
+    this.updatedAt = updatedAt;
+  }
+
+  @CheckForNull
+  public String getTemplateRuleKey() {
+    return templateRuleKey;
+  }
+
+  public void setTemplateRuleKey(@Nullable String templateRuleKey) {
+    this.templateRuleKey = templateRuleKey;
+  }
+
+  public String getInternalKey() {
+    return internalKey;
+  }
+
+  public void setInternalKey(String internalKey) {
+    this.internalKey = internalKey;
+  }
+
+}
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
new file mode 100644 (file)
index 0000000..6f14a13
--- /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;
+
+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
new file mode 100644 (file)
index 0000000..edcf70f
--- /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;
+
+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
new file mode 100644 (file)
index 0000000..f06830d
--- /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;
+
+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 2a1ee512bc0e7a82a989aa833f63a5e74b4d634c..3afb8c8608ed62aacb6247e3cc6c7fe9e62621b2 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.api.config;
 import java.util.Optional;
 import org.sonar.api.scanner.ScannerSide;
 import org.sonar.api.ce.ComputeEngineSide;
-import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ServerSide;
 import org.sonarsource.api.sonarlint.SonarLintSide;
 
@@ -65,7 +64,7 @@ import org.sonarsource.api.sonarlint.SonarLintSide;
  * </pre>
  *
  * <p>
- * For testing, and only for testing, the in-memory implementation {@link MapSettings} can be used.
+ * For testing, and only for testing, the in-memory implementation MapSettings can be used.
  * <pre>
  * {@literal @}Test
  * public void my_test() {
@@ -76,7 +75,6 @@ import org.sonarsource.api.sonarlint.SonarLintSide;
  * }
  * </pre>
  *
- * @see MapSettings
  * @see PropertyDefinition
  * @since 6.5
  */
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java
deleted file mode 100644 (file)
index 5455cf0..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.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/src/main/java/org/sonar/api/config/internal/MapSettings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java
deleted file mode 100644 (file)
index 5d07d60..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.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/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java
deleted file mode 100644 (file)
index dab98c5..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.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/src/main/java/org/sonar/api/config/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java
deleted file mode 100644 (file)
index f677479..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.config.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/MetadataLoader.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/MetadataLoader.java
deleted file mode 100644 (file)
index bb15575..0000000
+++ /dev/null
@@ -1,79 +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.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) {
-    try {
-      URL url = system.getResource(VERSION_FILE_PATH);
-      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) {
-    try {
-      URL url = system.getResource(EDITION_FILE_PATH);
-      if (url == null) {
-        return SonarEdition.COMMUNITY;
-      }
-      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/src/main/java/org/sonar/api/internal/PluginContextImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/PluginContextImpl.java
deleted file mode 100644 (file)
index 3fccb4c..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.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/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java
deleted file mode 100644 (file)
index 3f69f36..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.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/src/main/java/org/sonar/api/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/package-info.java
deleted file mode 100644 (file)
index 17dc122..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.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
index 2eb4d07f57d6000bc6d97d554bf2b997590a8b5f..6f8452a8bd4d587db43d13ffac355f06896f210d 100644 (file)
@@ -324,7 +324,7 @@ public class Rule {
    */
   public Rule setStatus(String status) {
     if (!STATUS_LIST.contains(status)) {
-      throw new SonarException("The status of a rule can only contain : " + String.join(", ", STATUS_LIST));
+      throw new IllegalStateException("The status of a rule can only contain : " + String.join(", ", STATUS_LIST));
     }
     this.status = status;
     return this;
index 6ad36f5998e639912890acfee19f6e34a0f92a9c..d249ac0bda86b8c02443f2b81ff94f7481bd028f 100644 (file)
@@ -347,7 +347,7 @@ public interface RulesDefinition {
   /**
    * Instantiated by core but not by plugins, except for their tests.
    */
-  interface Context {
+  abstract class Context {
     /*
      * New builder for {@link org.sonar.api.server.rule.RulesDefinition.Repository}.
      * <br>
@@ -355,7 +355,7 @@ public interface RulesDefinition {
      * the FbContrib plugin contributes to the Findbugs plugin rules. In this case no need
      * to execute {@link org.sonar.api.server.rule.RulesDefinition.NewRepository#setName(String)}
      */
-    NewRepository createRepository(String key, String language);
+    public abstract NewRepository createRepository(String key, String language);
 
     /**
      * Creates a repository of rules from external rule engines.
@@ -363,34 +363,34 @@ public interface RulesDefinition {
      *
      * @since 7.2
      */
-    NewRepository createExternalRepository(String engineId, String language);
+    public abstract NewRepository createExternalRepository(String engineId, String language);
 
     /**
      * @deprecated since 5.2. Simply use {@link #createRepository(String, String)}
      */
     @Deprecated
-    NewRepository extendRepository(String key, String language);
+    public abstract NewRepository extendRepository(String key, String language);
 
     @CheckForNull
-    Repository repository(String key);
+    public abstract Repository repository(String key);
 
-    List<Repository> repositories();
+    public abstract List<Repository> repositories();
 
     /**
      * @deprecated returns empty list since 5.2. Concept of "extended repository" was misleading and not valuable. Simply declare
      * repositories and use {@link #repositories()}. See http://jira.sonarsource.com/browse/SONAR-6709
      */
     @Deprecated
-    List<ExtendedRepository> extendedRepositories(String repositoryKey);
+    public abstract List<ExtendedRepository> extendedRepositories(String repositoryKey);
 
     /**
      * @deprecated returns empty list since 5.2. Concept of "extended repository" was misleading and not valuable. Simply declare
      * repositories and use {@link #repositories()}. See http://jira.sonarsource.com/browse/SONAR-6709
      */
     @Deprecated
-    List<ExtendedRepository> extendedRepositories();
+    public abstract List<ExtendedRepository> extendedRepositories();
 
-    void setCurrentPluginKey(@Nullable String pluginKey);
+    public abstract void setCurrentPluginKey(@Nullable String pluginKey);
   }
 
   interface NewExtendedRepository {
@@ -484,36 +484,36 @@ public interface RulesDefinition {
     DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String gapMultiplier, @Nullable String baseEffort);
   }
 
-  interface NewRule {
+  abstract class NewRule {
 
-    String key();
+    public abstract String key();
 
     /**
      * @since 7.1
      */
     @CheckForNull
-    RuleScope scope();
+    public abstract RuleScope scope();
 
     /**
      * @since 7.1
      */
-    NewRule setScope(RuleScope scope);
+    public abstract NewRule setScope(RuleScope scope);
 
     /**
      * Required rule name
      */
-    NewRule setName(String s);
+    public abstract NewRule setName(String s);
 
-    NewRule setTemplate(boolean template);
+    public abstract NewRule setTemplate(boolean template);
 
     /**
      * Should this rule be enabled by default. For example in SonarLint standalone.
      *
      * @since 6.0
      */
-    NewRule setActivatedByDefault(boolean activatedByDefault);
+    public abstract NewRule setActivatedByDefault(boolean activatedByDefault);
 
-    NewRule setSeverity(String s);
+    public abstract NewRule setSeverity(String s);
 
     /**
      * The type as defined by the SonarQube Quality Model.
@@ -531,36 +531,36 @@ public interface RulesDefinition {
      *
      * @since 5.5
      */
-    NewRule setType(RuleType t);
+    public abstract NewRule setType(RuleType t);
 
     /**
      * The optional description, in HTML format, has no max length. It's exclusive with markdown description
      * (see {@link #setMarkdownDescription(String)})
      */
-    NewRule setHtmlDescription(@Nullable String s);
+    public abstract NewRule setHtmlDescription(@Nullable String s);
 
     /**
      * Load description from a file available in classpath. Example : <code>setHtmlDescription(getClass().getResource("/myrepo/Rule1234.html")</code>
      */
-    NewRule setHtmlDescription(@Nullable URL classpathUrl);
+    public abstract NewRule setHtmlDescription(@Nullable URL classpathUrl);
 
     /**
      * The optional description, in a restricted Markdown format, has no max length. It's exclusive with HTML description
      * (see {@link #setHtmlDescription(String)})
      */
-    NewRule setMarkdownDescription(@Nullable String s);
+    public abstract NewRule setMarkdownDescription(@Nullable String s);
 
     /**
      * Load description from a file available in classpath. Example : {@code setMarkdownDescription(getClass().getResource("/myrepo/Rule1234.md")}
      */
-    NewRule setMarkdownDescription(@Nullable URL classpathUrl);
+    public abstract NewRule setMarkdownDescription(@Nullable URL classpathUrl);
 
     /**
      * Default value is {@link org.sonar.api.rule.RuleStatus#READY}. The value
      * {@link org.sonar.api.rule.RuleStatus#REMOVED} is not accepted and raises an
      * {@link java.lang.IllegalArgumentException}.
      */
-    NewRule setStatus(RuleStatus status);
+    public abstract NewRule setStatus(RuleStatus status);
 
     /**
      * SQALE sub-characteristic. See http://www.sqale.org
@@ -570,23 +570,24 @@ public interface RulesDefinition {
      * @deprecated in 5.5. SQALE Quality Model is replaced by SonarQube Quality Model. This method does nothing.
      * See https://jira.sonarsource.com/browse/MMF-184
      */
-    NewRule setDebtSubCharacteristic(@Nullable String s);
+    @Deprecated
+    public abstract NewRule setDebtSubCharacteristic(@Nullable String s);
 
     /**
      * Factory of {@link org.sonar.api.server.debt.DebtRemediationFunction}
      */
-    DebtRemediationFunctions debtRemediationFunctions();
+    public abstract DebtRemediationFunctions debtRemediationFunctions();
 
     /**
      * @see #debtRemediationFunctions()
      */
-    NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn);
+    public abstract NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn);
 
     /**
      * @deprecated since 5.5, replaced by {@link #setGapDescription(String)}
      */
     @Deprecated
-    NewRule setEffortToFixDescription(@Nullable String s);
+    public abstract NewRule setEffortToFixDescription(@Nullable String s);
 
     /**
      * For rules that use LINEAR or LINEAR_OFFSET remediation functions, the meaning
@@ -597,44 +598,44 @@ public interface RulesDefinition {
      * remediation function gap multiplier/base effort would be something like
      * "Effort to test one uncovered condition".
      */
-    NewRule setGapDescription(@Nullable String s);
+    public abstract NewRule setGapDescription(@Nullable String s);
 
     /**
      * Create a parameter with given unique key. Max length of key is 128 characters.
      */
-    NewParam createParam(String paramKey);
+    public abstract NewParam createParam(String paramKey);
 
     @CheckForNull
-    NewParam param(String paramKey);
+    public abstract NewParam param(String paramKey);
 
-    Collection<NewParam> params();
+    public abstract Collection<NewParam> params();
 
     /**
      * @see RuleTagFormat
      */
-    NewRule addTags(String... list);
+    public abstract NewRule addTags(String... list);
 
     /**
      * @see RuleTagFormat
      */
-    NewRule setTags(String... list);
+    public abstract NewRule setTags(String... list);
 
     /**
      * @since 7.3
      */
-    NewRule addOwaspTop10(OwaspTop10... standards);
+    public abstract NewRule addOwaspTop10(OwaspTop10... standards);
 
     /**
      * @since 7.3
      */
-    NewRule addCwe(int... nums);
+    public abstract NewRule addCwe(int... nums);
 
     /**
      * Optional key that can be used by the rule engine. Not displayed
      * in webapp. For example the Java Checkstyle plugin feeds this field
      * with the internal path ("Checker/TreeWalker/AnnotationUseStyle").
      */
-    NewRule setInternalKey(@Nullable String s);
+    public abstract NewRule setInternalKey(@Nullable String s);
 
     /**
      * Register a repository and key under which this rule used to be known
@@ -646,10 +647,7 @@ public interface RulesDefinition {
      * @see Rule#deprecatedRuleKeys
      * @since 7.1
      */
-    NewRule addDeprecatedRuleKey(String repository, String key);
-
-    @Override
-    String toString();
+    public abstract NewRule addDeprecatedRuleKey(String repository, String key);
   }
 
   @Immutable
@@ -796,22 +794,22 @@ public interface RulesDefinition {
 
   }
 
-  interface NewParam {
-    String key();
+  abstract class NewParam {
+    public abstract String key();
 
-    NewParam setName(@Nullable String s);
+    public abstract NewParam setName(@Nullable String s);
 
-    NewParam setType(RuleParamType t);
+    public abstract NewParam setType(RuleParamType t);
 
     /**
      * Plain-text description. Can be null. Max length is 4000 characters.
      */
-    NewParam setDescription(@Nullable String s);
+    public abstract NewParam setDescription(@Nullable String s);
 
     /**
      * Empty default value will be converted to null. Max length is 4000 characters.
      */
-    NewParam setDefaultValue(@Nullable String s);
+    public abstract NewParam setDefaultValue(@Nullable String s);
   }
 
   @Immutable
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/PartImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/PartImpl.java
deleted file mode 100644 (file)
index 0aca8b4..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.server.ws.internal;
-
-import java.io.InputStream;
-import org.sonar.api.server.ws.Request;
-
-public class PartImpl implements Request.Part {
-
-  private final InputStream inputStream;
-  private final String fileName;
-
-  public PartImpl(InputStream inputStream, String fileName) {
-    this.inputStream = inputStream;
-    this.fileName = fileName;
-  }
-
-  @Override
-  public InputStream getInputStream() {
-    return inputStream;
-  }
-
-  @Override
-  public String getFileName() {
-    return fileName;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java
deleted file mode 100644 (file)
index 757f8ea..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.server.ws.internal;
-
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.LocalConnector;
-import org.sonar.api.server.ws.Request;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.Objects.requireNonNull;
-
-/**
- * Fake implementation of {@link org.sonar.api.server.ws.Request} used
- * for testing. Call the method {@link #setParam(String, String)} to
- * emulate some parameter values.
- */
-public class SimpleGetRequest extends Request {
-
-  private final Map<String, String[]> params = new HashMap<>();
-  private final Map<String, Part> parts = new HashMap<>();
-  private final Map<String, String> headers = new HashMap<>();
-  private String mediaType = "application/json";
-  private String path;
-
-  @Override
-  public String method() {
-    return "GET";
-  }
-
-  @Override
-  public String getMediaType() {
-    return mediaType;
-  }
-
-  public SimpleGetRequest setMediaType(String mediaType) {
-    requireNonNull(mediaType);
-    this.mediaType = mediaType;
-    return this;
-  }
-
-  @Override
-  public boolean hasParam(String key) {
-    return params.keySet().contains(key);
-  }
-
-  @Override
-  public String param(String key) {
-    String[] strings = params.get(key);
-    return strings == null || strings.length == 0 ? null : strings[0];
-  }
-
-  @Override
-  public List<String> multiParam(String key) {
-    String value = param(key);
-    return value == null ? emptyList() : singletonList(value);
-  }
-
-  @Override
-  @CheckForNull
-  public List<String> paramAsStrings(String key) {
-    String value = param(key);
-    if (value == null) {
-      return null;
-    }
-
-    return Arrays.stream(value.split(",")).map(String::trim).filter(x -> !x.isEmpty()).collect(Collectors.toList());
-  }
-
-  @Override
-  public InputStream paramAsInputStream(String key) {
-    return IOUtils.toInputStream(param(key), UTF_8);
-  }
-
-  public SimpleGetRequest setParam(String key, @Nullable String value) {
-    if (value != null) {
-      params.put(key, new String[] {value});
-    }
-    return this;
-  }
-
-  @Override
-  public Map<String, String[]> getParams() {
-    return params;
-  }
-
-  @Override
-  public Part paramAsPart(String key) {
-    return parts.get(key);
-  }
-
-  public SimpleGetRequest setPart(String key, InputStream input, String fileName) {
-    parts.put(key, new PartImpl(input, fileName));
-    return this;
-  }
-
-  @Override
-  public LocalConnector localConnector() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getPath() {
-    return path;
-  }
-
-  public SimpleGetRequest setPath(String path) {
-    this.path = path;
-    return this;
-  }
-
-  @Override
-  public Optional<String> header(String name) {
-    return Optional.ofNullable(headers.get(name));
-  }
-
-  public SimpleGetRequest setHeader(String name, String value) {
-    headers.put(name, value);
-    return this;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java
deleted file mode 100644 (file)
index 5a9ee97..0000000
+++ /dev/null
@@ -1,242 +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.server.ws.internal;
-
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.server.ws.LocalConnector;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-
-import static java.lang.String.format;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.Objects.requireNonNull;
-import static org.apache.commons.lang.StringUtils.defaultString;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-
-/**
- * @since 4.2
- */
-public abstract class ValidatingRequest extends Request {
-
-  private static final String COMMA_SPLITTER = ",";
-  private WebService.Action action;
-  private LocalConnector localConnector;
-
-  public void setAction(WebService.Action action) {
-    this.action = action;
-  }
-
-  public WebService.Action action() {
-    return action;
-  }
-
-  @Override
-  public LocalConnector localConnector() {
-    requireNonNull(localConnector, "Local connector has not been set");
-    return localConnector;
-  }
-
-  public void setLocalConnector(LocalConnector lc) {
-    this.localConnector = lc;
-  }
-
-  @Override
-  @CheckForNull
-  public String param(String key) {
-    WebService.Param definition = action.param(key);
-    String rawValue = readParam(key, definition);
-    String rawValueOrDefault = defaultString(rawValue, definition.defaultValue());
-    String value = rawValueOrDefault == null ? null : trim(rawValueOrDefault);
-    validateRequiredValue(key, definition, rawValue);
-    if (value == null) {
-      return null;
-    }
-    validatePossibleValues(key, value, definition);
-    validateMaximumLength(key, definition, rawValueOrDefault);
-    validateMinimumLength(key, definition, rawValueOrDefault);
-    validateMaximumValue(key, definition, value);
-    return value;
-  }
-
-  @Override
-  public List<String> multiParam(String key) {
-    WebService.Param definition = action.param(key);
-    List<String> values = readMultiParamOrDefaultValue(key, definition);
-    return validateValues(values, definition);
-  }
-
-  private static String trim(String s) {
-    int begin;
-    for (begin = 0; begin < s.length(); begin++) {
-      if (!Character.isWhitespace(s.charAt(begin))) {
-        break;
-      }
-    }
-
-    int end;
-    for (end = s.length(); end > begin; end--) {
-      if (!Character.isWhitespace(s.charAt(end - 1))) {
-        break;
-      }
-    }
-    return s.substring(begin, end);
-  }
-
-  @Override
-  @CheckForNull
-  public InputStream paramAsInputStream(String key) {
-    return readInputStreamParam(key);
-  }
-
-  @Override
-  @CheckForNull
-  public Part paramAsPart(String key) {
-    return readPart(key);
-  }
-
-  @CheckForNull
-  @Override
-  public List<String> paramAsStrings(String key) {
-    WebService.Param definition = action.param(key);
-    String value = defaultString(readParam(key, definition), definition.defaultValue());
-    if (value == null) {
-      return null;
-    }
-    List<String> values = Arrays.stream(value.split(COMMA_SPLITTER))
-      .map(String::trim)
-      .filter(s -> !s.isEmpty())
-      .collect(Collectors.toList());
-    return validateValues(values, definition);
-  }
-
-  @CheckForNull
-  @Override
-  public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) {
-    List<String> values = paramAsStrings(key);
-    if (values == null) {
-      return null;
-    }
-    return values.stream()
-      .filter(s -> !s.isEmpty())
-      .map(value -> Enum.valueOf(enumClass, value))
-      .collect(Collectors.toList());
-  }
-
-  @CheckForNull
-  private String readParam(String key, @Nullable WebService.Param definition) {
-    checkArgument(definition != null, "BUG - parameter '%s' is undefined for action '%s'", key, action.key());
-    String deprecatedKey = definition.deprecatedKey();
-    return deprecatedKey != null ? defaultString(readParam(deprecatedKey), readParam(key)) : readParam(key);
-  }
-
-  private List<String> readMultiParamOrDefaultValue(String key, @Nullable WebService.Param definition) {
-    checkArgument(definition != null, "BUG - parameter '%s' is undefined for action '%s'", key, action.key());
-
-    List<String> keyValues = readMultiParam(key);
-    if (!keyValues.isEmpty()) {
-      return keyValues;
-    }
-
-    String deprecatedKey = definition.deprecatedKey();
-    List<String> deprecatedKeyValues = deprecatedKey == null ? emptyList() : readMultiParam(deprecatedKey);
-    if (!deprecatedKeyValues.isEmpty()) {
-      return deprecatedKeyValues;
-    }
-
-    String defaultValue = definition.defaultValue();
-    return defaultValue == null ? emptyList() : singletonList(defaultValue);
-  }
-
-  @CheckForNull
-  protected abstract String readParam(String key);
-
-  protected abstract List<String> readMultiParam(String key);
-
-  @CheckForNull
-  protected abstract InputStream readInputStreamParam(String key);
-
-  @CheckForNull
-  protected abstract Part readPart(String key);
-
-  private static List<String> validateValues(List<String> values, WebService.Param definition) {
-    Integer maximumValues = definition.maxValuesAllowed();
-    checkArgument(maximumValues == null || values.size() <= maximumValues, "'%s' can contains only %s values, got %s", definition.key(), maximumValues, values.size());
-    values.forEach(value -> validatePossibleValues(definition.key(), value, definition));
-    return values;
-  }
-
-  private static void validatePossibleValues(String key, String value, WebService.Param definition) {
-    Set<String> possibleValues = definition.possibleValues();
-    if (possibleValues == null) {
-      return;
-    }
-    checkArgument(possibleValues.contains(value), "Value of parameter '%s' (%s) must be one of: %s", key, value, possibleValues);
-  }
-
-  private static void validateMaximumLength(String key, WebService.Param definition, String valueOrDefault) {
-    Integer maximumLength = definition.maximumLength();
-    if (maximumLength == null) {
-      return;
-    }
-    int valueLength = valueOrDefault.length();
-    checkArgument(valueLength <= maximumLength, "'%s' length (%s) is longer than the maximum authorized (%s)", key, valueLength, maximumLength);
-  }
-
-  private static void validateMinimumLength(String key, WebService.Param definition, String valueOrDefault) {
-    Integer minimumLength = definition.minimumLength();
-    if (minimumLength == null) {
-      return;
-    }
-    int valueLength = valueOrDefault.length();
-    checkArgument(valueLength >= minimumLength, "'%s' length (%s) is shorter than the minimum authorized (%s)", key, valueLength, minimumLength);
-  }
-
-  private static void validateMaximumValue(String key, WebService.Param definition, String value) {
-    Integer maximumValue = definition.maximumValue();
-    if (maximumValue == null) {
-      return;
-    }
-    int valueAsInt = validateAsNumeric(key, value);
-    checkArgument(valueAsInt <= maximumValue, "'%s' value (%s) must be less than %s", key, valueAsInt, maximumValue);
-  }
-
-  private static void validateRequiredValue(String key, WebService.Param definition, String value) {
-    boolean required = definition.isRequired();
-    if (required) {
-      checkArgument(value != null, format(MSG_PARAMETER_MISSING, key));
-    }
-  }
-
-  private static int validateAsNumeric(String key, String value) {
-    try {
-      return Integer.parseInt(value);
-    } catch (NumberFormatException exception) {
-      throw new IllegalArgumentException(format("'%s' value '%s' cannot be parsed as an integer", key, value), exception);
-    }
-  }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/package-info.java
deleted file mode 100644 (file)
index 1dc6d3e..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.server.ws.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
index 1a70241d869409db079e5047eea04e2a98719a0e..a67dd38eb84e1c0729aff4b8c6537c88c9f953d8 100644 (file)
 package org.sonar.api.utils;
 
 public class Preconditions {
+  private Preconditions() {
+    // static only
+  }
+
   public static void checkArgument(boolean condition, String message) {
     if (!condition) {
       throw new IllegalArgumentException(message);
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2.java
deleted file mode 100644 (file)
index 3533408..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.utils.internal;
-
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Supplier;
-import org.sonar.api.utils.System2;
-
-import static org.sonar.api.utils.Preconditions.checkArgument;
-
-/**
- * A subclass of {@link System2} which implementation of {@link System2#now()} always return a bigger value than the
- * previous returned value.
- * <p>
- * This class is intended to be used in Unit tests.
- * </p>
- */
-public class AlwaysIncreasingSystem2 extends System2 {
-  private final AtomicLong now;
-  private final long increment;
-
-  private AlwaysIncreasingSystem2(Supplier<Long> initialValueSupplier, long increment) {
-    checkArgument(increment > 0, "increment must be > 0");
-    long initialValue = initialValueSupplier.get();
-    checkArgument(initialValue >= 0, "Initial value must be >= 0");
-    this.now = new AtomicLong(initialValue);
-    this.increment = increment;
-  }
-
-  public AlwaysIncreasingSystem2(long increment) {
-    this(AlwaysIncreasingSystem2::randomInitialValue, increment);
-  }
-
-  public AlwaysIncreasingSystem2(long initialValue, int increment) {
-    this(() -> initialValue, increment);
-  }
-
-  /**
-   * Values returned by {@link #now()} will start with a random value and increment by 100.
-   */
-  public AlwaysIncreasingSystem2() {
-    this(AlwaysIncreasingSystem2::randomInitialValue, 100);
-  }
-
-  @Override
-  public long now() {
-    return now.getAndAdd(increment);
-  }
-
-  private static long randomInitialValue() {
-    return (long) Math.abs(new Random().nextInt(2_000_000));
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java
deleted file mode 100644 (file)
index bedee39..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.utils.internal;
-
-import java.nio.file.FileVisitResult;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import org.apache.commons.io.FileUtils;
-import org.sonar.api.utils.TempFolder;
-
-import javax.annotation.Nullable;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-public class DefaultTempFolder implements TempFolder {
-  private static final Logger LOG = Loggers.get(DefaultTempFolder.class);
-
-  private final File tempDir;
-  private final boolean deleteOnExit;
-
-  public DefaultTempFolder(File tempDir) {
-    this(tempDir, false);
-  }
-
-  public DefaultTempFolder(File tempDir, boolean deleteOnExit) {
-    this.tempDir = tempDir;
-    this.deleteOnExit = deleteOnExit;
-  }
-
-  @Override
-  public File newDir() {
-    return createTempDir(tempDir.toPath()).toFile();
-  }
-
-  private static Path createTempDir(Path baseDir) {
-    try {
-      return Files.createTempDirectory(baseDir, null);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to create temp directory", e);
-    }
-  }
-
-  @Override
-  public File newDir(String name) {
-    File dir = new File(tempDir, name);
-    try {
-      FileUtils.forceMkdir(dir);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to create temp directory - " + dir, e);
-    }
-    return dir;
-  }
-
-  @Override
-  public File newFile() {
-    return newFile(null, null);
-  }
-
-  @Override
-  public File newFile(@Nullable String prefix, @Nullable String suffix) {
-    return createTempFile(tempDir.toPath(), prefix, suffix).toFile();
-  }
-
-  private static Path createTempFile(Path baseDir, String prefix, String suffix) {
-    try {
-      return Files.createTempFile(baseDir, prefix, suffix);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to create temp file", e);
-    }
-  }
-
-  public void clean() {
-    try {
-      if (tempDir.exists()) {
-        Files.walkFileTree(tempDir.toPath(), DeleteRecursivelyFileVisitor.INSTANCE);
-      }
-    } catch (IOException e) {
-      LOG.error("Failed to delete temp folder", e);
-    }
-  }
-
-  public void stop() {
-    if (deleteOnExit) {
-      clean();
-    }
-  }
-
-  private static final class DeleteRecursivelyFileVisitor extends SimpleFileVisitor<Path> {
-    public static final DeleteRecursivelyFileVisitor INSTANCE = new DeleteRecursivelyFileVisitor();
-
-    @Override
-    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-      Files.deleteIfExists(file);
-      return FileVisitResult.CONTINUE;
-    }
-
-    @Override
-    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
-      Files.deleteIfExists(dir);
-      return FileVisitResult.CONTINUE;
-    }
-  }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java
deleted file mode 100644 (file)
index 5c323f2..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.utils.internal;
-
-import org.apache.commons.lang.StringUtils;
-import org.junit.rules.ExternalResource;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-import org.sonar.api.utils.TempFolder;
-
-import javax.annotation.Nullable;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Implementation of {@link org.sonar.api.utils.TempFolder} to be used
- * only in JUnit tests. It wraps {@link org.junit.rules.TemporaryFolder}.
- * <br>
- * Example:
- * <pre>
- * public class MyTest {
- *   &#064;@org.junit.Rule
- *   public JUnitTempFolder temp = new JUnitTempFolder();
- *
- *   &#064;@org.junit.Test
- *   public void myTest() throws Exception {
- *     File dir = temp.newDir();
- *     // ...
- *   }
- * }
- * </pre>
- *
- * @since 5.1
- */
-public class JUnitTempFolder extends ExternalResource implements TempFolder {
-
-  private final TemporaryFolder junit = new TemporaryFolder();
-
-  @Override
-  public Statement apply(Statement base, Description description) {
-    return junit.apply(base, description);
-  }
-
-  @Override
-  protected void before() throws Throwable {
-    junit.create();
-  }
-
-  @Override
-  protected void after() {
-    junit.delete();
-  }
-
-  @Override
-  public File newDir() {
-    try {
-      return junit.newFolder();
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp dir", e);
-    }
-  }
-
-  @Override
-  public File newDir(String name) {
-    try {
-      return junit.newFolder(name);
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp dir", e);
-    }
-  }
-
-  @Override
-  public File newFile() {
-    try {
-      return junit.newFile();
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp file", e);
-    }
-  }
-
-  @Override
-  public File newFile(@Nullable String prefix, @Nullable String suffix) {
-    try {
-      return junit.newFile(StringUtils.defaultString(prefix) + "-" + StringUtils.defaultString(suffix));
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp file", e);
-    }
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TempFolderCleaner.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TempFolderCleaner.java
deleted file mode 100644 (file)
index 3a7836c..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.utils.internal;
-
-import org.sonar.api.Startable;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.TempFolder;
-
-@ServerSide
-public class TempFolderCleaner implements Startable {
-
-  private TempFolder defaultTempFolder;
-
-  public TempFolderCleaner(TempFolder defaultTempFolder) {
-    this.defaultTempFolder = defaultTempFolder;
-  }
-
-  /**
-   * This method should not be renamed. It follows the naming convention
-   * defined by IoC container.
-   */
-  @Override
-  public void start() {
-    // Nothing to do
-  }
-
-  /**
-   * This method should not be renamed. It follows the naming convention
-   * defined by IoC container.
-   */
-  @Override
-  public void stop() {
-    ((DefaultTempFolder) defaultTempFolder).clean();
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TestSystem2.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TestSystem2.java
deleted file mode 100644 (file)
index 37d2ed5..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.utils.internal;
-
-import java.util.TimeZone;
-import org.sonar.api.utils.System2;
-
-public class TestSystem2 extends System2 {
-
-  private long now = 0L;
-  private TimeZone defaultTimeZone = getDefaultTimeZone();
-
-  public TestSystem2 setNow(long l) {
-    this.now = l;
-    return this;
-  }
-
-  @Override
-  public long now() {
-    if (now <= 0L) {
-      throw new IllegalStateException("Method setNow() was not called by test");
-    }
-    return now;
-  }
-
-  public TestSystem2 setDefaultTimeZone(TimeZone defaultTimeZone) {
-    this.defaultTimeZone = defaultTimeZone;
-    return this;
-  }
-
-  @Override
-  public TimeZone getDefaultTimeZone() {
-    return defaultTimeZone;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/WorkDuration.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/WorkDuration.java
deleted file mode 100644 (file)
index fc4de00..0000000
+++ /dev/null
@@ -1,194 +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.utils.internal;
-
-import java.io.Serializable;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-
-/**
- * @since 4.2
- */
-public class WorkDuration implements Serializable {
-
-  static final int DAY_POSITION_IN_LONG = 10_000;
-  static final int HOUR_POSITION_IN_LONG = 100;
-  static final int MINUTE_POSITION_IN_LONG = 1;
-
-  public enum UNIT {
-    DAYS, HOURS, MINUTES
-  }
-
-  private int hoursInDay;
-
-  private long durationInMinutes;
-  private int days;
-  private int hours;
-  private int minutes;
-
-  private WorkDuration(long durationInMinutes, int days, int hours, int minutes, int hoursInDay) {
-    this.durationInMinutes = durationInMinutes;
-    this.days = days;
-    this.hours = hours;
-    this.minutes = minutes;
-    this.hoursInDay = hoursInDay;
-  }
-
-  public static WorkDuration create(int days, int hours, int minutes, int hoursInDay) {
-    long durationInSeconds = 60L * days * hoursInDay;
-    durationInSeconds += 60L * hours;
-    durationInSeconds += minutes;
-    return new WorkDuration(durationInSeconds, days, hours, minutes, hoursInDay);
-  }
-
-  public static WorkDuration createFromValueAndUnit(int value, UNIT unit, int hoursInDay) {
-    switch (unit) {
-      case DAYS:
-        return create(value, 0, 0, hoursInDay);
-      case HOURS:
-        return create(0, value, 0, hoursInDay);
-      case MINUTES:
-        return create(0, 0, value, hoursInDay);
-      default:
-        throw new IllegalStateException("Cannot create work duration");
-    }
-  }
-
-  static WorkDuration createFromLong(long duration, int hoursInDay) {
-    int days = 0;
-    int hours = 0;
-    int minutes = 0;
-
-    long time = duration;
-    Long currentTime = time / WorkDuration.DAY_POSITION_IN_LONG;
-    if (currentTime > 0) {
-      days = currentTime.intValue();
-      time = time - (currentTime * WorkDuration.DAY_POSITION_IN_LONG);
-    }
-
-    currentTime = time / WorkDuration.HOUR_POSITION_IN_LONG;
-    if (currentTime > 0) {
-      hours = currentTime.intValue();
-      time = time - (currentTime * WorkDuration.HOUR_POSITION_IN_LONG);
-    }
-
-    currentTime = time / WorkDuration.MINUTE_POSITION_IN_LONG;
-    if (currentTime > 0) {
-      minutes = currentTime.intValue();
-    }
-    return WorkDuration.create(days, hours, minutes, hoursInDay);
-  }
-
-  static WorkDuration createFromMinutes(long duration, int hoursInDay) {
-    int days = (int)(duration / (double)hoursInDay / 60.0);
-    Long currentDurationInMinutes = duration - (60L * days * hoursInDay);
-    int hours = (int)(currentDurationInMinutes / 60.0);
-    currentDurationInMinutes = currentDurationInMinutes - (60L * hours);
-    return new WorkDuration(duration, days, hours, currentDurationInMinutes.intValue(), hoursInDay);
-  }
-
-  /**
-   * Return the duration in number of working days.
-   * For instance, 3 days and 4 hours will return 3.5 days (if hoursIndDay is 8).
-   */
-  public double toWorkingDays() {
-    return durationInMinutes / 60d / hoursInDay;
-  }
-
-  /**
-   * Return the duration using the following format DDHHMM, where DD is the number of days, HH is the number of months, and MM the number of minutes.
-   * For instance, 3 days and 4 hours will return 030400 (if hoursIndDay is 8).
-   */
-  public long toLong() {
-    int workingDays = days;
-    int workingHours = hours;
-    if (hours >= hoursInDay) {
-      int nbAdditionalDays = hours / hoursInDay;
-      workingDays += nbAdditionalDays;
-      workingHours = hours - (nbAdditionalDays * hoursInDay);
-    }
-    return 1L * workingDays * DAY_POSITION_IN_LONG + workingHours * HOUR_POSITION_IN_LONG + minutes * MINUTE_POSITION_IN_LONG;
-  }
-
-  public long toMinutes() {
-    return durationInMinutes;
-  }
-
-  public WorkDuration add(@Nullable WorkDuration with) {
-    if (with != null) {
-      return WorkDuration.createFromMinutes(this.toMinutes() + with.toMinutes(), this.hoursInDay);
-    } else {
-      return this;
-    }
-  }
-
-  public WorkDuration subtract(@Nullable WorkDuration with) {
-    if (with != null) {
-      return WorkDuration.createFromMinutes(this.toMinutes() - with.toMinutes(), this.hoursInDay);
-    } else {
-      return this;
-    }
-  }
-
-  public WorkDuration multiply(int factor) {
-    return WorkDuration.createFromMinutes(this.toMinutes() * factor, this.hoursInDay);
-  }
-
-  public int days() {
-    return days;
-  }
-
-  public int hours() {
-    return hours;
-  }
-
-  public int minutes() {
-    return minutes;
-  }
-
-  int hoursInDay() {
-    return hoursInDay;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    WorkDuration that = (WorkDuration) o;
-    return durationInMinutes == that.durationInMinutes;
-
-  }
-
-  @Override
-  public int hashCode() {
-    return (int) (durationInMinutes ^ (durationInMinutes >>> 32));
-  }
-
-  @Override
-  public String toString() {
-    return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/package-info.java
deleted file mode 100644 (file)
index f3fea32..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.utils.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
index 53b84c86164266ce134d9c45524d6bca9e165939..6a75a66d49acf4b23b16c36b930e7efcc21a24d8 100644 (file)
@@ -21,9 +21,9 @@ package org.sonar.api;
 
 import java.util.Arrays;
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.internal.PluginContextImpl;
-import org.sonar.api.internal.SonarRuntimeImpl;
+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.utils.Version;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 48f3746bd356fa0da6ffed84d37a82dd5443637f..501b48945e87f60b560e19b36f1abe9ab2ed7fc3 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.core.Is.is;
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/MetadataTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/MetadataTest.java
deleted file mode 100644 (file)
index 861d0b8..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.batch.fs.internal;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.junit.Test;
-
-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/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java
deleted file mode 100644 (file)
index 8296da8..0000000
+++ /dev/null
@@ -1,109 +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.fs.internal;
-
-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.scanner.fs.DefaultIndexedFile;
-
-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");
-  }
-}
index 5a728e95faab887597747471e36f9ca59fbbeb61..b2ccc7a514aac4a9da91a98f602ad65fcac08f7d 100644 (file)
@@ -21,10 +21,9 @@ 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.rule.RuleKey;
 import org.sonar.api.utils.SonarException;
-import org.sonar.scanner.rule.ActiveRulesBuilder;
-import org.sonar.scanner.rule.NewActiveRule;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
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
new file mode 100644 (file)
index 0000000..927c793
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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 8de07ea19a02ee962da6f7646d9e7a2014efb8d4..a67127d5e2d21f925a4536996ed2c237f9018986 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.platform.Server;
 
 import static org.assertj.core.api.Assertions.assertThat;
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/internal/MapSettingsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/internal/MapSettingsTest.java
deleted file mode 100644 (file)
index a22d884..0000000
+++ /dev/null
@@ -1,565 +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.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.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() {
-    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/src/test/java/org/sonar/api/config/internal/MultivaluePropertyTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/internal/MultivaluePropertyTest.java
deleted file mode 100644 (file)
index bd50d94..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.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/src/test/java/org/sonar/api/internal/MetadataLoaderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/internal/MetadataLoaderTest.java
deleted file mode 100644 (file)
index d62ebdc..0000000
+++ /dev/null
@@ -1,79 +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.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/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java
deleted file mode 100644 (file)
index 8e439af..0000000
+++ /dev/null
@@ -1,67 +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.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);
-  }
-
-}
index 20427354f25a0c7b11fd260cc9e9c9439500ef4e..efe7b99c67b87e04f37acd95768458884e5ed279 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.issue.DefaultNoSonarFilter;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.issue.DefaultNoSonarFilter;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index f52f32080b4855d5622925591b19f8222814f0d4..f11be94b5900f1ec1c83b246f163eb679494f16f 100644 (file)
  */
 package org.sonar.api.rules;
 
-import org.junit.Assert;
-import org.junit.Test;
-import org.sonar.api.utils.SonarException;
-
 import java.util.Arrays;
 import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -81,7 +79,7 @@ public class RuleTest {
     assertThat(rule.getSeverity()).isEqualTo(RulePriority.MAJOR);
   }
 
-  @Test(expected = SonarException.class)
+  @Test(expected = IllegalStateException.class)
   public void should_not_authorize_unkown_status() {
     Rule.create().setStatus("Unknown");
   }
index 91499a18c77a74502c340e3dc14232f34c5b3ae2..0889a04aaf28fbb4b42eba565d2da4c521bb8ad8 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index bf7678ab7574d49de426575e0ac860e2fd4f6af1..f841e1a6afd25b4ffa04788e52ca98d8d6aa155d 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.server.rule.RuleDefinitionContext;
+import org.sonar.api.impl.server.RuleDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index d7c0ab4e3d82a638feeb06a1f4dc581318917e93..65a523e017950f0aad5d000ae5618d699da84436 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.server.rule.RuleDefinitionContext;
+import org.sonar.api.impl.server.RuleDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 50eea7cf408c508efc4e6fb3c9704eb978829163..27fd0a673ceaa7decf483263aecb5423c9538db2 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.server.rule.RuleDefinitionContext;
+import org.sonar.api.impl.server.RuleDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.fail;
index 3e180e3abca4c3bf346af6910b7da777fbcef726..4103c498b08d2bff98ac24ac3fd211fd32070ea5 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.server.rule.RuleDefinitionContext;
+import org.sonar.api.impl.server.RuleDefinitionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.utils.ExceptionCauseMatcher.hasType;
index e887feea0182da59814d62234c25e31f74cb58ef..ed0622fb956647946f09c36ea0c5c781ec00cd08 100644 (file)
@@ -41,8 +41,8 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.server.ws.internal.PartImpl;
-import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.api.impl.ws.PartImpl;
+import org.sonar.api.impl.ws.ValidatingRequest;
 import org.sonar.api.utils.DateUtils;
 
 import static com.google.common.base.Strings.repeat;
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/internal/SimpleGetRequestTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/internal/SimpleGetRequestTest.java
deleted file mode 100644 (file)
index d8e1d90..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.server.ws.internal;
-
-import java.io.InputStream;
-import org.junit.Test;
-import org.sonar.api.server.ws.Request;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.entry;
-import static org.mockito.Mockito.mock;
-
-public class SimpleGetRequestTest {
-
-  SimpleGetRequest underTest = new SimpleGetRequest();
-
-  @Test
-  public void method() {
-    assertThat(underTest.method()).isEqualTo("GET");
-
-    underTest.setParam("foo", "bar");
-    assertThat(underTest.param("foo")).isEqualTo("bar");
-    assertThat(underTest.param("unknown")).isNull();
-  }
-
-  @Test
-  public void has_param() {
-    assertThat(underTest.method()).isEqualTo("GET");
-
-    underTest.setParam("foo", "bar");
-    assertThat(underTest.hasParam("foo")).isTrue();
-    assertThat(underTest.hasParam("unknown")).isFalse();
-  }
-
-  @Test
-  public void get_part() {
-    InputStream inputStream = mock(InputStream.class);
-    underTest.setPart("key", inputStream, "filename");
-
-    Request.Part part = underTest.paramAsPart("key");
-    assertThat(part.getInputStream()).isEqualTo(inputStream);
-    assertThat(part.getFileName()).isEqualTo("filename");
-
-    assertThat(underTest.paramAsPart("unknown")).isNull();
-  }
-
-  @Test
-  public void getMediaType() {
-    underTest.setMediaType("JSON");
-
-    assertThat(underTest.getMediaType()).isEqualTo("JSON");
-  }
-
-  @Test
-  public void multiParam_with_one_element() {
-    underTest.setParam("foo", "bar");
-
-    assertThat(underTest.multiParam("foo")).containsExactly("bar");
-  }
-
-  @Test
-  public void multiParam_without_any_element() {
-    assertThat(underTest.multiParam("42")).isEmpty();
-  }
-
-  @Test
-  public void getParams() {
-    underTest
-      .setParam("foo", "bar")
-      .setParam("fee", "beer");
-
-    assertThat(underTest.getParams()).containsOnly(
-      entry("foo", new String[] {"bar"}),
-      entry("fee", new String[] {"beer"}));
-  }
-
-  @Test
-  public void header_returns_empty_if_header_is_not_present() {
-    assertThat(underTest.header("foo")).isEmpty();
-  }
-
-  @Test
-  public void header_returns_value_of_header_if_present() {
-    underTest.setHeader("foo", "bar");
-    assertThat(underTest.header("foo")).hasValue("bar");
-  }
-
-  @Test
-  public void header_returns_empty_string_value_if_header_is_present_without_value() {
-    underTest.setHeader("foo", "");
-    assertThat(underTest.header("foo")).hasValue("");
-  }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2Test.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2Test.java
deleted file mode 100644 (file)
index 7155af8..0000000
+++ /dev/null
@@ -1,118 +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.utils.internal;
-
-import javax.annotation.Nullable;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class AlwaysIncreasingSystem2Test {
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void default_constructor_makes_now_start_with_random_number_and_increase_returned_value_by_100_with_each_call() {
-    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2();
-    verifyValuesReturnedByNow(underTest, null, 100);
-  }
-
-  @Test
-  public void constructor_with_increment_makes_now_start_with_random_number_and_increase_returned_value_by_specified_value_with_each_call() {
-    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2(663);
-
-    verifyValuesReturnedByNow(underTest, null, 663);
-  }
-
-  @Test
-  public void constructor_with_initial_value_and_increment_makes_now_start_with_specified_value_and_increase_returned_value_by_specified_value_with_each_call() {
-    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2(777777L, 96);
-
-    verifyValuesReturnedByNow(underTest, 777777L, 96);
-  }
-
-  @Test
-  public void constructor_with_initial_value_and_increment_throws_IAE_if_initial_value_is_less_than_0() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Initial value must be >= 0");
-    
-    new AlwaysIncreasingSystem2(-1, 100);
-  }
-
-  @Test
-  public void constructor_with_initial_value_and_increment_accepts_initial_value_0() {
-    AlwaysIncreasingSystem2 underTest = new AlwaysIncreasingSystem2(0, 100);
-
-    verifyValuesReturnedByNow(underTest, 0L, 100);
-  }
-
-  @Test
-  public void constructor_with_initial_value_and_increment_throws_IAE_if_increment_is_0() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("increment must be > 0");
-
-    new AlwaysIncreasingSystem2(10, 0);
-  }
-
-  @Test
-  public void constructor_with_initial_value_and_increment_throws_IAE_if_increment_is_less_than_0() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("increment must be > 0");
-
-    new AlwaysIncreasingSystem2(10, -66);
-  }
-
-  @Test
-  public void constructor_with_increment_throws_IAE_if_increment_is_0() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("increment must be > 0");
-
-    new AlwaysIncreasingSystem2(0);
-  }
-
-  @Test
-  public void constructor_with_increment_throws_IAE_if_increment_is_less_than_0() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("increment must be > 0");
-
-    new AlwaysIncreasingSystem2(-20);
-  }
-
-  private void verifyValuesReturnedByNow(AlwaysIncreasingSystem2 underTest, @Nullable Long initialValue, int increment) {
-    long previousValue = -1;
-    for (int i = 0; i < 333; i++) {
-      if (previousValue == -1) {
-        long now = underTest.now();
-        if (initialValue != null) {
-          assertThat(now).isEqualTo(initialValue);
-        } else {
-          assertThat(now).isGreaterThan(0);
-        }
-        previousValue = now;
-      } else {
-        long now = underTest.now();
-        assertThat(now).isEqualTo(previousValue + increment);
-        previousValue = now;
-      }
-    }
-  }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/DefaultTempFolderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/DefaultTempFolderTest.java
deleted file mode 100644 (file)
index 6078b8c..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.utils.internal;
-
-import java.io.File;
-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.assertj.core.api.Assertions.assertThat;
-
-public class DefaultTempFolderTest {
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Rule
-  public LogTester logTester = new LogTester();
-
-  @Test
-  public void createTempFolderAndFile() throws Exception {
-    File rootTempFolder = temp.newFolder();
-    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
-    File dir = underTest.newDir();
-    assertThat(dir).exists().isDirectory();
-    File file = underTest.newFile();
-    assertThat(file).exists().isFile();
-
-    new TempFolderCleaner(underTest).stop();
-    assertThat(rootTempFolder).doesNotExist();
-  }
-
-  @Test
-  public void createTempFolderWithName() throws Exception {
-    File rootTempFolder = temp.newFolder();
-    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
-    File dir = underTest.newDir("sample");
-    assertThat(dir).exists().isDirectory();
-    assertThat(new File(rootTempFolder, "sample")).isEqualTo(dir);
-
-    new TempFolderCleaner(underTest).stop();
-    assertThat(rootTempFolder).doesNotExist();
-  }
-
-  @Test
-  public void newDir_throws_ISE_if_name_is_not_valid() throws Exception {
-    File rootTempFolder = temp.newFolder();
-    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
-    String tooLong = "tooooolong";
-    for (int i = 0; i < 50; i++) {
-      tooLong += "tooooolong";
-    }
-
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Failed to create temp directory");
-
-    underTest.newDir(tooLong);
-  }
-
-  @Test
-  public void newFile_throws_ISE_if_name_is_not_valid() throws Exception {
-    File rootTempFolder = temp.newFolder();
-    DefaultTempFolder underTest = new DefaultTempFolder(rootTempFolder);
-    String tooLong = "tooooolong";
-    for (int i = 0; i < 50; i++) {
-      tooLong += "tooooolong";
-    }
-
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Failed to create temp file");
-
-    underTest.newFile(tooLong, ".txt");
-  }
-
-  @Test
-  public void clean_deletes_non_empty_directory() throws Exception {
-    File dir = temp.newFolder();
-    FileUtils.touch(new File(dir, "foo.txt"));
-
-    DefaultTempFolder underTest = new DefaultTempFolder(dir);
-    underTest.clean();
-
-    assertThat(dir).doesNotExist();
-  }
-
-  @Test
-  public void clean_does_not_fail_if_directory_has_already_been_deleted() throws Exception {
-    File dir = temp.newFolder();
-
-    DefaultTempFolder underTest = new DefaultTempFolder(dir);
-    underTest.clean();
-    assertThat(dir).doesNotExist();
-
-    // second call does not fail, nor log ERROR logs
-    underTest.clean();
-
-    assertThat(logTester.logs(LoggerLevel.ERROR)).isEmpty();
-  }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/JUnitTempFolderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/JUnitTempFolderTest.java
deleted file mode 100644 (file)
index d4a377c..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.utils.internal;
-
-import org.junit.Test;
-
-import java.io.File;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class JUnitTempFolderTest {
-
-  @Test
-  public void apply() throws Throwable {
-    JUnitTempFolder temp = new JUnitTempFolder();
-    temp.before();
-    File dir1 = temp.newDir();
-    assertThat(dir1).isDirectory().exists();
-
-    File dir2 = temp.newDir("foo");
-    assertThat(dir2).isDirectory().exists();
-
-    File file1 = temp.newFile();
-    assertThat(file1).isFile().exists();
-
-    File file2 = temp.newFile("foo", "txt");
-    assertThat(file2).isFile().exists();
-
-    temp.after();
-    assertThat(dir1).doesNotExist();
-    assertThat(dir2).doesNotExist();
-    assertThat(file1).doesNotExist();
-    assertThat(file2).doesNotExist();
-  }
-
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/WorkDurationTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/internal/WorkDurationTest.java
deleted file mode 100644 (file)
index 131f202..0000000
+++ /dev/null
@@ -1,200 +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.utils.internal;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class WorkDurationTest {
-
-  static final int HOURS_IN_DAY = 8;
-
-  static final Long ONE_MINUTE = 1L;
-  static final Long ONE_HOUR_IN_MINUTES = ONE_MINUTE * 60;
-  static final Long ONE_DAY_IN_MINUTES = ONE_HOUR_IN_MINUTES * HOURS_IN_DAY;
-
-  @Test
-  public void create_from_days_hours_minutes() {
-    WorkDuration workDuration = WorkDuration.create(1, 1, 1, HOURS_IN_DAY);
-    assertThat(workDuration.days()).isEqualTo(1);
-    assertThat(workDuration.hours()).isEqualTo(1);
-    assertThat(workDuration.minutes()).isEqualTo(1);
-    assertThat(workDuration.toMinutes()).isEqualTo(ONE_DAY_IN_MINUTES + ONE_HOUR_IN_MINUTES + ONE_MINUTE);
-    assertThat(workDuration.hoursInDay()).isEqualTo(HOURS_IN_DAY);
-  }
-
-  @Test
-  public void create_from_value_and_unit() {
-    WorkDuration result = WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.DAYS, HOURS_IN_DAY);
-    assertThat(result.days()).isEqualTo(1);
-    assertThat(result.hours()).isEqualTo(0);
-    assertThat(result.minutes()).isEqualTo(0);
-    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
-    assertThat(result.toMinutes()).isEqualTo(ONE_DAY_IN_MINUTES);
-
-    assertThat(WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toMinutes()).isEqualTo(ONE_DAY_IN_MINUTES);
-    assertThat(WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toMinutes()).isEqualTo(ONE_HOUR_IN_MINUTES);
-    assertThat(WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toMinutes()).isEqualTo(ONE_MINUTE);
-  }
-
-  @Test
-  public void create_from_minutes() {
-    WorkDuration workDuration = WorkDuration.createFromMinutes(ONE_MINUTE, HOURS_IN_DAY);
-    assertThat(workDuration.days()).isEqualTo(0);
-    assertThat(workDuration.hours()).isEqualTo(0);
-    assertThat(workDuration.minutes()).isEqualTo(1);
-
-    workDuration = WorkDuration.createFromMinutes(ONE_HOUR_IN_MINUTES, HOURS_IN_DAY);
-    assertThat(workDuration.days()).isEqualTo(0);
-    assertThat(workDuration.hours()).isEqualTo(1);
-    assertThat(workDuration.minutes()).isEqualTo(0);
-
-    workDuration = WorkDuration.createFromMinutes(ONE_DAY_IN_MINUTES, HOURS_IN_DAY);
-    assertThat(workDuration.days()).isEqualTo(1);
-    assertThat(workDuration.hours()).isEqualTo(0);
-    assertThat(workDuration.minutes()).isEqualTo(0);
-  }
-
-  @Test
-  public void create_from_working_long() {
-    // 1 minute
-    WorkDuration workDuration = WorkDuration.createFromLong(1L, HOURS_IN_DAY);
-    assertThat(workDuration.days()).isEqualTo(0);
-    assertThat(workDuration.hours()).isEqualTo(0);
-    assertThat(workDuration.minutes()).isEqualTo(1);
-
-    // 1 hour
-    workDuration = WorkDuration.createFromLong(100L, HOURS_IN_DAY);
-    assertThat(workDuration.days()).isEqualTo(0);
-    assertThat(workDuration.hours()).isEqualTo(1);
-    assertThat(workDuration.minutes()).isEqualTo(0);
-
-    // 1 day
-    workDuration = WorkDuration.createFromLong(10000L, HOURS_IN_DAY);
-    assertThat(workDuration.days()).isEqualTo(1);
-    assertThat(workDuration.hours()).isEqualTo(0);
-    assertThat(workDuration.minutes()).isEqualTo(0);
-  }
-
-  @Test
-  public void convert_to_seconds() {
-    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toMinutes()).isEqualTo(2L * ONE_MINUTE);
-    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toMinutes()).isEqualTo(2L * ONE_HOUR_IN_MINUTES);
-    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toMinutes()).isEqualTo(2L * ONE_DAY_IN_MINUTES);
-  }
-
-  @Test
-  public void convert_to_working_days() {
-    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toWorkingDays()).isEqualTo(2d / 60d / 8d);
-    assertThat(WorkDuration.createFromValueAndUnit(240, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toWorkingDays()).isEqualTo(0.5);
-    assertThat(WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(0.5);
-    assertThat(WorkDuration.createFromValueAndUnit(8, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(1d);
-    assertThat(WorkDuration.createFromValueAndUnit(16, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(2d);
-    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toWorkingDays()).isEqualTo(2d);
-  }
-
-  @Test
-  public void convert_to_working_long() {
-    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).toLong()).isEqualTo(2l);
-    assertThat(WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toLong()).isEqualTo(400l);
-    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toLong()).isEqualTo(10200l);
-    assertThat(WorkDuration.createFromValueAndUnit(8, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).toLong()).isEqualTo(10000l);
-    assertThat(WorkDuration.createFromValueAndUnit(2, WorkDuration.UNIT.DAYS, HOURS_IN_DAY).toLong()).isEqualTo(20000l);
-  }
-
-  @Test
-  public void add() {
-    // 4h + 5h = 1d 1h
-    WorkDuration result = WorkDuration.createFromValueAndUnit(4, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).add(WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.HOURS, HOURS_IN_DAY));
-    assertThat(result.days()).isEqualTo(1);
-    assertThat(result.hours()).isEqualTo(1);
-    assertThat(result.minutes()).isEqualTo(0);
-    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
-
-    // 40 m + 30m = 1h 10m
-    result = WorkDuration.createFromValueAndUnit(40, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).add(WorkDuration.createFromValueAndUnit(30, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY));
-    assertThat(result.days()).isEqualTo(0);
-    assertThat(result.hours()).isEqualTo(1);
-    assertThat(result.minutes()).isEqualTo(10);
-    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
-
-    // 10 m + 20m = 30m
-    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).add(
-      WorkDuration.createFromValueAndUnit(20, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY)
-    ).minutes()).isEqualTo(30);
-
-    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).add(null).minutes()).isEqualTo(10);
-  }
-
-  @Test
-  public void subtract() {
-    // 1d 1h - 5h = 4h
-    WorkDuration result = WorkDuration.create(1, 1, 0, HOURS_IN_DAY).subtract(WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.HOURS, HOURS_IN_DAY));
-    assertThat(result.days()).isEqualTo(0);
-    assertThat(result.hours()).isEqualTo(4);
-    assertThat(result.minutes()).isEqualTo(0);
-    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
-
-    // 1h 10m - 30m = 40m
-    result = WorkDuration.create(0, 1, 10, HOURS_IN_DAY).subtract(WorkDuration.createFromValueAndUnit(30, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY));
-    assertThat(result.days()).isEqualTo(0);
-    assertThat(result.hours()).isEqualTo(0);
-    assertThat(result.minutes()).isEqualTo(40);
-    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
-
-    // 30m - 20m = 10m
-    assertThat(WorkDuration.createFromValueAndUnit(30, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).subtract(WorkDuration.createFromValueAndUnit(20, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY))
-      .minutes()).isEqualTo(10);
-
-    assertThat(WorkDuration.createFromValueAndUnit(10, WorkDuration.UNIT.MINUTES, HOURS_IN_DAY).subtract(null).minutes()).isEqualTo(10);
-  }
-
-  @Test
-  public void multiply() {
-    // 5h * 2 = 1d 2h
-    WorkDuration result = WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.HOURS, HOURS_IN_DAY).multiply(2);
-    assertThat(result.days()).isEqualTo(1);
-    assertThat(result.hours()).isEqualTo(2);
-    assertThat(result.minutes()).isEqualTo(0);
-    assertThat(result.hoursInDay()).isEqualTo(HOURS_IN_DAY);
-  }
-
-  @Test
-  public void test_equals_and_hashcode() throws Exception {
-    WorkDuration duration = WorkDuration.createFromLong(28800, HOURS_IN_DAY);
-    WorkDuration durationWithSameValue = WorkDuration.createFromLong(28800, HOURS_IN_DAY);
-    WorkDuration durationWithDifferentValue = WorkDuration.createFromLong(14400, HOURS_IN_DAY);
-
-    assertThat(duration).isEqualTo(duration);
-    assertThat(durationWithSameValue).isEqualTo(duration);
-    assertThat(durationWithDifferentValue).isNotEqualTo(duration);
-    assertThat(duration).isNotEqualTo(null);
-
-    assertThat(duration.hashCode()).isEqualTo(duration.hashCode());
-    assertThat(durationWithSameValue.hashCode()).isEqualTo(duration.hashCode());
-    assertThat(durationWithDifferentValue.hashCode()).isNotEqualTo(duration.hashCode());
-  }
-
-  @Test
-  public void test_toString() throws Exception {
-    assertThat(WorkDuration.createFromLong(28800, HOURS_IN_DAY).toString()).isNotNull();
-  }
-}
index 68880e4ae0af80ea94cd84524e7e8fac9b5a34ab..65821d1555aa214f649e85374f390c98c00404fe 100644 (file)
@@ -30,6 +30,7 @@ dependencies {
   compile project(':sonar-scanner-protocol')
   compile project(':sonar-ws')
   compile project(':sonar-duplications')
+  compile project(':sonar-plugin-api-impl')
   runtime project(path: ':sonar-plugin-api', configuration: 'shadow')
   compileOnly project(path: ':sonar-plugin-api')
 
@@ -44,7 +45,6 @@ dependencies {
   testCompile 'org.mockito:mockito-core'
   testCompile project(':plugins:sonar-xoo-plugin')
   testCompile project(':sonar-plugin-api').sourceSets.test.output
-  testCompile project(':server:sonar-server')
 
 }
 
index be5b715891fb69e262dfa5d69b8626e863e24361..e0481cfb52d1d7e107e73db40850a5cda1e3d1c8 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.scanner.sensor.DefaultMeasure;
+import org.sonar.api.impl.sensor.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.FileLinesContext;
 import org.sonar.api.utils.KeyValueFormat;
index dee0cc79aa78da2dfeda0100b3e641a913bf8326..8848449b2f30478f5202d3f01434d0f2d2f0d9cf 100644 (file)
@@ -25,9 +25,9 @@ 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.impl.utils.DefaultTempFolder;
 import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.internal.DefaultTempFolder;
-import org.sonar.scanner.fs.DefaultInputProject;
 
 public class AnalysisTempFolderProvider extends ProviderAdapter implements ComponentLifecycle<TempFolder> {
   static final String TMP_NAME = ".sonartmp";
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/DefaultScannerWsClient.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/DefaultScannerWsClient.java
new file mode 100644 (file)
index 0000000..2cf094e
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * 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.scanner.bootstrap;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.log.Profiler;
+import org.sonarqube.ws.client.HttpException;
+import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.WsConnector;
+import org.sonarqube.ws.client.WsRequest;
+import org.sonarqube.ws.client.WsResponse;
+
+import static java.lang.String.format;
+import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
+import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultScannerWsClient implements ScannerWsClient {
+  private static final int MAX_ERROR_MSG_LEN = 128;
+  private static final Logger LOG = Loggers.get(DefaultScannerWsClient.class);
+
+  private final WsClient target;
+  private final boolean hasCredentials;
+  private final GlobalAnalysisMode globalMode;
+
+  public DefaultScannerWsClient(WsClient target, boolean hasCredentials, GlobalAnalysisMode globalMode) {
+    this.target = target;
+    this.hasCredentials = hasCredentials;
+    this.globalMode = globalMode;
+  }
+
+  /**
+   * If an exception is not thrown, the response needs to be closed by either calling close() directly, or closing the
+   * body content's stream/reader.
+   *
+   * @throws IllegalStateException if the request could not be executed due to a connectivity problem or timeout. Because networks can
+   *                               fail during an exchange, it is possible that the remote server accepted the request before the failure
+   * @throws MessageException      if there was a problem with authentication or if a error message was parsed from the response.
+   * @throws HttpException         if the response code is not in range [200..300). Consider using {@link #createErrorMessage(HttpException)} to create more relevant messages for the users.
+   */
+  public WsResponse call(WsRequest request) {
+    checkState(!globalMode.isMediumTest(), "No WS call should be made in medium test mode");
+    Profiler profiler = Profiler.createIfDebug(LOG).start();
+    WsResponse response = target.wsConnector().call(request);
+    profiler.stopDebug(format("%s %d %s", request.getMethod(), response.code(), response.requestUrl()));
+    failIfUnauthorized(response);
+    return response;
+  }
+
+  public String baseUrl() {
+    return target.wsConnector().baseUrl();
+  }
+
+  WsConnector wsConnector() {
+    return target.wsConnector();
+  }
+
+  private void failIfUnauthorized(WsResponse response) {
+    int code = response.code();
+    if (code == HTTP_UNAUTHORIZED) {
+      response.close();
+      if (hasCredentials) {
+        // credentials are not valid
+        throw MessageException.of(format("Not authorized. Please check the properties %s and %s.",
+          CoreProperties.LOGIN, CoreProperties.PASSWORD));
+      }
+      // not authenticated - see https://jira.sonarsource.com/browse/SONAR-4048
+      throw MessageException.of(format("Not authorized. Analyzing this project requires to be authenticated. " +
+        "Please provide the values of the properties %s and %s.", CoreProperties.LOGIN, CoreProperties.PASSWORD));
+
+    }
+    if (code == HTTP_FORBIDDEN) {
+      throw MessageException.of("You're not authorized to run analysis. Please contact the project administrator.");
+    }
+    if (code == HTTP_BAD_REQUEST) {
+      String jsonMsg = tryParseAsJsonError(response.content());
+      if (jsonMsg != null) {
+        throw MessageException.of(jsonMsg);
+      }
+    }
+
+    // if failed, throws an HttpException
+    response.failIfNotSuccessful();
+  }
+
+  /**
+   * Tries to form a short and relevant error message from the exception, to be displayed in the console.
+   */
+  public static String createErrorMessage(HttpException exception) {
+    String json = tryParseAsJsonError(exception.content());
+    if (json != null) {
+      return json;
+    }
+
+    String msg = "HTTP code " + exception.code();
+    if (isHtml(exception.content())) {
+      return msg;
+    }
+
+    return msg + ": " + StringUtils.left(exception.content(), MAX_ERROR_MSG_LEN);
+  }
+
+  @CheckForNull
+  private static String tryParseAsJsonError(String responseContent) {
+    try {
+      JsonParser parser = new JsonParser();
+      JsonObject obj = parser.parse(responseContent).getAsJsonObject();
+      JsonArray errors = obj.getAsJsonArray("errors");
+      List<String> errorMessages = new ArrayList<>();
+      for (JsonElement e : errors) {
+        errorMessages.add(e.getAsJsonObject().get("msg").getAsString());
+      }
+      return String.join(", ", errorMessages);
+    } catch (Exception e) {
+      return null;
+    }
+  }
+
+  private static boolean isHtml(String responseContent) {
+    return StringUtils.stripToEmpty(responseContent).startsWith("<!DOCTYPE html>");
+  }
+}
index cf39ff12cdf23d7cc35d196964bbab47c1bf4a95..7c93cfa4ce407d27e406bd95530e8dea6eab9527 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.internal.PluginContextImpl;
+import org.sonar.api.impl.context.PluginContextImpl;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginInfo;
 import org.sonar.core.platform.PluginRepository;
index 87f69aad2a849ce9182ea0c934724ad5c12b612e..5903adcbf67c34c5a90253abbf82f811d69d5f17 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.internal.MetadataLoader;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.context.MetadataLoader;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.UriReader;
index ad49d73742589e259409d47e2ab67ddc8c6cbcf8..33ff6234a22f63fe17c2d6c2b1cdbe53c2b5fbd4 100644 (file)
@@ -31,9 +31,9 @@ import org.picocontainer.ComponentLifecycle;
 import org.picocontainer.PicoContainer;
 import org.picocontainer.injectors.ProviderAdapter;
 import org.sonar.api.CoreProperties;
+import org.sonar.api.impl.utils.DefaultTempFolder;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.internal.DefaultTempFolder;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 
index e6b12f2cf85f0d1862583b387fa4b5481322f073..406e82b067149c7feb72798165557e0e7c49be40 100644 (file)
@@ -52,11 +52,11 @@ public class PluginFiles {
   private static final String PACK200 = "pack200";
   private static final String UNCOMPRESSED_MD5_HEADER = "Sonar-UncompressedMD5";
 
-  private final ScannerWsClient wsClient;
+  private final DefaultScannerWsClient wsClient;
   private final File cacheDir;
   private final File tempDir;
 
-  public PluginFiles(ScannerWsClient wsClient, Configuration configuration) {
+  public PluginFiles(DefaultScannerWsClient wsClient, Configuration configuration) {
     this.wsClient = wsClient;
     File home = locateHomeDir(configuration);
     this.cacheDir = mkdir(new File(home, "cache"), "user cache");
index db02b02d440d5d999546c1e30af1f71a35aa4299..d80a52a26e9f8e0f501494482f922be18b89f35c 100644 (file)
@@ -45,9 +45,9 @@ public class ScannerPluginInstaller implements PluginInstaller {
   private static final String PLUGINS_WS_URL = "api/plugins/installed";
 
   private final PluginFiles pluginFiles;
-  private final ScannerWsClient wsClient;
+  private final DefaultScannerWsClient wsClient;
 
-  public ScannerPluginInstaller(PluginFiles pluginFiles, ScannerWsClient wsClient) {
+  public ScannerPluginInstaller(PluginFiles pluginFiles, DefaultScannerWsClient wsClient) {
     this.pluginFiles = pluginFiles;
     this.wsClient = wsClient;
   }
index e04de9c05d9696d19ab2af06893ffe875de9e2c6..3d13b6e3139ef266092cc6c9e4f888d20041053a 100644 (file)
  */
 package org.sonar.scanner.bootstrap;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import java.util.ArrayList;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.utils.MessageException;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.log.Profiler;
-import org.sonarqube.ws.client.HttpException;
-import org.sonarqube.ws.client.WsClient;
-import org.sonarqube.ws.client.WsConnector;
 import org.sonarqube.ws.client.WsRequest;
 import org.sonarqube.ws.client.WsResponse;
 
-import static java.lang.String.format;
-import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
-import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
-import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
+public interface ScannerWsClient {
+  WsResponse call(WsRequest request);
 
-public class ScannerWsClient {
-  private static final int MAX_ERROR_MSG_LEN = 128;
-  private static final Logger LOG = Loggers.get(ScannerWsClient.class);
+  String baseUrl();
 
-  private final WsClient target;
-  private final boolean hasCredentials;
-  private final GlobalAnalysisMode globalMode;
 
-  public ScannerWsClient(WsClient target, boolean hasCredentials, GlobalAnalysisMode globalMode) {
-    this.target = target;
-    this.hasCredentials = hasCredentials;
-    this.globalMode = globalMode;
-  }
-
-  /**
-   * If an exception is not thrown, the response needs to be closed by either calling close() directly, or closing the
-   * body content's stream/reader.
-   *
-   * @throws IllegalStateException if the request could not be executed due to a connectivity problem or timeout. Because networks can
-   *                               fail during an exchange, it is possible that the remote server accepted the request before the failure
-   * @throws MessageException      if there was a problem with authentication or if a error message was parsed from the response.
-   * @throws HttpException         if the response code is not in range [200..300). Consider using {@link #createErrorMessage(HttpException)} to create more relevant messages for the users.
-   */
-  public WsResponse call(WsRequest request) {
-    Preconditions.checkState(!globalMode.isMediumTest(), "No WS call should be made in medium test mode");
-    Profiler profiler = Profiler.createIfDebug(LOG).start();
-    WsResponse response = target.wsConnector().call(request);
-    profiler.stopDebug(format("%s %d %s", request.getMethod(), response.code(), response.requestUrl()));
-    failIfUnauthorized(response);
-    return response;
-  }
-
-  public String baseUrl() {
-    return target.wsConnector().baseUrl();
-  }
-
-  @VisibleForTesting
-  WsConnector wsConnector() {
-    return target.wsConnector();
-  }
-
-  private void failIfUnauthorized(WsResponse response) {
-    int code = response.code();
-    if (code == HTTP_UNAUTHORIZED) {
-      response.close();
-      if (hasCredentials) {
-        // credentials are not valid
-        throw MessageException.of(format("Not authorized. Please check the properties %s and %s.",
-          CoreProperties.LOGIN, CoreProperties.PASSWORD));
-      }
-      // not authenticated - see https://jira.sonarsource.com/browse/SONAR-4048
-      throw MessageException.of(format("Not authorized. Analyzing this project requires to be authenticated. " +
-        "Please provide the values of the properties %s and %s.", CoreProperties.LOGIN, CoreProperties.PASSWORD));
-
-    }
-    if (code == HTTP_FORBIDDEN) {
-      throw MessageException.of("You're not authorized to run analysis. Please contact the project administrator.");
-    }
-    if (code == HTTP_BAD_REQUEST) {
-      String jsonMsg = tryParseAsJsonError(response.content());
-      if (jsonMsg != null) {
-        throw MessageException.of(jsonMsg);
-      }
-    }
-
-    // if failed, throws an HttpException
-    response.failIfNotSuccessful();
-  }
-
-  /**
-   * Tries to form a short and relevant error message from the exception, to be displayed in the console.
-   */
-  public static String createErrorMessage(HttpException exception) {
-    String json = tryParseAsJsonError(exception.content());
-    if (json != null) {
-      return json;
-    }
-
-    String msg = "HTTP code " + exception.code();
-    if (isHtml(exception.content())) {
-      return msg;
-    }
-
-    return msg + ": " + StringUtils.left(exception.content(), MAX_ERROR_MSG_LEN);
-  }
-
-  @CheckForNull
-  private static String tryParseAsJsonError(String responseContent) {
-    try {
-      JsonParser parser = new JsonParser();
-      JsonObject obj = parser.parse(responseContent).getAsJsonObject();
-      JsonArray errors = obj.getAsJsonArray("errors");
-      List<String> errorMessages = new ArrayList<>();
-      for (JsonElement e : errors) {
-        errorMessages.add(e.getAsJsonObject().get("msg").getAsString());
-      }
-      return Joiner.on(", ").join(errorMessages);
-    } catch (Exception e) {
-      return null;
-    }
-  }
-
-  private static boolean isHtml(String responseContent) {
-    return StringUtils.stripToEmpty(responseContent).startsWith("<!DOCTYPE html>");
-  }
 }
index 7f619482ab16ec57942e44303df641ec640f4384..2161973c494ffa4909ceefae7560880c845f92e0 100644 (file)
@@ -36,9 +36,9 @@ public class ScannerWsClientProvider extends ProviderAdapter {
   static final String READ_TIMEOUT_SEC_PROPERTY = "sonar.ws.timeout";
   static final int DEFAULT_READ_TIMEOUT_SEC = 60;
 
-  private ScannerWsClient wsClient;
+  private DefaultScannerWsClient wsClient;
 
-  public synchronized ScannerWsClient provide(final RawScannerProperties scannerProps,
+  public synchronized DefaultScannerWsClient provide(final RawScannerProperties scannerProps,
     final EnvironmentInformation env, GlobalAnalysisMode globalMode, System2 system) {
     if (wsClient == null) {
       String url = defaultIfBlank(scannerProps.property("sonar.host.url"), CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE);
@@ -60,7 +60,7 @@ public class ScannerWsClientProvider extends ProviderAdapter {
         connectorBuilder.proxyCredentials(proxyUser, System.getProperty("http.proxyPassword"));
       }
 
-      wsClient = new ScannerWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null, globalMode);
+      wsClient = new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null, globalMode);
     }
     return wsClient;
   }
index d57b46c7994af7f056dcb990c492587b12cc1480..8c392cfed46c0cf0e5c02bb3b350e1b2394d195b 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.config.internal.MultivalueProperty.parseAsCsv;
+import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
 
 @Immutable
 public abstract class DefaultConfiguration implements Configuration {
index c5c1112317d02786aa09d63f8766c657feb2cd66..74684a0019be5b8cdc7f8da128a6fa82a9a2283e 100644 (file)
@@ -42,8 +42,8 @@ import org.sonar.duplications.index.CloneGroup;
 import org.sonar.duplications.index.ClonePart;
 import org.sonar.duplications.index.PackedMemoryCloneIndex.ResourceBlocks;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
-import org.sonar.scanner.fs.DefaultInputComponent;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputComponent;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Duplicate;
 import org.sonar.scanner.protocol.output.ScannerReport.Duplication;
index f40e5d107bdc520b879fab8d616c2eaa0fb50004..82ee99a37ee58d66dec61edceaeb6dcb873cc9f3 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 public class CpdSettings {
   private final Configuration settings;
index a66df96bbed5a78e37bbf9522d8f22a7e5d22b03..69645b6c05dd3620b83344a1c6f555b5c459c642 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 /**
  * Special case for Java that use a dedicated block indexer.
index 645d9fab4b103f8434b6f62a3914ddff1d26fe9e..44b419f26ff5783ea3867fb2dc09b5274ecca5d5 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.protocol.output.FileStructure;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.report.ReportPublisher;
index 364544377ed28d4ad13f7bb98195d81f2f453752..be9e3686cdf35433349e2d8e4b8d9f581e451c5a 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 public class DefaultCoverageBlock implements CoverageBlock {
 
index 960a6cf03b56834d561b32a294a12445518597ab..74113b9ed68de7e42f00136f2929d7d191e7c4d9 100644 (file)
@@ -32,7 +32,7 @@ import org.sonar.api.test.TestPlan;
 import org.sonar.api.test.Testable;
 import org.sonar.api.test.exception.CoverageAlreadyExistsException;
 import org.sonar.api.test.exception.IllegalDurationException;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 public class DefaultTestCase implements MutableTestCase {
 
index 20a0abfec50200440e32d473a5d5166fcea6ef38..5219368da91541db38d5dfeb6ae56605b3a5eaef 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 public class DefaultTestable implements MutableTestable {
 
index 615ebd2f5cf00077d282f87c27deca39fb4660de..c4c5286590728b355d62b6a0f9cfcd38b90210d5 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 public class TestPlanBuilder extends PerspectiveBuilder<MutableTestPlan> {
 
index 84f74e12ff5e8dfc74e2ad9cfe5e90b0533c5778..4498f0b4d9380deb89e366666d5f110c0fd46f88 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 public class TestableBuilder extends PerspectiveBuilder<MutableTestable> {
 
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/AbstractProjectOrModule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/AbstractProjectOrModule.java
deleted file mode 100644 (file)
index 9fc2d13..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultFileSystem.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultFileSystem.java
deleted file mode 100644 (file)
index 1c17296..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.scanner.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.scan.filesystem.PathResolver;
-import org.sonar.api.utils.PathUtils;
-import org.sonar.scanner.fs.predicates.DefaultFilePredicates;
-import org.sonar.scanner.fs.predicates.FileExtensionPredicate;
-import org.sonar.scanner.fs.predicates.OptimizedFilePredicateAdapter;
-
-/**
- * @since 4.2
- */
-public class DefaultFileSystem implements FileSystem {
-
-  private final Cache cache;
-  private final Path baseDir;
-  private Path workDir;
-  private Charset encoding;
-  protected final FilePredicates predicates;
-
-  /**
-   * Only for testing
-   */
-  public DefaultFileSystem(Path baseDir) {
-    this(baseDir, new MapCache());
-  }
-
-  /**
-   * Only for testing
-   */
-  public DefaultFileSystem(File baseDir) {
-    this(baseDir.toPath(), new MapCache());
-  }
-
-  protected DefaultFileSystem(Path baseDir, Cache cache) {
-    this.baseDir = baseDir;
-    this.cache = cache;
-    this.predicates = new DefaultFilePredicates(this.baseDir);
-  }
-
-  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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultIndexedFile.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultIndexedFile.java
deleted file mode 100644 (file)
index e52e0b4..0000000
+++ /dev/null
@@ -1,162 +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.scanner.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.batch.fs.internal.SensorStrategy;
-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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputComponent.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputComponent.java
deleted file mode 100644 (file)
index 11601e0..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputDir.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputDir.java
deleted file mode 100644 (file)
index 13eb77b..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputFile.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputFile.java
deleted file mode 100644 (file)
index c74f1c4..0000000
+++ /dev/null
@@ -1,440 +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.scanner.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 org.sonar.api.batch.fs.internal.Metadata;
-
-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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputModule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputModule.java
deleted file mode 100644 (file)
index a729bff..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.scanner.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.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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputProject.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultInputProject.java
deleted file mode 100644 (file)
index 9dcd025..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultTextPointer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultTextPointer.java
deleted file mode 100644 (file)
index 5cfc84f..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultTextRange.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/DefaultTextRange.java
deleted file mode 100644 (file)
index f83c330..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/FileMetadata.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/FileMetadata.java
deleted file mode 100644 (file)
index 1b98416..0000000
+++ /dev/null
@@ -1,162 +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.scanner.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.batch.fs.internal.Metadata;
-import org.sonar.scanner.fs.charhandler.CharHandler;
-import org.sonar.scanner.fs.charhandler.FileHashComputer;
-import org.sonar.scanner.fs.charhandler.LineCounter;
-import org.sonar.scanner.fs.charhandler.LineHashComputer;
-import org.sonar.scanner.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);
-    }
-  }
-}
index 9048824f0329ba4ef739ef453475eb9af1ad1322..ef1124cbcc9a2379b8c64f4fc79d5e5aadd318ce 100644 (file)
@@ -22,6 +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;
 
 @Immutable
 public interface InputModuleHierarchy {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/TestInputFileBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/TestInputFileBuilder.java
deleted file mode 100644 (file)
index 6764b61..0000000
+++ /dev/null
@@ -1,280 +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.scanner.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.batch.fs.internal.Metadata;
-import org.sonar.api.batch.fs.internal.SensorStrategy;
-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-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/CharHandler.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/CharHandler.java
deleted file mode 100644 (file)
index 737f6c2..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/FileHashComputer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/FileHashComputer.java
deleted file mode 100644 (file)
index 46229a5..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/IntArrayList.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/IntArrayList.java
deleted file mode 100644 (file)
index 1267414..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineCounter.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineCounter.java
deleted file mode 100644 (file)
index 7cac0f2..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineHashComputer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineHashComputer.java
deleted file mode 100644 (file)
index 5435499..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.scanner.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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineOffsetCounter.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/LineOffsetCounter.java
deleted file mode 100644 (file)
index 74b7f48..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/package-info.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/charhandler/package-info.java
deleted file mode 100644 (file)
index 4e5375f..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.scanner.fs.charhandler;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AbsolutePathPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AbsolutePathPredicate.java
deleted file mode 100644 (file)
index c55099a..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AbstractFilePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AbstractFilePredicate.java
deleted file mode 100644 (file)
index 4f69526..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AndPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/AndPredicate.java
deleted file mode 100644 (file)
index 0249642..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/DefaultFilePredicates.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/DefaultFilePredicates.java
deleted file mode 100644 (file)
index bcda1ac..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.scanner.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.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FalsePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FalsePredicate.java
deleted file mode 100644 (file)
index e76bb84..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FileExtensionPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FileExtensionPredicate.java
deleted file mode 100644 (file)
index 46f257f..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FilenamePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/FilenamePredicate.java
deleted file mode 100644 (file)
index a99d931..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/LanguagePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/LanguagePredicate.java
deleted file mode 100644 (file)
index 5492e22..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/NotPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/NotPredicate.java
deleted file mode 100644 (file)
index 5bc68ad..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.scanner.fs.predicates;
-
-import java.util.Arrays;
-import java.util.List;
-import org.sonar.api.batch.fs.FilePredicate;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.scanner.fs.predicates.AbstractFilePredicate;
-import org.sonar.scanner.fs.predicates.OperatorPredicate;
-
-/**
- * @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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OperatorPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OperatorPredicate.java
deleted file mode 100644 (file)
index c449309..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OptimizedFilePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OptimizedFilePredicate.java
deleted file mode 100644 (file)
index 9b5216d..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OptimizedFilePredicateAdapter.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OptimizedFilePredicateAdapter.java
deleted file mode 100644 (file)
index ba46aff..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OrPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/OrPredicate.java
deleted file mode 100644 (file)
index 2690a12..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/PathPatternPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/PathPatternPredicate.java
deleted file mode 100644 (file)
index 032d820..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.scanner.fs.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/RelativePathPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/RelativePathPredicate.java
deleted file mode 100644 (file)
index d79221e..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/StatusPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/StatusPredicate.java
deleted file mode 100644 (file)
index fb88b96..0000000
+++ /dev/null
@@ -1,43 +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.scanner.fs.predicates;
-
-import javax.annotation.Nullable;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.scanner.fs.predicates.AbstractFilePredicate;
-
-/**
- * @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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/TruePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/TruePredicate.java
deleted file mode 100644 (file)
index 562515c..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/TypePredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/TypePredicate.java
deleted file mode 100644 (file)
index 3cddc59..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/URIPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/fs/predicates/URIPredicate.java
deleted file mode 100644 (file)
index 9e25267..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/issue/AbstractDefaultIssue.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/AbstractDefaultIssue.java
deleted file mode 100644 (file)
index 4b13e20..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.scanner.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.scanner.sensor.DefaultStorable;
-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.utils.PathUtils;
-import org.sonar.scanner.fs.DefaultInputDir;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultInputProject;
-
-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;
-    }
-  }
-}
index 5485c348c8774a1399d52035ef60f00f5ec2e3ec..5d107da2d76180c9dcf5c0849163e4ded5cc3c08 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.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.fs.DefaultTextRange;
+import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultTextPointer;
+import org.sonar.api.impl.fs.DefaultTextRange;
 import org.sonar.scanner.protocol.output.ScannerReport.Issue;
 
 @ThreadSafe
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultIssue.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultIssue.java
deleted file mode 100644 (file)
index 154dfc9..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.scanner.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.rule.RuleKey;
-import org.sonar.scanner.fs.DefaultInputProject;
-
-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-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultIssueLocation.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultIssueLocation.java
deleted file mode 100644 (file)
index 33018bb..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.scanner.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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultNoSonarFilter.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultNoSonarFilter.java
deleted file mode 100644 (file)
index 00d3ba5..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.scanner.issue;
-
-import java.util.Set;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.issue.NoSonarFilter;
-import org.sonar.scanner.fs.DefaultInputFile;
-
-public class DefaultNoSonarFilter extends NoSonarFilter {
-  public NoSonarFilter noSonarInFile(InputFile inputFile, Set<Integer> noSonarLines) {
-    ((DefaultInputFile) inputFile).noSonarAt(noSonarLines);
-    return this;
-  }
-}
index 87a4846a81a5625143ce1a2d9a278095776b0a44..3b887b024efd43a4707ba31d4bce378756795014 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 import org.sonar.scanner.protocol.output.ScannerReport;
 
 /**
index ac02497f4745e1411764cad6581c646aebca3ee1..1bbf26f6bd1d825c8ae58205eef20cd41b63c4bd 100644 (file)
@@ -29,8 +29,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.scanner.fs.DefaultInputComponent;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputComponent;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.protocol.Constants.Severity;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.IssueLocation;
index e518408f13beb47ff2317a64f81aff2085f08cbc..3faefb38407da5c5e3688425e8fed53381f38e16 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.issue.DefaultFilterableIssue;
 import org.sonar.scanner.issue.ignore.pattern.IssueInclusionPatternInitializer;
 import org.sonar.scanner.issue.ignore.pattern.IssuePattern;
index 8d825944b849e2bccad4a74b8de86680831d7a6e..2a961ee65ad8595d4d7664712118022f2ea8d3ed 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.issue.DefaultFilterableIssue;
 
 public class IgnoreIssuesFilter implements IssueFilter {
index 4c3117835ca37de5481d520b4767ecdde25cde09..ad9b431b5d386e11af516d4180f49d97196b2d47 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.charhandler.CharHandler;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.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 2ab767f7f3b7e9052b5f988b5a585d6531f1ffb8..345db834790be4dd43222754d714cfb4c1166525 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.charhandler.CharHandler;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.charhandler.CharHandler;
 import org.sonar.scanner.issue.ignore.pattern.LineRange;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader.DoubleRegexpMatcher;
 
index c75da29f0ed1bac3bf9464b76330e8534cdfd2f5..0e851054801b99d6fe4b2e768c5a7c3cae13857a 100644 (file)
@@ -37,8 +37,8 @@ import org.sonar.api.batch.fs.TextRange;
 import org.sonar.api.batch.sensor.highlighting.TypeOfText;
 import org.sonar.api.scanner.fs.InputProject;
 import org.sonar.core.util.CloseableIterator;
-import org.sonar.scanner.fs.DefaultInputComponent;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputComponent;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Component;
 import org.sonar.scanner.protocol.output.ScannerReport.Symbol;
index dfe4993d31b0a5defccc80f486e39d2359969d60..72837700b07c7bc8faea3996ce09162d2d6844d9 100644 (file)
@@ -27,17 +27,17 @@ import org.sonar.api.SonarRuntime;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.DateUtils;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 
 import static org.apache.commons.lang.StringUtils.trimToEmpty;
 
 public class DefaultServer extends Server {
 
   private final Configuration settings;
-  private final ScannerWsClient client;
+  private final DefaultScannerWsClient client;
   private final SonarRuntime runtime;
 
-  public DefaultServer(Configuration settings, ScannerWsClient client, SonarRuntime runtime) {
+  public DefaultServer(Configuration settings, DefaultScannerWsClient client, SonarRuntime runtime) {
     this.settings = settings;
     this.client = client;
     this.runtime = runtime;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/DefaultPostJobDescriptor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/DefaultPostJobDescriptor.java
deleted file mode 100644 (file)
index 1292e10..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.scanner.postjob;
-
-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;
-  }
-
-}
index cd68e1694feddb4d92e5e56ddc062cbb5a4be85f..ea9acd22d342bd08556c1b525401c5a5f95f31c7 100644 (file)
@@ -22,6 +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;
 
 public class PostJobOptimizer {
 
index 60ea28821632395c9fa686061adbb996d0d0dd20..9df6f4cd892de46504322f15cc29ffa8e8537691 100644 (file)
@@ -21,6 +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;
 
 public class PostJobWrapper {
 
index f0f8991c073d91cdeabf87d1452f900fe503d13a..174659fe796844fe7edee1fe4eacc7c85b990d59 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.report;
 
 import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.scanner.rule.DefaultActiveRule;
+import org.sonar.api.batch.rule.DefaultActiveRule;
 import org.sonar.scanner.protocol.Constants;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
index 25780591679b34afb5600d1c50c3810c2412268b..5c6daad40b86ce76e7531ad00873dfaecbfc7b6b 100644 (file)
@@ -30,13 +30,13 @@ import java.util.Map;
 import java.util.TreeSet;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
-import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
+import org.sonar.api.impl.fs.AbstractProjectOrModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.api.utils.System2;
 import org.sonar.core.platform.PluginInfo;
 import org.sonar.scanner.bootstrap.GlobalServerSettings;
 import org.sonar.scanner.bootstrap.ScannerPluginRepository;
+import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.ProjectServerSettings;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
index 00d8bed5abfb56ef9bb90bf57fa77064bc297a4f..db7d22baf08c85920c38fe317a7451701a6fb202 100644 (file)
@@ -29,14 +29,14 @@ 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputProject;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 import org.sonar.scanner.scm.ScmConfiguration;
-import org.sonar.scanner.util.ScannerUtils;
+import org.sonar.api.impl.utils.ScannerUtils;
 
 public class ChangedLinesPublisher implements ReportPublisherStep {
   private static final Logger LOG = Loggers.get(ChangedLinesPublisher.class);
index 597785f763258caac0064291e78aeb5f95198fb4..b66fc8e8a93f630d702d2a76509ce261bde1a65d 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.scanner.fs.AbstractProjectOrModule;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.AbstractProjectOrModule;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.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 be1e838b810f36770511b83232cda60bf8f4896a..f238735d3cb7eb0bd305e2840a13f1fa7e95778b 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.scanner.fs.AbstractProjectOrModule;
-import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.AbstractProjectOrModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Metadata.BranchType;
index c2afdc1baf275c75419c080caac4eeda8d6ba277..46078b34f84f4a624e932f26467fe4eeb623986e 100644 (file)
@@ -43,7 +43,7 @@ import org.sonar.api.utils.ZipUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
@@ -72,7 +72,7 @@ public class ReportPublisher implements Startable {
   private static final String ID = "id";
   private static final String RESOLVED = "resolved";
 
-  private final ScannerWsClient wsClient;
+  private final DefaultScannerWsClient wsClient;
   private final AnalysisContextReportPublisher contextPublisher;
   private final InputModuleHierarchy moduleHierarchy;
   private final GlobalAnalysisMode analysisMode;
@@ -86,7 +86,7 @@ public class ReportPublisher implements Startable {
   private ScannerReportWriter writer;
   private ScannerReportReader reader;
 
-  public ReportPublisher(ScanProperties properties, ScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher,
+  public ReportPublisher(ScanProperties properties, DefaultScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher,
     InputModuleHierarchy moduleHierarchy, GlobalAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers, BranchConfiguration branchConfiguration) {
     this.wsClient = wsClient;
     this.server = server;
@@ -195,7 +195,7 @@ public class ReportPublisher implements Startable {
     try {
       response = wsClient.call(post).failIfNotSuccessful();
     } catch (HttpException e) {
-      throw MessageException.of(String.format("Failed to upload report - %s", ScannerWsClient.createErrorMessage(e)));
+      throw MessageException.of(String.format("Failed to upload report - %s", DefaultScannerWsClient.createErrorMessage(e)));
     }
 
     try (InputStream protobuf = response.contentStream()) {
index 765ac95da04c739e8e7e7a60f74643be57a9ce29..f18549f81df5088ba7a43a9889a9c4e59d9f5420 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
index f04f204bf2b82f6836464ff444929f4ed0ac93ef..2aa1802f814580a33322465fa1b6399518e93bc8 100644 (file)
@@ -24,16 +24,16 @@ 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.test.MutableTestPlan;
 import org.sonar.api.test.TestCase;
 import org.sonar.api.test.TestCase.Status;
 import org.sonar.scanner.deprecated.test.TestPlanBuilder;
-import org.sonar.scanner.fs.DefaultInputComponent;
-import org.sonar.scanner.fs.DefaultInputFile;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
-import org.sonar.scanner.sensor.DefaultMeasure;
 
 import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS;
 import static org.sonar.api.measures.CoreMetrics.TESTS;
index 64482589fec0499830167d6198a518432561347e..7afc0c68587a806827f0984fddd5229d7da62493 100644 (file)
@@ -25,16 +25,16 @@ import java.util.ArrayList;
 import java.util.List;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.measures.Metric.ValueType;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonar.scanner.protocol.GsonHelper;
 import org.sonarqube.ws.client.GetRequest;
 
 public class DefaultMetricsRepositoryLoader implements MetricsRepositoryLoader {
 
   private static final String METRICS_SEARCH_URL = "/api/metrics/search?f=name,description,direction,qualitative,custom&ps=500&p=";
-  private ScannerWsClient wsClient;
+  private DefaultScannerWsClient wsClient;
 
-  public DefaultMetricsRepositoryLoader(ScannerWsClient wsClient) {
+  public DefaultMetricsRepositoryLoader(DefaultScannerWsClient wsClient) {
     this.wsClient = wsClient;
   }
 
index f5136784e434a127d6a9974e7d97bd8806df50c3..3c7e7ad548413a3516d16c027b12ae1971d8dbfc 100644 (file)
@@ -28,8 +28,8 @@ import java.util.Map;
 import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
-import org.sonar.scanner.util.ScannerUtils;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
+import org.sonar.api.impl.utils.ScannerUtils;
 import org.sonarqube.ws.Batch.WsProjectResponse;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.HttpException;
@@ -38,9 +38,9 @@ import org.sonarqube.ws.client.WsResponse;
 public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoader {
   private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectRepositoriesLoader.class);
   private static final String BATCH_PROJECT_URL = "/batch/project.protobuf";
-  private final ScannerWsClient wsClient;
+  private final DefaultScannerWsClient wsClient;
 
-  public DefaultProjectRepositoriesLoader(ScannerWsClient wsClient) {
+  public DefaultProjectRepositoriesLoader(DefaultScannerWsClient wsClient) {
     this.wsClient = wsClient;
   }
 
index 361eeab3e6d1629c2c8103b41b5174f0539d4f8e..7bf41b77a93f6a3a0feb28f27adac92ab8dd0b37 100644 (file)
@@ -28,7 +28,7 @@ import java.util.Map;
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
 import org.sonar.api.utils.MessageException;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
@@ -37,15 +37,15 @@ import org.sonarqube.ws.client.HttpException;
 
 import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toMap;
-import static org.sonar.scanner.util.ScannerUtils.encodeForUrl;
+import static org.sonar.api.impl.utils.ScannerUtils.encodeForUrl;
 
 public class DefaultQualityProfileLoader implements QualityProfileLoader {
   private static final String WS_URL = "/api/qualityprofiles/search.protobuf";
 
-  private final ScannerWsClient wsClient;
+  private final DefaultScannerWsClient wsClient;
   private final ScanProperties properties;
 
-  public DefaultQualityProfileLoader(ScanProperties properties, ScannerWsClient wsClient) {
+  public DefaultQualityProfileLoader(ScanProperties properties, DefaultScannerWsClient wsClient) {
     this.properties = properties;
     this.wsClient = wsClient;
   }
@@ -69,10 +69,10 @@ public class DefaultQualityProfileLoader implements QualityProfileLoader {
         if (tryLoadDefault) {
           return loadDefault();
         } else {
-          throw MessageException.of(errorMsg.get() + ": " + ScannerWsClient.createErrorMessage(e));
+          throw MessageException.of(errorMsg.get() + ": " + DefaultScannerWsClient.createErrorMessage(e));
         }
       }
-      throw new IllegalStateException(errorMsg.get() + ": " + ScannerWsClient.createErrorMessage(e));
+      throw new IllegalStateException(errorMsg.get() + ": " + DefaultScannerWsClient.createErrorMessage(e));
     } catch (MessageException e) {
       throw e;
     } catch (Exception e) {
index d1a7a30080ca7b0464087129c3e6a544de654e77..ad817fd2a4776928e38768f7ee825db9fe033131 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.scanner.repository;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.concurrent.Immutable;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 @Immutable
 public abstract class ProjectRepositories {
index 797acbfcdb9e93d446d8c4f3492a775519cf9ac0..795a217b5a1e82ce7d3702b97a71736dab7769b8 100644 (file)
@@ -34,8 +34,8 @@ import org.apache.commons.lang.StringEscapeUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.api.utils.log.Profiler;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
-import org.sonar.scanner.util.ScannerUtils;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
+import org.sonar.api.impl.utils.ScannerUtils;
 import org.sonarqube.ws.Settings;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.HttpException;
@@ -43,9 +43,9 @@ import org.sonarqube.ws.client.HttpException;
 public abstract class AbstractSettingsLoader {
 
   private static final Logger LOG = Loggers.get(AbstractSettingsLoader.class);
-  private final ScannerWsClient wsClient;
+  private final DefaultScannerWsClient wsClient;
 
-  public AbstractSettingsLoader(final ScannerWsClient wsClient) {
+  public AbstractSettingsLoader(final DefaultScannerWsClient wsClient) {
     this.wsClient = wsClient;
   }
 
index cd6165637307a0c8e12effcdfc63cceadf38c8ed..8e3e34cf90a388d3da7a37c2fed3c9415d71ca77 100644 (file)
 package org.sonar.scanner.repository.settings;
 
 import java.util.Map;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 
 public class DefaultGlobalSettingsLoader extends AbstractSettingsLoader implements GlobalSettingsLoader {
 
-  public DefaultGlobalSettingsLoader(final ScannerWsClient wsClient) {
+  public DefaultGlobalSettingsLoader(final DefaultScannerWsClient wsClient) {
     super(wsClient);
   }
 
index 4274772cc8c17da21189ee53861721ccb207bb0e..32d41243f93dbc768cb34ed0864ed0b2ea9746cf 100644 (file)
@@ -21,12 +21,12 @@ package org.sonar.scanner.repository.settings;
 
 import java.util.Map;
 import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 
 public class DefaultProjectSettingsLoader extends AbstractSettingsLoader implements ProjectSettingsLoader {
   private final ProcessedScannerProperties scannerProperties;
 
-  public DefaultProjectSettingsLoader(final ScannerWsClient wsClient, final ProcessedScannerProperties scannerProperties) {
+  public DefaultProjectSettingsLoader(final DefaultScannerWsClient wsClient, final ProcessedScannerProperties scannerProperties) {
     super(wsClient);
     this.scannerProperties = scannerProperties;
   }
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesBuilder.java
deleted file mode 100644 (file)
index ce58858..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.scanner.rule;
-
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.rule.RuleKey;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * 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());
-  }
-}
index e9bd8897dc8f3c5f1562d1f6fe087725ad9f2a42..0cf793876f4368c22d8f29eeaa7e6d52526efcca 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.scanner.rule;
 
 import java.util.List;
+import org.sonar.api.batch.rule.LoadedActiveRule;
 
 public interface ActiveRulesLoader {
   List<LoadedActiveRule> load(String qualityProfileKey);
index f918a847f2bbac685cc12365d2a7ab1425a52bd9..dbf8ec440a230ffb3c8d9efe84f0e7c6bdc74f15 100644 (file)
@@ -27,6 +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.LoadedActiveRule;
+import org.sonar.api.batch.rule.NewActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRule.java
deleted file mode 100644 (file)
index 68bdf1e..0000000
+++ /dev/null
@@ -1,101 +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.scanner.rule;
-
-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;
-
-  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-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRules.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRules.java
deleted file mode 100644 (file)
index 77a2787..0000000
+++ /dev/null
@@ -1,83 +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.scanner.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.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;
-  }
-}
index 3f6cb897aafe9a39b18e98742a7a2a4a852d1205..e7d2cb63f86bb00c5fe3ddc8ee7870152d4f3cfe 100644 (file)
@@ -26,9 +26,11 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.io.IOUtils;
-import org.sonar.api.rule.RuleKey;
 import org.sonar.scanner.bootstrap.ScannerWsClient;
-import org.sonar.scanner.util.ScannerUtils;
+import org.sonar.api.impl.utils.ScannerUtils;
+import org.sonar.api.batch.rule.LoadedActiveRule;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.DateUtils;
 import org.sonarqube.ws.Rules;
 import org.sonarqube.ws.Rules.Active;
 import org.sonarqube.ws.Rules.Active.Param;
@@ -37,9 +39,6 @@ import org.sonarqube.ws.Rules.Rule;
 import org.sonarqube.ws.Rules.SearchResponse;
 import org.sonarqube.ws.client.GetRequest;
 
-import static org.sonar.api.utils.DateUtils.dateToLong;
-import static org.sonar.api.utils.DateUtils.parseDateTime;
-
 public class DefaultActiveRulesLoader implements ActiveRulesLoader {
   private static final String RULES_SEARCH_URL = "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt,updatedAt&activation=true";
 
@@ -106,8 +105,8 @@ public class DefaultActiveRulesLoader implements ActiveRulesLoader {
       loadedRule.setRuleKey(RuleKey.parse(r.getKey()));
       loadedRule.setName(r.getName());
       loadedRule.setSeverity(active.getSeverity());
-      loadedRule.setCreatedAt(dateToLong(parseDateTime(active.getCreatedAt())));
-      loadedRule.setUpdatedAt(dateToLong(parseDateTime(active.getUpdatedAt())));
+      loadedRule.setCreatedAt(DateUtils.dateToLong(DateUtils.parseDateTime(active.getCreatedAt())));
+      loadedRule.setUpdatedAt(DateUtils.dateToLong(DateUtils.parseDateTime(active.getUpdatedAt())));
       loadedRule.setLanguage(r.getLang());
       loadedRule.setInternalKey(r.getInternalKey());
       if (r.hasTemplateKey()) {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRule.java
deleted file mode 100644 (file)
index d53859a..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.scanner.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.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;
-
-  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-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRuleParam.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRuleParam.java
deleted file mode 100644 (file)
index 31fed46..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.scanner.rule;
-
-import org.sonar.api.batch.rule.RuleParam;
-
-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-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRules.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRules.java
deleted file mode 100644 (file)
index efcc710..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.scanner.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.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());
-  }
-}
index 61a97e00921543fd2ad441fc5b96b74d0143f4b8..cc745877ae928fa7568c0b3adf0545b4e2e72eb5 100644 (file)
@@ -23,7 +23,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 import org.apache.commons.io.IOUtils;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonarqube.ws.Rules.ListResponse;
 import org.sonarqube.ws.Rules.ListResponse.Rule;
 import org.sonarqube.ws.client.GetRequest;
@@ -31,9 +31,9 @@ import org.sonarqube.ws.client.GetRequest;
 public class DefaultRulesLoader implements RulesLoader {
   private static final String RULES_SEARCH_URL = "/api/rules/list.protobuf";
 
-  private final ScannerWsClient wsClient;
+  private final DefaultScannerWsClient wsClient;
 
-  public DefaultRulesLoader(ScannerWsClient wsClient) {
+  public DefaultRulesLoader(DefaultScannerWsClient wsClient) {
     this.wsClient = wsClient;
   }
 
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/LoadedActiveRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/LoadedActiveRule.java
deleted file mode 100644 (file)
index cb50dad..0000000
+++ /dev/null
@@ -1,111 +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.scanner.rule;
-
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.rule.RuleKey;
-
-public class LoadedActiveRule {
-  private RuleKey ruleKey;
-  private String severity;
-  private String name;
-  private String language;
-  private Map<String, String> params;
-  private long createdAt;
-  private long updatedAt;
-  private String templateRuleKey;
-  private String internalKey;
-
-  public RuleKey getRuleKey() {
-    return ruleKey;
-  }
-
-  public void setRuleKey(RuleKey ruleKey) {
-    this.ruleKey = ruleKey;
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  public String getSeverity() {
-    return severity;
-  }
-
-  public void setSeverity(String severity) {
-    this.severity = severity;
-  }
-
-  public String getLanguage() {
-    return language;
-  }
-
-  public void setLanguage(String language) {
-    this.language = language;
-  }
-
-  public Map<String, String> getParams() {
-    return params;
-  }
-
-  public void setParams(Map<String, String> params) {
-    this.params = params;
-  }
-
-  public long getCreatedAt() {
-    return createdAt;
-  }
-
-  public void setCreatedAt(long createdAt) {
-    this.createdAt = createdAt;
-  }
-
-  public long getUpdatedAt() {
-    return updatedAt;
-  }
-
-  public void setUpdatedAt(long updatedAt) {
-    this.updatedAt = updatedAt;
-  }
-
-  @CheckForNull
-  public String getTemplateRuleKey() {
-    return templateRuleKey;
-  }
-
-  public void setTemplateRuleKey(@Nullable String templateRuleKey) {
-    this.templateRuleKey = templateRuleKey;
-  }
-
-  public String getInternalKey() {
-    return internalKey;
-  }
-
-  public void setInternalKey(String internalKey) {
-    this.internalKey = internalKey;
-  }
-
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/NewActiveRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/NewActiveRule.java
deleted file mode 100644 (file)
index 10867a5..0000000
+++ /dev/null
@@ -1,130 +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.scanner.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 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-scanner-engine/src/main/java/org/sonar/scanner/rule/NewRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/NewRule.java
deleted file mode 100644 (file)
index 179768d..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/rule/NewRuleParam.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/NewRuleParam.java
deleted file mode 100644 (file)
index 9fa4825..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.scanner.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;
-  }
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesBuilder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesBuilder.java
deleted file mode 100644 (file)
index 3d1ccb3..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.scanner.rule;
-
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.rule.RuleKey;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 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());
-  }
-}
index a0c89c2d6f039b60f1bd88efe793a00815014c7c..3b365ac3c718cf25effe1dd758d197b4d4ec9e64 100644 (file)
@@ -21,7 +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.Rules;
+import org.sonar.api.impl.rule.RulesBuilder;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
index aa6cbeb0db1d82a28492249c73c5b1f64a06c8c1..108a6dc72857693fb835797cd65a02f0a3857c22 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.scanner.fs.AbstractProjectOrModule;
-import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.AbstractProjectOrModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 @Immutable
index da0b8781ddecc176105a6b148339609fb3ceb4ba..ef806c5b2ab8bfe0f956b790c09484adfe640a35 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.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputProject;
 import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
 
 public class InputModuleHierarchyProvider extends ProviderAdapter {
index 1219f2871dd5decd2e1d39690182d82c8fc2ab87..9500e47d8f75d43d9b23ca3152516d6ec01d57b1 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
 
 public class InputProjectProvider extends ProviderAdapter {
index 21d241c23f4bea5e498271499e352bf4486ded7b..dab9cc531fd9bb93642fe98ea8d437c11e1ca2a5 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 
 public class ModuleConfigurationProvider extends ProviderAdapter {
 
index 1bc1611097fa94ee7c05b1e151f3d1c3fa26d976..c307a20aafc013e1c5a5280cba5701bf5e6544b0 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan;
 
 import org.picocontainer.Startable;
-import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
index 1a7a78f93cf889ffd9b2aa6e8da206d39227be7b..f573dd47e4dcedfc7acb3a5b56a09d2db0861ecf 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
 import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore;
 import org.sonar.scanner.sensor.ModuleSensorContext;
index 0d17b4a81142ca226f4d2456dbca7bc65e905dab..1903ad736eb0f1e89d9eda59dea0fbd24b176cda 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 public class ProjectConfigurationProvider extends ProviderAdapter {
 
index 9bf6bf731152ec42c679245e956c0ee2b19f2321..d024d47f7cbc9aa142a4187b3b510691dd6eac8d 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.scanner.fs.AbstractProjectOrModule;
+import org.sonar.api.impl.fs.AbstractProjectOrModule;
 
 public class ProjectLock implements Startable {
   private final DirectoryLock lock;
index 01f181d55f05c8e90e1971d0312650bd4f52b762..e15525df2d2472c402d96ef704602febb2767281 100644 (file)
@@ -49,11 +49,11 @@ import org.sonar.core.config.IssueExclusionProperties;
 import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
 import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
 import org.sonar.scanner.issue.ignore.pattern.IssueInclusionPatternInitializer;
-import org.sonar.scanner.util.ScannerUtils;
+import org.sonar.api.impl.utils.ScannerUtils;
 
 import static java.util.Arrays.asList;
 import static java.util.stream.Collectors.toList;
-import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
+import static org.sonar.api.impl.config.MultivalueProperty.parseAsCsv;
 
 /**
  * Class that creates a project definition based on a set of properties.
index 8cd93d031c46686fb5dbe0199744d349f8c08fc9..3fd76637dd51faa5e5a8b773544d4d81eac26a53 100644 (file)
@@ -23,8 +23,11 @@ import com.google.common.annotations.VisibleForTesting;
 import javax.annotation.Nullable;
 import org.sonar.api.SonarEdition;
 import org.sonar.api.SonarRuntime;
-import org.sonar.api.batch.fs.internal.SensorStrategy;
 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.resources.Languages;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.scan.filesystem.PathResolver;
@@ -63,10 +66,7 @@ import org.sonar.scanner.cpd.CpdSettings;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
 import org.sonar.scanner.deprecated.test.TestPlanBuilder;
 import org.sonar.scanner.deprecated.test.TestableBuilder;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.FileMetadata;
 import org.sonar.scanner.fs.InputModuleHierarchy;
-import org.sonar.scanner.issue.DefaultNoSonarFilter;
 import org.sonar.scanner.issue.IssueFilters;
 import org.sonar.scanner.issue.IssuePublisher;
 import org.sonar.scanner.issue.ignore.EnforceIssuesFilter;
index 2fa3bbeaf02374b2c58658eb283f47b1ad703d30..6beb97470af3cb7f854766405d76d937970212eb 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 import static org.sonar.core.config.ScannerProperties.BRANCH_NAME;
 import static org.sonar.core.config.ScannerProperties.ORGANIZATION;
index 8c5b01e4b2bd24249ceb7a4f7d7dad16172ae8a4..03b39315cc08fc3467701bcf502aa812d4b19be6 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 /**
index 1bcbad7f75a86151948321bf0b033b68705d2699..495b65448d4d5bdca0900f5f1d8dd6efe7008041 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 
 import static java.util.stream.Collectors.toList;
 
index 9a348fee7f50e8e6fd71f8a45d40f6b945fd5a6d..65aca8bd046463d5897dc2200146bf6af292e692 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.batch.fs.internal.PathPattern;
+import org.sonar.api.impl.fs.PathPattern;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 
index 6c1bb65332ad6914db14c8264031ecbc657a7f3a..299cb5a268c7fadeacce2dca2f3d65b0e36538df 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan.filesystem;
 
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.scanner.fs.predicates.AbstractFilePredicate;
+import org.sonar.api.impl.fs.predicates.AbstractFilePredicate;
 
 /**
  * Additional {@link org.sonar.api.batch.fs.FilePredicate}s that are
index d25948764dd70a2e9cb0886f818658cfafa98f13..3792a52e8a2f36dc1e50a89bb6828ae9d43f6769 100644 (file)
 package org.sonar.scanner.scan.filesystem;
 
 import com.google.common.annotations.VisibleForTesting;
-import org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultFileSystem;
+import org.sonar.api.impl.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.predicates.DefaultFilePredicates;
 
 public class DefaultModuleFileSystem extends DefaultFileSystem {
 
   public DefaultModuleFileSystem(ModuleInputComponentStore moduleInputFileCache, DefaultInputModule module) {
-    super(module.getBaseDir(), moduleInputFileCache);
+    super(module.getBaseDir(), moduleInputFileCache, new DefaultFilePredicates(module.getBaseDir()));
     initFields(module);
   }
 
index 294b0b946d118bb09be5b3c92f90ad2d56b6ede3..d7892ce887be2f4aba0d8ad8d75f3dc83b49d822 100644 (file)
 package org.sonar.scanner.scan.filesystem;
 
 import com.google.common.annotations.VisibleForTesting;
-import org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultFileSystem;
+import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.predicates.DefaultFilePredicates;
 
 public class DefaultProjectFileSystem extends DefaultFileSystem {
 
   public DefaultProjectFileSystem(InputComponentStore inputComponentStore, DefaultInputProject project) {
-    super(project.getBaseDir(), inputComponentStore);
+    super(project.getBaseDir(), inputComponentStore, new DefaultFilePredicates(project.getBaseDir()));
     setFields(project);
   }
 
index 56c2133396229915194fcf772c881369f0828ede..c01df402b0043b3269c2748ee3a527bd49e131cb 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.batch.fs.internal.SensorStrategy;
+import org.sonar.api.impl.fs.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.scanner.fs.DefaultIndexedFile;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultInputProject;
+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.scanner.issue.ignore.scanner.IssueExclusionsLoader;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.util.ProgressReport;
index 4eab927136dd9cbae6c2233ae4298a8a6e0e013a..eb33beb7e534c24089601f91b5ce414a2d812ba5 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.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.predicates.FileExtensionPredicate;
+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.scanner.scan.branch.BranchConfiguration;
 
 /**
index 57fbb86e23d39b8bab80d11e81583a3a0c5c97e0..7b699f2befd9a8292ac381e2785ed2a34a24edf6 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.batch.fs.internal.PathPattern;
+import org.sonar.api.impl.fs.PathPattern;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.repository.language.Language;
index 2da2f6db0c411627904e2b8837eb7efed375ba91..c15c9cdb5c6a638b76d55a1e76e93a3ca6b46087 100644 (file)
@@ -23,11 +23,11 @@ import com.google.common.annotations.VisibleForTesting;
 import java.io.InputStream;
 import java.nio.charset.Charset;
 import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.Metadata;
+import org.sonar.api.impl.fs.Metadata;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.FileMetadata;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.FileMetadata;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader;
 
 public class MetadataGenerator {
index 3ef961f83e2cd732048bd4aeb90ddc9d724c9824..2eb7d6805f4706052df194727e1b32a82ea2b455 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan.filesystem;
 
 import javax.annotation.concurrent.Immutable;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.scan.ModuleConfiguration;
 
 @Immutable
index e6d52849c6393b7e899ca355c09a2c88a17638d9..23d7e257731ea697f760219f518f560d60263ba0 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.batch.fs.internal.SensorStrategy;
-import org.sonar.scanner.fs.DefaultFileSystem;
+import org.sonar.api.impl.fs.SensorStrategy;
+import org.sonar.api.impl.fs.DefaultFileSystem;
 
 @ScannerSide
 public class ModuleInputComponentStore extends DefaultFileSystem.Cache {
index 4ab146afb275a80a48d69b71da35e6b64c3a924c..e52ab6cc1bb16198c3956e62d487232087d42c2c 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.scan.filesystem;
 
 import javax.annotation.concurrent.Immutable;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.scan.ProjectConfiguration;
 
 @Immutable
index 118b3eb5567c687963cee9dca3bab464f7998a93..b5633d772ebbd7e2ba3d0baba16a4b11cd9defcf 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.ModuleConfiguration;
 import org.sonar.scanner.scan.ModuleConfigurationProvider;
index 2cd3f8d5240b96fd5a2382531260d08a6c362ba7..9de8b028234a559286f2d7a7d03f5cd6fccea674 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.repository.FileData;
 import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
 import org.sonar.scanner.scm.ScmChangedFiles;
index e2742ea4d3a86245b15b92d814485120f18603b8..885de1be663e256cddde862ea9744422ab330b95 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.batch.scm.BlameCommand.BlameOutput;
 import org.sonar.api.batch.scm.BlameLine;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.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 6e93b9d4ad64d1a5189d7ded0a279985c7f6115d..4c65b2843e8067b0a5db5d1f60c2356a54b10435 100644 (file)
@@ -27,9 +27,9 @@ 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonar.scanner.util.ScannerUtils;
+import org.sonar.api.impl.utils.ScannerUtils;
 
 public class ScmChangedFilesProvider extends ProviderAdapter {
   private static final Logger LOG = Loggers.get(ScmChangedFilesProvider.class);
index 7b048096dab308213e5f5f314791181b34250e31..834d224ec820db108dd2649195d3754f8eba1ce2 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.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 95b473e05ceb46b0edde47d0f48ccf020151c828..cc089182c6bc122a17b8c6c8949e7c4563563b3b 100644 (file)
@@ -25,6 +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;
 
 public abstract class AbstractSensorOptimizer {
 
index caba9bc9101491ef5cd2694a7dae12c9632896a9..d5109c87943246cbf73cef1ed0a55b91be38825e 100644 (file)
@@ -20,6 +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.scanner.sensor.ProjectSensor;
 
 public abstract class AbstractSensorWrapper<G extends ProjectSensor> {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAdHocRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAdHocRule.java
deleted file mode 100644 (file)
index 1dde73e..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAnalysisError.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAnalysisError.java
deleted file mode 100644 (file)
index 3da46d8..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultCoverage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultCoverage.java
deleted file mode 100644 (file)
index 5a2f048..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.scanner.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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultCpdTokens.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultCpdTokens.java
deleted file mode 100644 (file)
index d470ab7..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.scanner.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.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.scanner.fs.DefaultInputFile;
-
-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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultExternalIssue.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultExternalIssue.java
deleted file mode 100644 (file)
index 7141a3e..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.scanner.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.rule.RuleKey;
-import org.sonar.api.rules.RuleType;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.issue.AbstractDefaultIssue;
-
-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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultHighlighting.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultHighlighting.java
deleted file mode 100644 (file)
index 0f97280..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.scanner.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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultMeasure.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultMeasure.java
deleted file mode 100644 (file)
index 1ad7b83..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorDescriptor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorDescriptor.java
deleted file mode 100644 (file)
index 1bb7466..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.scanner.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;
-  }
-
-}
index 13b72b07f7b1a8538744cb1562cd447347e455c7..8cece1eba14abdd82b53bcdd506e77bd77feef61 100644 (file)
@@ -46,6 +46,15 @@ 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.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;
@@ -55,9 +64,6 @@ import org.sonar.core.util.CloseableIterator;
 import org.sonar.duplications.block.Block;
 import org.sonar.duplications.internal.pmd.PmdBlockChunker;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
-import org.sonar.scanner.fs.DefaultInputComponent;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
 import org.sonar.scanner.issue.IssuePublisher;
 import org.sonar.scanner.protocol.Constants;
 import org.sonar.scanner.protocol.output.FileStructure;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSignificantCode.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSignificantCode.java
deleted file mode 100644 (file)
index 04ff5f1..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultStorable.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultStorable.java
deleted file mode 100644 (file)
index 23b989c..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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSymbolTable.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSymbolTable.java
deleted file mode 100644 (file)
index ca8b162..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.scanner.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.scanner.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-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java
deleted file mode 100644 (file)
index 472537d..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.scanner.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);
-  }
-}
index 1e8f6009f8d5b28b9e73751d758a9a3c0c3f4ffb..783c4b2720f74d404b1e6402b53bee2d243b1df3 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 @ThreadSafe
 public class ModuleSensorContext extends ProjectSensorContext {
index ec3d21f661352af8b76664ba8b83c747205e40e3..7c627f3d50202d4441d9f806e053f9cd9db5fa1a 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.batch.fs.internal.SensorStrategy;
+import org.sonar.api.impl.fs.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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 public class ModuleSensorsExecutor {
index 8a24451032828316c6714c93cb0f44d01978135c..eae821692a052a1de9522b3c3f98a18b8279491e 100644 (file)
@@ -40,11 +40,19 @@ 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.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.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.issue.DefaultIssue;
 import org.sonar.scanner.sensor.noop.NoOpNewAnalysisError;
 
 @ThreadSafe
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorContextTester.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorContextTester.java
deleted file mode 100644 (file)
index e3ffc32..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.scanner.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.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 org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.issue.DefaultIssue;
-import org.sonar.scanner.rule.ActiveRulesBuilder;
-
-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-scanner-engine/src/main/java/org/sonar/scanner/sensor/SyntaxHighlightingRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SyntaxHighlightingRule.java
deleted file mode 100644 (file)
index cded69e..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.scanner.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);
-  }
-}
index 54bf590d75884848085af50875b521e5c83965bc..20b3d3e586952ec7fc5b304084f34a7605d73ace 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.report.ReportPublisher;
 
 @Phase(name = Phase.Name.POST)
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/util/ScannerUtils.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/util/ScannerUtils.java
deleted file mode 100644 (file)
index d22f0ea..0000000
+++ /dev/null
@@ -1,73 +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.scanner.util;
-
-import com.google.common.base.Strings;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-
-public class ScannerUtils {
-
-  private ScannerUtils() {
-  }
-
-  /**
-   * Clean provided string to remove chars that are not valid as file name.
-   * @param projectKey e.g. my:file
-   */
-  public static String cleanKeyForFilename(String projectKey) {
-    String cleanKey = StringUtils.deleteWhitespace(projectKey);
-    return StringUtils.replace(cleanKey, ":", "_");
-  }
-
-  public static String encodeForUrl(@Nullable String url) {
-    try {
-      return URLEncoder.encode(Strings.nullToEmpty(url), "UTF-8");
-
-    } catch (UnsupportedEncodingException e) {
-      throw new IllegalStateException("Encoding not supported", e);
-    }
-  }
-
-  public static String describe(Object o) {
-    try {
-      if (o.getClass().getMethod("toString").getDeclaringClass() != Object.class) {
-        String str = o.toString();
-        if (str != null) {
-          return str;
-        }
-      }
-    } catch (Exception e) {
-      // fallback
-    }
-
-    return o.getClass().getName();
-  }
-
-  public static String pluralize(String str, int i) {
-    if (i == 1) {
-      return str;
-    }
-    return str + "s";
-  }
-
-}
index f6e59a75f9a0f15234d476c41ad3741616146c13..5f789670c6a40e5eb4a99b3ce8a0dfaee1286564 100644 (file)
@@ -27,10 +27,10 @@ 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.measures.CoreMetrics;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultMeasure;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
index a882ca0afcf865369b2b9da60c595bb7791364c4..b43f101cdd1e3343f006d9791660681f69655ac9 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
index 29f806c9b0feadd63f9ea3400e180f9602176dfb..091d4899e8e9db68ef10c1dca30650365c67c0c1 100644 (file)
@@ -24,7 +24,7 @@ import java.io.Reader;
 import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.mockito.ArgumentMatcher;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonarqube.ws.client.WsRequest;
 import org.sonarqube.ws.client.WsResponse;
 
@@ -35,25 +35,25 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class WsTestUtil {
-  public static void mockStream(ScannerWsClient mock, String path, InputStream is) {
+  public static void mockStream(DefaultScannerWsClient mock, String path, InputStream is) {
     WsResponse response = mock(WsResponse.class);
     when(response.contentStream()).thenReturn(is);
     when(mock.call(argThat(new RequestMatcher(path)))).thenReturn(response);
   }
 
-  public static void mockStream(ScannerWsClient mock, InputStream is) {
+  public static void mockStream(DefaultScannerWsClient mock, InputStream is) {
     WsResponse response = mock(WsResponse.class);
     when(response.contentStream()).thenReturn(is);
     when(mock.call(any(WsRequest.class))).thenReturn(response);
   }
 
-  public static void mockReader(ScannerWsClient mock, Reader reader) {
+  public static void mockReader(DefaultScannerWsClient mock, Reader reader) {
     WsResponse response = mock(WsResponse.class);
     when(response.contentReader()).thenReturn(reader);
     when(mock.call(any(WsRequest.class))).thenReturn(response);
   }
 
-  public static void mockReader(ScannerWsClient mock, String path, Reader reader, Reader... others) {
+  public static void mockReader(DefaultScannerWsClient mock, String path, Reader reader, Reader... others) {
     WsResponse response = mock(WsResponse.class);
     when(response.contentReader()).thenReturn(reader);
     WsResponse[] otherResponses = new WsResponse[others.length];
@@ -66,15 +66,15 @@ public class WsTestUtil {
     when(mock.call(argThat(new RequestMatcher(path)))).thenReturn(response, otherResponses);
   }
 
-  public static void mockException(ScannerWsClient mock, Exception e) {
+  public static void mockException(DefaultScannerWsClient mock, Exception e) {
     when(mock.call(any(WsRequest.class))).thenThrow(e);
   }
 
-  public static void mockException(ScannerWsClient mock, String path, Exception e) {
+  public static void mockException(DefaultScannerWsClient mock, String path, Exception e) {
     when(mock.call(argThat(new RequestMatcher(path)))).thenThrow(e);
   }
 
-  public static void verifyCall(ScannerWsClient mock, String path) {
+  public static void verifyCall(DefaultScannerWsClient mock, String path) {
     verify(mock).call(argThat(new RequestMatcher(path)));
   }
 
index d625da5f8dfd5c3065f3bdd7ea10a0c693263c70..620e3f703c179fbf02cea08991beb904f50f6468 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/DefaultScannerWsClientTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/DefaultScannerWsClientTest.java
new file mode 100644 (file)
index 0000000..bbc55bb
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * 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.scanner.bootstrap;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang.StringUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.HttpException;
+import org.sonarqube.ws.client.MockWsResponse;
+import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.WsRequest;
+import org.sonarqube.ws.client.WsResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DefaultScannerWsClientTest {
+
+  @Rule
+  public LogTester logTester = new LogTester();
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  WsClient wsClient = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
+
+  @Test
+  public void log_and_profile_request_if_debug_level() {
+    WsRequest request = newRequest();
+    WsResponse response = newResponse().setRequestUrl("https://local/api/issues/search");
+    when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+    logTester.setLevel(LoggerLevel.DEBUG);
+    DefaultScannerWsClient underTest = new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(
+      new RawScannerProperties(Collections.emptyMap())));
+
+    WsResponse result = underTest.call(request);
+
+    // do not fail the execution -> interceptor returns the response
+    assertThat(result).isSameAs(response);
+
+    // check logs
+    List<String> debugLogs = logTester.logs(LoggerLevel.DEBUG);
+    assertThat(debugLogs).hasSize(1);
+    assertThat(debugLogs.get(0)).contains("GET 200 https://local/api/issues/search | time=");
+  }
+
+  @Test
+  public void create_error_msg_from_json() {
+    String content = "{\"errors\":[{\"msg\":\"missing scan permission\"}, {\"msg\":\"missing another permission\"}]}";
+    assertThat(DefaultScannerWsClient.createErrorMessage(new HttpException("url", 400, content))).isEqualTo("missing scan permission, missing another permission");
+  }
+
+  @Test
+  public void create_error_msg_from_html() {
+    String content = "<!DOCTYPE html><html>something</html>";
+    assertThat(DefaultScannerWsClient.createErrorMessage(new HttpException("url", 400, content))).isEqualTo("HTTP code 400");
+  }
+
+  @Test
+  public void create_error_msg_from_long_content() {
+    String content = StringUtils.repeat("mystring", 1000);
+    assertThat(DefaultScannerWsClient.createErrorMessage(new HttpException("url", 400, content))).hasSize(15 + 128);
+  }
+
+  @Test
+  public void fail_if_requires_credentials() {
+    expectedException.expect(MessageException.class);
+    expectedException
+      .expectMessage("Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
+
+    WsRequest request = newRequest();
+    WsResponse response = newResponse().setCode(401);
+    when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+    new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
+  }
+
+  @Test
+  public void fail_if_credentials_are_not_valid() {
+    expectedException.expect(MessageException.class);
+    expectedException.expectMessage("Not authorized. Please check the properties sonar.login and sonar.password.");
+
+    WsRequest request = newRequest();
+    WsResponse response = newResponse().setCode(401);
+    when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+    new DefaultScannerWsClient(wsClient, /* credentials are configured */true, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
+  }
+
+  @Test
+  public void fail_if_requires_permission() {
+    expectedException.expect(MessageException.class);
+    expectedException.expectMessage("You're not authorized to run analysis. Please contact the project administrator.");
+
+    WsRequest request = newRequest();
+    WsResponse response = newResponse()
+      .setCode(403);
+    when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+    new DefaultScannerWsClient(wsClient, true, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
+  }
+
+  @Test
+  public void fail_if_bad_request() {
+    expectedException.expect(MessageException.class);
+    expectedException.expectMessage("Boo! bad request! bad!");
+
+    WsRequest request = newRequest();
+    WsResponse response = newResponse()
+      .setCode(400)
+      .setContent("{\"errors\":[{\"msg\":\"Boo! bad request! bad!\"}]}");
+    when(wsClient.wsConnector().call(request)).thenReturn(response);
+
+    new DefaultScannerWsClient(wsClient, true, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
+  }
+
+  private MockWsResponse newResponse() {
+    return new MockWsResponse().setRequestUrl("https://local/api/issues/search");
+  }
+
+  private WsRequest newRequest() {
+    return new GetRequest("api/issues/search");
+  }
+}
index d060367750d5e6c88cfd6a04dc928810e3f38351..17e4b72f4b06fcef588a997335bd4f8a8bab8457 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginInfo;
 
index 2c4ed265b275dc7ffa71f992101714d2716141f1..68070e636b516176f907f81547cea8aa85a9ee72 100644 (file)
@@ -33,8 +33,8 @@ 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.core.platform.ComponentContainer;
-import org.sonar.scanner.sensor.DefaultSensorDescriptor;
 import org.sonar.scanner.sensor.ModuleSensorContext;
 import org.sonar.scanner.sensor.ModuleSensorExtensionDictionnary;
 import org.sonar.scanner.sensor.ModuleSensorOptimizer;
index 9a7ebb0e127221a8ed07851634b15717eb2f3e0b..004528a98ebabb38aab79b16a01ddaa96239cef7 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.scanner.bootstrap.ScannerPluginInstaller.InstalledPlugin;
 import org.sonarqube.ws.client.HttpConnector;
 import org.sonarqube.ws.client.WsClientFactories;
@@ -74,7 +74,7 @@ public class PluginFilesTest {
   public void setUp() throws Exception {
     HttpConnector connector = HttpConnector.newBuilder().url(server.url("/").toString()).build();
     GlobalAnalysisMode analysisMode = new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()));
-    ScannerWsClient wsClient = new ScannerWsClient(WsClientFactories.getDefault().newClient(connector), false, analysisMode);
+    DefaultScannerWsClient wsClient = new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connector), false, analysisMode);
 
     userHome = temp.newFolder();
     MapSettings settings = new MapSettings();
index ed35ee1943d9ff4029e801ccea3b5df87aa84c3e..c81893378b8cbcb5f449f7bfd6c08cbfc49b06f5 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.scanner.postjob.DefaultPostJobDescriptor;
+import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
index fe6720aca8993500de0d71f12aae2109251de70a..edceff19a1b260b82b91acc214ab70267fc59751 100644 (file)
@@ -48,7 +48,7 @@ public class ScannerPluginInstallerTest {
   public ExpectedException expectedException = ExpectedException.none();
 
   private PluginFiles pluginFiles = mock(PluginFiles.class);
-  private ScannerWsClient wsClient = mock(ScannerWsClient.class);
+  private DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class);
   private ScannerPluginInstaller underTest = new ScannerPluginInstaller(pluginFiles, wsClient);
 
   @Test
index 5122d6f23e1dbc83cbf62538754877d3796e2c88..6f462beeaa7063c456fff6059d3559c2bae9fbf0 100644 (file)
@@ -39,7 +39,7 @@ public class ScannerWsClientProviderTest {
   public void provide_client_with_default_settings() {
     RawScannerProperties settings = new RawScannerProperties(new HashMap<>());
 
-    ScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), mock(System2.class));
+    DefaultScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), mock(System2.class));
 
     assertThat(client).isNotNull();
     assertThat(client.baseUrl()).isEqualTo("http://localhost:9000/");
@@ -59,7 +59,7 @@ public class ScannerWsClientProviderTest {
     props.put("sonar.ws.timeout", "42");
     RawScannerProperties settings = new RawScannerProperties(props);
 
-    ScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), mock(System2.class));
+    DefaultScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), mock(System2.class));
 
     assertThat(client).isNotNull();
     HttpConnector httpConnector = (HttpConnector) client.wsConnector();
@@ -72,8 +72,8 @@ public class ScannerWsClientProviderTest {
     System2 system = mock(System2.class);
 
     RawScannerProperties settings = new RawScannerProperties(new HashMap<>());
-    ScannerWsClient first = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), system);
-    ScannerWsClient second = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), system);
+    DefaultScannerWsClient first = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), system);
+    DefaultScannerWsClient second = underTest.provide(settings, env, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap())), system);
     assertThat(first).isSameAs(second);
   }
 }
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientTest.java
deleted file mode 100644 (file)
index abe99ed..0000000
+++ /dev/null
@@ -1,151 +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.scanner.bootstrap;
-
-import java.util.Collections;
-import java.util.List;
-import org.apache.commons.lang.StringUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.Mockito;
-import org.sonar.api.utils.MessageException;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonarqube.ws.client.GetRequest;
-import org.sonarqube.ws.client.HttpException;
-import org.sonarqube.ws.client.MockWsResponse;
-import org.sonarqube.ws.client.WsClient;
-import org.sonarqube.ws.client.WsRequest;
-import org.sonarqube.ws.client.WsResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ScannerWsClientTest {
-
-  @Rule
-  public LogTester logTester = new LogTester();
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  WsClient wsClient = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
-
-  @Test
-  public void log_and_profile_request_if_debug_level() {
-    WsRequest request = newRequest();
-    WsResponse response = newResponse().setRequestUrl("https://local/api/issues/search");
-    when(wsClient.wsConnector().call(request)).thenReturn(response);
-
-    logTester.setLevel(LoggerLevel.DEBUG);
-    ScannerWsClient underTest = new ScannerWsClient(wsClient, false, new GlobalAnalysisMode(
-      new RawScannerProperties(Collections.emptyMap())));
-
-    WsResponse result = underTest.call(request);
-
-    // do not fail the execution -> interceptor returns the response
-    assertThat(result).isSameAs(response);
-
-    // check logs
-    List<String> debugLogs = logTester.logs(LoggerLevel.DEBUG);
-    assertThat(debugLogs).hasSize(1);
-    assertThat(debugLogs.get(0)).contains("GET 200 https://local/api/issues/search | time=");
-  }
-
-  @Test
-  public void create_error_msg_from_json() {
-    String content = "{\"errors\":[{\"msg\":\"missing scan permission\"}, {\"msg\":\"missing another permission\"}]}";
-    assertThat(ScannerWsClient.createErrorMessage(new HttpException("url", 400, content))).isEqualTo("missing scan permission, missing another permission");
-  }
-
-  @Test
-  public void create_error_msg_from_html() {
-    String content = "<!DOCTYPE html><html>something</html>";
-    assertThat(ScannerWsClient.createErrorMessage(new HttpException("url", 400, content))).isEqualTo("HTTP code 400");
-  }
-
-  @Test
-  public void create_error_msg_from_long_content() {
-    String content = StringUtils.repeat("mystring", 1000);
-    assertThat(ScannerWsClient.createErrorMessage(new HttpException("url", 400, content))).hasSize(15 + 128);
-  }
-
-  @Test
-  public void fail_if_requires_credentials() {
-    expectedException.expect(MessageException.class);
-    expectedException
-      .expectMessage("Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
-
-    WsRequest request = newRequest();
-    WsResponse response = newResponse().setCode(401);
-    when(wsClient.wsConnector().call(request)).thenReturn(response);
-
-    new ScannerWsClient(wsClient, false, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
-  }
-
-  @Test
-  public void fail_if_credentials_are_not_valid() {
-    expectedException.expect(MessageException.class);
-    expectedException.expectMessage("Not authorized. Please check the properties sonar.login and sonar.password.");
-
-    WsRequest request = newRequest();
-    WsResponse response = newResponse().setCode(401);
-    when(wsClient.wsConnector().call(request)).thenReturn(response);
-
-    new ScannerWsClient(wsClient, /* credentials are configured */true, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
-  }
-
-  @Test
-  public void fail_if_requires_permission() {
-    expectedException.expect(MessageException.class);
-    expectedException.expectMessage("You're not authorized to run analysis. Please contact the project administrator.");
-
-    WsRequest request = newRequest();
-    WsResponse response = newResponse()
-      .setCode(403);
-    when(wsClient.wsConnector().call(request)).thenReturn(response);
-
-    new ScannerWsClient(wsClient, true, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
-  }
-
-  @Test
-  public void fail_if_bad_request() {
-    expectedException.expect(MessageException.class);
-    expectedException.expectMessage("Boo! bad request! bad!");
-
-    WsRequest request = newRequest();
-    WsResponse response = newResponse()
-      .setCode(400)
-      .setContent("{\"errors\":[{\"msg\":\"Boo! bad request! bad!\"}]}");
-    when(wsClient.wsConnector().call(request)).thenReturn(response);
-
-    new ScannerWsClient(wsClient, true, new GlobalAnalysisMode(new RawScannerProperties(Collections.emptyMap()))).call(request);
-  }
-
-  private MockWsResponse newResponse() {
-    return new MockWsResponse().setRequestUrl("https://local/api/issues/search");
-  }
-
-  private WsRequest newRequest() {
-    return new GetRequest("api/issues/search");
-  }
-}
index 57e1aa0efd4f7de2e532c1d7b6adaf0704b8b4ed..b372dd2bc978c3e328fcb628dc637742be90c399 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.scanner.ci;
 
 import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
 
 import static org.assertj.core.api.Assertions.assertThat;
index a649c5e9f24eeb95a034ba88a8995cca1e88e638..9767f60dedfde7dd6eaadf13063079bd5845d95d 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.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 2e3e6d2898d7a4d9c4035136e2defdd648647363..80a8e4b61f9e9c33865d5a94278bb3088a499324 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.anyString;
index f62bb729defbd3028f1c9638e695d9bd0074ef25..3b567a3846b2a4b54d7a83a32163c0e0b31e7e05 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.eq;
index 3eaeb9997adf7ec35e7c07b3107990c42d9b2cee..3659faec62f13949a06131f397c7c8fdb82c1189 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.commons.lang.ObjectUtils.defaultIfNull;
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultFileSystemTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultFileSystemTest.java
deleted file mode 100644 (file)
index 74a43db..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.scanner.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 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-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputDirTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputDirTest.java
deleted file mode 100644 (file)
index 1679a8d..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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputFileTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputFileTest.java
deleted file mode 100644 (file)
index 6673977..0000000
+++ /dev/null
@@ -1,315 +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.scanner.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.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-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputModuleTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputModuleTest.java
deleted file mode 100644 (file)
index 02570d3..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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputProjectTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/DefaultInputProjectTest.java
deleted file mode 100644 (file)
index 0324847..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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/FileMetadataTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/FileMetadataTest.java
deleted file mode 100644 (file)
index c266532..0000000
+++ /dev/null
@@ -1,308 +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.scanner.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.Metadata;
-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-scanner-engine/src/test/java/org/sonar/scanner/fs/TestInputFileBuilderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/TestInputFileBuilderTest.java
deleted file mode 100644 (file)
index 2d83007..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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/charhandler/IntArrayListTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/charhandler/IntArrayListTest.java
deleted file mode 100644 (file)
index 048a030..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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/AndPredicateTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/AndPredicateTest.java
deleted file mode 100644 (file)
index d3ec2aa..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.scanner.fs.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 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.<FilePredicate>asList(pathPatternPredicate1,
-      AndPredicate.create(Arrays.<FilePredicate>asList(pathPatternPredicate2, pathPatternPredicate3))));
-    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(pathPatternPredicate1, pathPatternPredicate2, pathPatternPredicate3);
-  }
-
-  @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.<FilePredicate>asList(pathPatternPredicate1,
-      relativePathPredicate, pathPatternPredicate2));
-    assertThat(((AndPredicate) andPredicate).predicates()).containsExactly(relativePathPredicate, pathPatternPredicate1, pathPatternPredicate2);
-  }
-
-  @Test
-  public void simplifyAndExpressionsWhenEmpty() {
-    FilePredicate andPredicate = AndPredicate.create(Arrays.<FilePredicate>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.<FilePredicate>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.<FilePredicate>asList(pathPatternPredicate1,
-      FalsePredicate.FALSE, pathPatternPredicate2));
-    assertThat(andPredicate).isEqualTo(FalsePredicate.FALSE);
-  }
-
-}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/DefaultFilePredicatesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/DefaultFilePredicatesTest.java
deleted file mode 100644 (file)
index d0869f0..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.scanner.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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/FileExtensionPredicateTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/FileExtensionPredicateTest.java
deleted file mode 100644 (file)
index 8cae2f4..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.scanner.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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/FilenamePredicateTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/FilenamePredicateTest.java
deleted file mode 100644 (file)
index 71c7d1f..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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/OrPredicateTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/OrPredicateTest.java
deleted file mode 100644 (file)
index 0804d1f..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.scanner.fs.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-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/RelativePathPredicateTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/fs/predicates/RelativePathPredicateTest.java
deleted file mode 100644 (file)
index b3c9c2d..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.scanner.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();
-  }
-}
index ccd628b0a17dc462d4ca1b533dffa0e1a987fe5f..777c85a924b3548b143f9ab58cf5e88dbcceecfa 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 40ac5200719b848bd0130c1ad26e272c40c99bc0..a13c2a7e88ac2a394aa4e370edf2c4e5dc766e35 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
index 980ee96bbe8db2996e420ed7abac5617e324a6ef..fcd36806b4f273467b1850a91994b58937c982e7 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.scanner.sensor.SensorContextTester;
+import org.sonar.api.impl.sensor.SensorContextTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 5250e1aa5d1311fdca91406e2c0d758b31229f68..cf1b13c9fd8e4d179d8fda50c5254d4ea28214a5 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.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 881a3629a04f60844ebb8b5b4f1ffdbc2b1ef43f..3bd71931f2dd6e80c1ea1795ae4eaa7cc070b48f 100644 (file)
@@ -32,18 +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.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.report.ReportPublisher;
-import org.sonar.scanner.rule.ActiveRulesBuilder;
-import org.sonar.scanner.rule.NewActiveRule;
-import org.sonar.scanner.rule.RulesBuilder;
-import org.sonar.scanner.sensor.DefaultExternalIssue;
+import org.sonar.api.impl.rule.ActiveRulesBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
index a656a767f71f520820a645cdcd85e87855c7601f..770bfc94806c58f82bd758c803968f7c45d3df7a 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.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.api.notifications.AnalysisWarnings;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.scan.issue.filter.IssueFilterChain;
index d5a99ff296fecf44afa6b60e77f78e8b30742f9f..4f514205e43ff1be78e8618ffd91e72c85cdfe2f 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.issue.DefaultFilterableIssue;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 50096cc117fd8709d1db5955fcb9db793bf39cf8..70a6a486db77d42aa5cac7b118e142df9fbd146a 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.core.config.IssueExclusionProperties;
 
index c6cc5777bda1f23aa981fec975e328300669760b..7932972af78256cfa417f0e3428130a5eabc7d1e 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.core.config.IssueExclusionProperties;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 94cebe5f0bdc96ad2bec20c73a67b8fe3c354f4b..ea148567732f114f344b2bd14d479c881b5096e7 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.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 fb4165825e750fe3fded201ffab88fb5ac24bff8..e6c757a92d37abded0d74cea3dd8fea52e2c30c7 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.FileMetadata;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.FileMetadata;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
 import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader.DoubleRegexpMatcher;
 
index 244dec3cfcc9be08936376925c3ae2565827e2a9..96b69e81ff183a8a6f48575f0de087184be1d0ec 100644 (file)
@@ -44,6 +44,8 @@ import org.sonar.api.SonarEdition;
 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.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.rule.RuleKey;
@@ -65,7 +67,6 @@ import org.sonar.scanner.repository.SingleProjectRepository;
 import org.sonar.scanner.repository.settings.GlobalSettingsLoader;
 import org.sonar.scanner.repository.settings.ProjectSettingsLoader;
 import org.sonar.scanner.rule.ActiveRulesLoader;
-import org.sonar.scanner.rule.LoadedActiveRule;
 import org.sonar.scanner.rule.RulesLoader;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
@@ -73,7 +74,6 @@ import org.sonar.scanner.scan.branch.BranchConfigurationLoader;
 import org.sonar.scanner.scan.branch.BranchType;
 import org.sonar.scanner.scan.branch.ProjectBranches;
 import org.sonar.scanner.scan.branch.ProjectPullRequests;
-import org.sonar.server.rule.RuleDefinitionContext;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
 import org.sonarqube.ws.Rules.ListResponse.Rule;
 
index 40695d3529e397518fc8463fa328279884063300..bb77fdd9001c487887abd1c00d5f99722cb96857 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.FileMetadata;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.FileMetadata;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.protocol.output.ScannerReport;
index d6f141aa0f87b879156936ed50504a7b51168e98..27b0c75eb391c5eed7418b1a2053e409f4dd85d9 100644 (file)
@@ -32,8 +32,8 @@ 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.utils.MessageException;
-import org.sonar.scanner.fs.DefaultInputFile;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.xoo.XooPlugin;
index e64c47b7edb77ecc964425ab9457ef3abc6e5150..aeab443969487a905c7b2f2ce5782dfc2645135f 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.scanner.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.xoo.XooPlugin;
index fdc8a2c2b68e66c67ba1df59ec2647d0d0b64a3e..e725100e8387e99046739b8e0684d88c4d21ad78 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.protocol.output.ScannerReport.Issue;
-import org.sonar.scanner.rule.LoadedActiveRule;
+import org.sonar.api.batch.rule.LoadedActiveRule;
 import org.sonar.xoo.XooPlugin;
 import org.sonar.xoo.rule.XooRulesDefinition;
 
index 683773b6e94eca3ea874e0feda3be348b47a74f0..dc306bbec9d337ee603001316636668071f47317 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.mediumtest.AnalysisResult;
 import org.sonar.scanner.protocol.output.ScannerReport.ExternalIssue;
 import org.sonar.scanner.protocol.output.ScannerReport.Issue;
-import org.sonar.scanner.rule.LoadedActiveRule;
+import org.sonar.api.batch.rule.LoadedActiveRule;
 import org.sonar.xoo.XooPlugin;
 import org.sonar.xoo.rule.HasTagSensor;
 import org.sonar.xoo.rule.OneExternalIssuePerLineSensor;
index 6bfffc32384e7aa8837539211a41769df651ad90..eff17f8ca83e65a39aa47538d10088414f9ee66d 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.scan.ModuleConfiguration;
 import org.sonar.scanner.scan.filesystem.ModuleCoverageAndDuplicationExclusions;
 
index d48402ea9edff75ed61b41e24ccb53ff85c330dc..fb7cf2ccea13579247718e54211f4a69a39ac0ec 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.batch.fs.internal.SensorStrategy;
+import org.sonar.api.impl.fs.SensorStrategy;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.scanner.bootstrap.ScannerPluginRepository;
-import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.sensor.ModuleSensorExtensionDictionnary;
 import org.sonar.scanner.sensor.ModuleSensorWrapper;
 import org.sonar.scanner.sensor.ModuleSensorsExecutor;
index a225093a650321bdf8b898f6a27648046a98d46d..f95fa930015467d1e03dd2aaa53360b1baa6e125 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.scan.ProjectConfiguration;
 import org.sonar.scanner.scan.filesystem.ProjectCoverageAndDuplicationExclusions;
 
index a9283aa8590b8220a384b221ea66fcbd9ba1f514..d34cfb43c1280b72e7edc2d9dd806fc699c3a838 100644 (file)
@@ -24,10 +24,10 @@ import org.junit.Test;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.SonarQubeSide;
 import org.sonar.api.config.Settings;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.api.internal.SonarRuntimeImpl;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.context.SonarRuntimeImpl;
 import org.sonar.api.utils.Version;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -40,7 +40,7 @@ public class DefaultServerTest {
     Settings settings = new MapSettings();
     settings.setProperty(CoreProperties.SERVER_ID, "123");
     settings.setProperty(CoreProperties.SERVER_STARTTIME, "2010-05-18T17:59:00+0000");
-    ScannerWsClient client = mock(ScannerWsClient.class);
+    DefaultScannerWsClient client = mock(DefaultScannerWsClient.class);
     when(client.baseUrl()).thenReturn("http://foo.com");
 
     DefaultServer metadata = new DefaultServer(((MapSettings) settings).asConfig(), client,
@@ -61,7 +61,7 @@ public class DefaultServerTest {
   @Test
   public void publicRootUrl() {
     Settings settings = new MapSettings();
-    ScannerWsClient client = mock(ScannerWsClient.class);
+    DefaultScannerWsClient client = mock(DefaultScannerWsClient.class);
     when(client.baseUrl()).thenReturn("http://foo.com/");
     DefaultServer metadata = new DefaultServer(((MapSettings) settings).asConfig(), client, null);
 
@@ -76,7 +76,7 @@ public class DefaultServerTest {
   public void invalid_startup_date_throws_exception() {
     Settings settings = new MapSettings();
     settings.setProperty(CoreProperties.SERVER_STARTTIME, "invalid");
-    ScannerWsClient client = mock(ScannerWsClient.class);
+    DefaultScannerWsClient client = mock(DefaultScannerWsClient.class);
     DefaultServer metadata = new DefaultServer(((MapSettings) settings).asConfig(), client, null);
     metadata.getStartedAt();
   }
index 6399495c410d305417c35bce4f43199305164634..27a4f7bbd9eebf751eb724addcb83a69b3a49183 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 1b604e11b6ebeccb4da9f5aca70e029c3f162293..c10ffd5c23761bd64a57daea32a2283d7e6a56a2 100644 (file)
@@ -23,7 +23,8 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
+import org.sonar.api.impl.sensor.DefaultPostJobDescriptor;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 6293696adc4c15e018e00ec655a92b8575bbc0fb..2dce5ea77306e3c691e4914a505014db5b8ef297 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.scanner.rule.DefaultActiveRules;
-import org.sonar.scanner.rule.NewActiveRule;
+import org.sonar.api.impl.rule.DefaultActiveRules;
+import org.sonar.api.batch.rule.NewActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.scanner.protocol.Constants;
index f795cf9740809d1a4ca3265d8e4e272bfce0bd0a..5299672f6fd0bb724bd3d3abf4ee1f6350f9a7c0 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.ProjectServerSettings;
@@ -147,66 +147,6 @@ public class AnalysisContextReportPublisherTest {
       "  - sonar.projectKey=foo");
   }
 
-  @Test
-  public void shouldNotDumpSQPropsInSystemProps() throws Exception {
-    logTester.setLevel(LoggerLevel.DEBUG);
-    ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder());
-    Properties props = new Properties();
-    props.setProperty(COM_FOO, "bar");
-    props.setProperty(SONAR_SKIP, "true");
-    when(system2.properties()).thenReturn(props);
-    DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create()
-      .setBaseDir(temp.newFolder())
-      .setWorkDir(temp.newFolder())
-      .setProperty("sonar.projectKey", "foo")
-      .setProperty(COM_FOO, "bar")
-      .setProperty(SONAR_SKIP, "true"));
-    when(store.allModules()).thenReturn(singletonList(rootModule));
-    when(hierarchy.root()).thenReturn(rootModule);
-
-    publisher.init(writer);
-
-    List<String> lines = FileUtils.readLines(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8);
-    assertThat(lines).containsExactly("Environment variables:",
-      "System properties:",
-      "  - com.foo=bar",
-      "SonarQube plugins:",
-      "Global server settings:",
-      "Project server settings:",
-      "Project scanner properties:",
-      "  - sonar.projectKey=foo",
-      "  - sonar.skip=true");
-  }
-
-  @Test
-  public void shouldNotDumpEnvTwice() throws Exception {
-    logTester.setLevel(LoggerLevel.DEBUG);
-    ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder());
-
-    Map<String, String> env = new HashMap<>();
-    env.put(FOO, "BAR");
-    env.put(BIZ, "BAZ");
-    when(system2.envVariables()).thenReturn(env);
-    DefaultInputModule rootModule = new DefaultInputModule(ProjectDefinition.create()
-      .setBaseDir(temp.newFolder())
-      .setWorkDir(temp.newFolder())
-      .setProperty("sonar.projectKey", "foo")
-      .setProperty("env." + FOO, "BAR"));
-    when(store.allModules()).thenReturn(singletonList(rootModule));
-    when(hierarchy.root()).thenReturn(rootModule);
-    publisher.init(writer);
-
-    String content = FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8);
-    assertThat(content).containsOnlyOnce(FOO);
-    assertThat(content).containsOnlyOnce(BIZ);
-    assertThat(content).containsSubsequence(BIZ, FOO);
-
-    content = FileUtils.readFileToString(writer.getFileStructure().analysisLog(), StandardCharsets.UTF_8);
-    assertThat(content).containsOnlyOnce(FOO);
-    assertThat(content).containsOnlyOnce(BIZ);
-    assertThat(content).doesNotContain("env." + FOO);
-  }
-
   @Test
   public void shouldNotDumpSensitiveModuleProperties() throws Exception {
     ScannerReportWriter writer = new ScannerReportWriter(temp.newFolder());
index 18ce32fab0a154c558d3e256358167bdf81e1ddd..d3b7a0b4936e67c4f9710ead5f5008f8b5c129ca 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputProject;
 import org.sonar.scanner.fs.InputModuleHierarchy;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
index b812747c69228efd8690b652722a1617e3082f58..0561c6076e3b72215c02419a1792cd6b8c0d2c99 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.FileStructure;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Component;
index 3eb07e5e945daa87492372b1ae8d64bd9099425c..9bbe982e9fcd5d98b6864eddb4013d32f9adf93f 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
index 3c7893722adb1fcb52a15d1183cf8d5fe4645504..e81e23e2f3bee2a3f6c617127b79f798796cb465 100644 (file)
@@ -40,8 +40,8 @@ import org.sonar.api.utils.TempFolder;
 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.ScannerWsClient;
-import org.sonar.scanner.fs.DefaultInputModule;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
@@ -73,7 +73,7 @@ public class ReportPublisherTest {
 
   GlobalAnalysisMode mode = mock(GlobalAnalysisMode.class);
   ScanProperties properties = mock(ScanProperties.class);
-  ScannerWsClient wsClient = mock(ScannerWsClient.class, Mockito.RETURNS_DEEP_STUBS);
+  DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class, Mockito.RETURNS_DEEP_STUBS);
   Server server = mock(Server.class);
   InputModuleHierarchy moduleHierarchy = mock(InputModuleHierarchy.class);
   DefaultInputModule root;
index 835e423f9ee3828f5bd0618b2206b97bc0aa1ce9..e1239caab09c9b83f660a699e77293e1d1240b97 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
index 5bf5861506147f8f875aeabf0823c8aaea9e12ae..7b21c92e5a82f1a166187e8507408389be32a0d5 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.scanner.WsTestUtil;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
@@ -40,7 +40,7 @@ import static org.mockito.Mockito.when;
 
 public class DefaultMetricsRepositoryLoaderTest {
   private static final String WS_URL = "/api/metrics/search?f=name,description,direction,qualitative,custom&ps=500&p=";
-  private ScannerWsClient wsClient;
+  private DefaultScannerWsClient wsClient;
   private DefaultMetricsRepositoryLoader metricsRepositoryLoader;
 
   @Rule
@@ -48,7 +48,7 @@ public class DefaultMetricsRepositoryLoaderTest {
 
   @Before
   public void setUp() throws IOException {
-    wsClient = mock(ScannerWsClient.class);
+    wsClient = mock(DefaultScannerWsClient.class);
     WsTestUtil.mockReader(wsClient, WS_URL + "1", new StringReader(IOUtils.toString(this.getClass().getResourceAsStream("DefaultMetricsRepositoryLoaderTest/page1.json"))));
     WsTestUtil.mockReader(wsClient, WS_URL + "2", new StringReader(IOUtils.toString(this.getClass().getResourceAsStream("DefaultMetricsRepositoryLoaderTest/page2.json"))));
     metricsRepositoryLoader = new DefaultMetricsRepositoryLoader(wsClient);
index f2888be4c655607ee7f4e92e4a3ef678556f55a2..567079db5853541735dde93946c537fd054ed4f3 100644 (file)
@@ -31,8 +31,8 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.WsTestUtil;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
-import org.sonar.scanner.fs.DefaultInputFile;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
+import org.sonar.api.impl.fs.DefaultInputFile;
 import org.sonarqube.ws.Batch.WsProjectResponse;
 import org.sonarqube.ws.client.HttpException;
 import org.sonarqube.ws.client.WsRequest;
@@ -49,11 +49,11 @@ public class DefaultProjectRepositoriesLoaderTest {
   public ExpectedException thrown = ExpectedException.none();
 
   private DefaultProjectRepositoriesLoader loader;
-  private ScannerWsClient wsClient;
+  private DefaultScannerWsClient wsClient;
 
   @Before
   public void prepare() throws IOException {
-    wsClient = mock(ScannerWsClient.class);
+    wsClient = mock(DefaultScannerWsClient.class);
     InputStream is = mockData();
     WsTestUtil.mockStream(wsClient, "/batch/project.protobuf?key=foo%3F", is);
     loader = new DefaultProjectRepositoriesLoader(wsClient);
index 95e38e4520eb670602c3c9f47809e20f9336e0c4..edfc14e5bd6378aa3464b707cdec4f6f6e0228ba 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.WsTestUtil;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonarqube.ws.Qualityprofiles;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
@@ -43,7 +43,7 @@ public class DefaultQualityProfileLoaderTest {
   @Rule
   public ExpectedException exception = ExpectedException.none();
 
-  private ScannerWsClient wsClient = mock(ScannerWsClient.class);
+  private DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class);
   private ScanProperties properties = mock(ScanProperties.class);
   private DefaultQualityProfileLoader underTest = new DefaultQualityProfileLoader(properties, wsClient);
 
index aff5f0fcc3c4da962ddbe2e40ccf5d19c3151d3c..0a1f91e94294e468bf806ecd26517b0576ab4f99 100644 (file)
@@ -25,7 +25,7 @@ import java.io.PipedOutputStream;
 import java.util.Map;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonarqube.ws.Settings;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.WsResponse;
@@ -39,7 +39,7 @@ import static org.mockito.Mockito.when;
 
 public class DefaultGlobalSettingsLoaderTest {
 
-  private ScannerWsClient wsClient = mock(ScannerWsClient.class);
+  private DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class);
   private DefaultGlobalSettingsLoader underTest = new DefaultGlobalSettingsLoader(wsClient);
 
   @Test
index a9163f56bb3ae7b0be44458372d625b03b1b5dd0..125e7bd74ee8e1476f921c8df3adb6db0ba80b9a 100644 (file)
@@ -26,7 +26,7 @@ import java.util.Map;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonarqube.ws.Settings;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.WsResponse;
@@ -40,7 +40,7 @@ import static org.mockito.Mockito.when;
 
 public class DefaultProjectSettingsLoaderTest {
 
-  private ScannerWsClient wsClient = mock(org.sonar.scanner.bootstrap.ScannerWsClient.class);
+  private DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class);
   private ProcessedScannerProperties properties = mock(ProcessedScannerProperties.class);
   private DefaultProjectSettingsLoader underTest = new DefaultProjectSettingsLoader(wsClient, properties);
 
index e892510d04611c53682ef299aae43b83085d702e..c48b0dc8aeb7289f0b8277d41408fe9201279ce4 100644 (file)
@@ -24,6 +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.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 
index 2773208a00faa61f15a30d41db71513cfa8aa02f..4a8851ded6c2171cdfc0b652f9034e8d90769ad0 100644 (file)
@@ -30,6 +30,7 @@ import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.LoadedActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.DateUtils;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
index ad46a6851ed305dc83d33c893b5d9b6a7b068eb9..0dd61ad9ccff5747e3135b04ae6916c586428331 100644 (file)
@@ -26,10 +26,11 @@ import java.util.Collection;
 import java.util.stream.IntStream;
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.batch.rule.LoadedActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.scanner.WsTestUtil;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonarqube.ws.Rules;
 import org.sonarqube.ws.Rules.Active;
@@ -54,11 +55,11 @@ public class DefaultActiveRulesLoaderTest {
   private static final String SEVERITY_VALUE = Severity.MINOR;
 
   private DefaultActiveRulesLoader loader;
-  private ScannerWsClient wsClient;
+  private DefaultScannerWsClient wsClient;
 
   @Before
   public void setUp() {
-    wsClient = mock(ScannerWsClient.class);
+    wsClient = mock(DefaultScannerWsClient.class);
     BranchConfiguration branchConfig = mock(BranchConfiguration.class);
     when(branchConfig.isShortOrPullRequest()).thenReturn(false);
     loader = new DefaultActiveRulesLoader(wsClient);
index b2d06f19442b94f1fdedc5fc82fd8cff6d2b016c..b614d456fbe254e64fb85f9beb5154117b8cbf3d 100644 (file)
@@ -27,7 +27,7 @@ import java.util.List;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.scanner.WsTestUtil;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
 import org.sonarqube.ws.Rules.ListResponse.Rule;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -39,7 +39,7 @@ public class DefaultRulesLoaderTest {
 
   @Test
   public void testParseServerResponse() throws IOException {
-    ScannerWsClient wsClient = mock(ScannerWsClient.class);
+    DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class);
     InputStream is = Resources.asByteSource(this.getClass().getResource("DefaultRulesLoaderTest/response.protobuf")).openBufferedStream();
     WsTestUtil.mockStream(wsClient, is);
     DefaultRulesLoader loader = new DefaultRulesLoader(wsClient);
@@ -49,7 +49,7 @@ public class DefaultRulesLoaderTest {
 
   @Test
   public void testError() throws IOException {
-    ScannerWsClient wsClient = mock(ScannerWsClient.class);
+    DefaultScannerWsClient wsClient = mock(DefaultScannerWsClient.class);
     InputStream is = ByteSource.wrap(new String("trash").getBytes()).openBufferedStream();
     WsTestUtil.mockStream(wsClient, is);
     DefaultRulesLoader loader = new DefaultRulesLoader(wsClient);
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultRulesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultRulesTest.java
deleted file mode 100644 (file)
index 3beb53f..0000000
+++ /dev/null
@@ -1,73 +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.scanner.rule;
-
-import org.sonar.api.rule.RuleKey;
-import org.junit.Test;
-
-import java.util.LinkedList;
-import java.util.List;
-
-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-scanner-engine/src/test/java/org/sonar/scanner/rule/NewActiveRuleTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/NewActiveRuleTest.java
deleted file mode 100644 (file)
index a3a4e40..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.scanner.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(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(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 f7a64f06b630acfb48e14516fa83938f8b945ef6..e81930bf234ea7209acbff405780bf4bbeb567ad 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.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/RulesBuilderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/RulesBuilderTest.java
deleted file mode 100644 (file)
index 1bb2375..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.scanner.rule;
-
-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(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(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");
-  }
-}
index aadf37e6a7542ef3bb857667f2f4baf1965ae18b..1bdce821151f21aa38226faacc2f224fec6202ea 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 3c4cb6ffb15765e6588214c0b81e98244e2c7edc..18da6ddf5bff961a638471278bccef4d030c2203 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.filesystem.InputComponentStore;
 
index 12f20933bdb4f240c337d036854b64e24266bb13..9ebc2cea34efa7664bf6e4a4d6fe6346626a0c25 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index a2622ae4cbd7fbf4ade5978cf9e2bf89dca06b82..7241ab7b03a2122fc86f9b1470333dbea2a457fa 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.utils.MessageException;
-import org.sonar.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index ba5aedb451f4e80a16954f21200013c086f0b9be..19797c845bd9f964e4400b94095152002b5d7add 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.scanner.fs.DefaultInputModule;
+import org.sonar.api.impl.fs.DefaultInputModule;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 37775d19ae53e6845f494aeba24b56863b4124b5..4974350faf7fe87d7efc25656a0b13e003876d15 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.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index e9365140bd2a4cadf160cb7be8c2ff81c89e9f4a..709b5960b9f05fbf8447cdc09b60a98ce0938306 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+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.scanner.scan.branch.BranchConfiguration;
 
 import static org.assertj.core.api.Assertions.assertThat;
index c924cb4c5e5cfa3f3f1eb5c3d6551793bebd003e..30a3a20d713a075656239247a27cf936e4084c57 100644 (file)
@@ -27,8 +27,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.config.MapSettings;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.utils.MessageException;
index 0682ccaf345a28af3359f9d8b642e98ea00a387e..8ec05f3294e8060cf4225462ef92c64c8f904d48 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.FileMetadata;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.FileMetadata;
+import org.sonar.api.impl.fs.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 c624be2c6f1ebf8c0026058886795b233d2c845e..57386cb65e9a7d092061c575a643f83d09c57c44 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.batch.fs.internal.SensorStrategy;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.SensorStrategy;
+import org.sonar.api.impl.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 
 import static org.assertj.core.api.Assertions.assertThat;
index 9f613f48ed703f1ed9807534da60691040e4e59e..af8c8156613d989cedf3a95a3741410dcc044aab 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.scanner.fs.DefaultIndexedFile;
-import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.impl.fs.DefaultIndexedFile;
+import org.sonar.api.impl.config.MapSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
index 167b4e33a9cfd8193127fea454381c8258a09826..10fc2c68e1ad710c0cbd9dd8573814dabb215ea5 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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.DefaultInputFile;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.scanner.repository.FileData;
 import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
 import org.sonar.scanner.repository.SingleProjectRepository;
index a408dde4a419238d2b3934a5edfea11aeb9e7d43..5ea2bc5464c964f3669e0be90caf64e1891e04c4 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.scanner.fs.TestInputFileBuilder;
+import org.sonar.api.impl.fs.TestInputFileBuilder;
 import org.sonar.api.batch.scm.BlameLine;
 
 public class DefaultBlameOutputTest {
index 681433767ff5961cba6d79cd2f70d00ab0b751dd..6304dcbd82f17b495975a9fcbaa1c9ac96604cea 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.scanner.fs.DefaultInputProject;
+import org.sonar.api.impl.fs.DefaultInputProject;
 import org.sonar.scanner.fs.InputModuleHierarchy;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultAdHocRuleTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultAdHocRuleTest.java
deleted file mode 100644 (file)
index 44a53e7..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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultAnalysisErrorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultAnalysisErrorTest.java
deleted file mode 100644 (file)
index afff924..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.scanner.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.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultCpdTokensTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultCpdTokensTest.java
deleted file mode 100644 (file)
index 7a55979..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.scanner.sensor;
-
-import org.junit.Test;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultExternalIssueTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultExternalIssueTest.java
deleted file mode 100644 (file)
index 0081480..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.scanner.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.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultHighlightingTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultHighlightingTest.java
deleted file mode 100644 (file)
index f70f92d..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.scanner.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.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.fs.DefaultTextRange;
-import org.sonar.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultIssueLocationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultIssueLocationTest.java
deleted file mode 100644 (file)
index f869f6f..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.scanner.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.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultIssueTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultIssueTest.java
deleted file mode 100644 (file)
index c6659db..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.scanner.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.scanner.fs.DefaultInputDir;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.issue.DefaultIssue;
-import org.sonar.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultMeasureTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultMeasureTest.java
deleted file mode 100644 (file)
index 43de69f..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.scanner.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.scanner.fs.AbstractProjectOrModule;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorDescriptorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorDescriptorTest.java
deleted file mode 100644 (file)
index a43272b..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.scanner.sensor;
-
-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");
-  }
-
-}
index d95d44a69ed2ffd05c3ffa725826384fbee7af90..fe82b6429026b6f133127756e5701a876fb55105 100644 (file)
@@ -33,17 +33,22 @@ import org.sonar.api.batch.measure.MetricFinder;
 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.config.internal.MapSettings;
+import org.sonar.api.impl.config.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.scanner.fs.DefaultInputDir;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.issue.DefaultIssue;
-import org.sonar.scanner.issue.DefaultIssueLocation;
+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;
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSignificantCodeTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSignificantCodeTest.java
deleted file mode 100644 (file)
index 73a7f1c..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.scanner.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.scanner.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-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSymbolTableTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSymbolTableTest.java
deleted file mode 100644 (file)
index 3339e1d..0000000
+++ /dev/null
@@ -1,73 +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.scanner.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.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.sensor.DefaultSymbolTable;
-
-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-scanner-engine/src/test/java/org/sonar/scanner/sensor/InMemorySensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/InMemorySensorStorageTest.java
deleted file mode 100644 (file)
index 76e4874..0000000
+++ /dev/null
@@ -1,59 +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.scanner.sensor;
-
-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);
-  }
-}
index 668a050119ade6d8c9cb6d11c3c159e502de69d4..dea7f4176d5a904b5aad230eae18f54290359cac 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.config.internal.MapSettings;
-import org.sonar.api.internal.SonarRuntimeImpl;
+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.measures.CoreMetrics;
 import org.sonar.api.utils.Version;
-import org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.DefaultInputProject;
-import org.sonar.scanner.rule.ActiveRulesBuilder;
+import org.sonar.api.impl.rule.ActiveRulesBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 0a78c6b2984cc7a812f11a87d7d2b515167c422c..197749532c879de00c5752c47fb7939bc10a679f 100644 (file)
@@ -26,12 +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.config.internal.MapSettings;
+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.rule.RuleKey;
-import org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.rule.ActiveRulesBuilder;
-import org.sonar.scanner.rule.NewActiveRule;
+import org.sonar.api.impl.rule.ActiveRulesBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/SensorContextTesterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/SensorContextTesterTest.java
deleted file mode 100644 (file)
index 24e9379..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.scanner.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.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.measures.CoreMetrics;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleType;
-import org.sonar.scanner.fs.DefaultFileSystem;
-import org.sonar.scanner.fs.DefaultInputFile;
-import org.sonar.scanner.fs.DefaultInputModule;
-import org.sonar.scanner.fs.DefaultTextPointer;
-import org.sonar.scanner.fs.TestInputFileBuilder;
-import org.sonar.scanner.rule.ActiveRulesBuilder;
-import org.sonar.scanner.rule.NewActiveRule;
-
-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"));
-  }
-}
index f5df14fd0b37a2ea47112c770bfd8f53f0952a2b..1a1ccf2843c0d4d5247ccfcbccc043784c064e4e 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.scanner.util;
 
 import org.junit.Test;
+import org.sonar.api.impl.utils.ScannerUtils;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/sonar-scanner-engine/src/test/resources/org/sonar/scanner/fs/glyphicons-halflings-regular.woff b/sonar-scanner-engine/src/test/resources/org/sonar/scanner/fs/glyphicons-halflings-regular.woff
deleted file mode 100644 (file)
index 2cc3e48..0000000
Binary files a/sonar-scanner-engine/src/test/resources/org/sonar/scanner/fs/glyphicons-halflings-regular.woff and /dev/null differ