diff options
36 files changed, 649 insertions, 310 deletions
diff --git a/plugins/sonar-design-plugin/pom.xml b/plugins/sonar-design-plugin/pom.xml deleted file mode 100644 index f04d435231f..00000000000 --- a/plugins/sonar-design-plugin/pom.xml +++ /dev/null @@ -1,103 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar</artifactId> - <version>5.0-SNAPSHOT</version> - <relativePath>../..</relativePath> - </parent> - <groupId>org.codehaus.sonar.plugins</groupId> - <artifactId>sonar-design-plugin</artifactId> - <packaging>sonar-plugin</packaging> - <name>SonarQube :: Plugins :: Design</name> - - <dependencies> - <dependency> - <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar-core</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar-plugin-api</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.apache.maven.shared</groupId> - <artifactId>maven-dependency-tree</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - </dependency> - - <!-- unit tests --> - <dependency> - <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar-testing-harness</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - </dependency> - </dependencies> - - <build> - - <plugins> - <plugin> - <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar-packaging-maven-plugin</artifactId> - <configuration> - <pluginKey>design</pluginKey> - <pluginName>Design</pluginName> - <pluginClass>org.sonar.plugins.design.DesignPlugin</pluginClass> - <pluginDescription><![CDATA[Analyze Java bytecode to compute O.O. metrics and extract dependencies between resources.]]></pluginDescription> - </configuration> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - </execution> - </executions> - <configuration> - <artifactSet> - <includes> - <include>org.codehaus.sonar:sonar-gwt-pages</include> - </includes> - </artifactSet> - </configuration> - </plugin> - - <plugin> - <groupId>org.codehaus.sonar</groupId> - <artifactId>sonar-dev-maven-plugin</artifactId> - <executions> - <execution> - <id>trim</id> - <phase>process-resources</phase> - <goals> - <goal>trim</goal> - </goals> - <configuration> - <directory>${project.build.outputDirectory}</directory> - <includes> - <include>**/*.erb</include> - </includes> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </build> -</project> diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/DesignPlugin.java b/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/DesignPlugin.java deleted file mode 100644 index bc464fe4b96..00000000000 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/DesignPlugin.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.design; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.Extension; -import org.sonar.api.SonarPlugin; -import org.sonar.plugins.design.batch.FileTangleIndexDecorator; -import org.sonar.plugins.design.batch.MavenDependenciesSensor; -import org.sonar.plugins.design.batch.PackageTangleIndexDecorator; -import org.sonar.plugins.design.batch.ProjectDsmDecorator; -import org.sonar.plugins.design.ui.widgets.FileDesignWidget; -import org.sonar.plugins.design.ui.widgets.PackageDesignWidget; - -import java.util.List; - -public class DesignPlugin extends SonarPlugin { - - public List<Class<? extends Extension>> getExtensions() { - return ImmutableList.of( - // Batch - MavenDependenciesSensor.class, - ProjectDsmDecorator.class, - PackageTangleIndexDecorator.class, - FileTangleIndexDecorator.class, - - // UI - FileDesignWidget.class, - PackageDesignWidget.class); - } -} diff --git a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/DesignPluginTest.java b/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/DesignPluginTest.java deleted file mode 100644 index 336889f2f81..00000000000 --- a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/DesignPluginTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.design; - -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertThat; -import org.junit.Test; - -public class DesignPluginTest { - - @Test - public void getExtensions() { - DesignPlugin plugin = new DesignPlugin(); - assertThat(plugin.getExtensions().size(), greaterThan(1)); - } -} diff --git a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/MavenDependenciesSensorTest/getEffectiveLibraries/pom.xml b/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/MavenDependenciesSensorTest/getEffectiveLibraries/pom.xml deleted file mode 100644 index 1ff8aa38516..00000000000 --- a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/MavenDependenciesSensorTest/getEffectiveLibraries/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <groupId>fake.group</groupId> - <artifactId>fake-artifact</artifactId> - <version>0.1-SNAPSHOT</version> - <name>Fake</name> - <dependencies> - <dependency> - <groupId>commons-lang</groupId> - <artifactId>commons-lang</artifactId> - <version>2.4</version> - </dependency> - - <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>1.4</version> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.7</version> - <scope>test</scope> - </dependency> - </dependencies> -</project>
\ No newline at end of file @@ -32,7 +32,6 @@ <module>plugins/sonar-core-plugin</module> <module>plugins/sonar-dbcleaner-plugin</module> <module>plugins/sonar-cpd-plugin</module> - <module>plugins/sonar-design-plugin</module> <module>plugins/sonar-l10n-en-plugin</module> <module>plugins/sonar-email-notifications-plugin</module> <module>plugins/sonar-xoo-plugin</module> diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/FileDesignWidget.java b/server/sonar-server/src/main/java/org/sonar/server/design/FileDesignWidget.java index 6da07758166..219a20a8e4e 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/FileDesignWidget.java +++ b/server/sonar-server/src/main/java/org/sonar/server/design/FileDesignWidget.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.ui.widgets; +package org.sonar.server.design; import org.sonar.api.web.AbstractRubyTemplate; import org.sonar.api.web.RubyRailsWidget; @@ -25,7 +25,7 @@ import org.sonar.api.web.UserRole; import org.sonar.api.web.WidgetCategory; @UserRole(UserRole.USER) -@WidgetCategory({ "Design" }) +@WidgetCategory({"Design"}) public final class FileDesignWidget extends AbstractRubyTemplate implements RubyRailsWidget { public String getId() { @@ -38,6 +38,6 @@ public final class FileDesignWidget extends AbstractRubyTemplate implements Ruby @Override protected String getTemplatePath() { - return "/org/sonar/plugins/design/ui/widgets/file_design.html.erb"; + return "/org/sonar/server/design/file_design.html.erb"; } } diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/PackageDesignWidget.java b/server/sonar-server/src/main/java/org/sonar/server/design/PackageDesignWidget.java index f5d18f61c2f..d5f02c36788 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/ui/widgets/PackageDesignWidget.java +++ b/server/sonar-server/src/main/java/org/sonar/server/design/PackageDesignWidget.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.ui.widgets; +package org.sonar.server.design; import org.sonar.api.web.AbstractRubyTemplate; import org.sonar.api.web.RubyRailsWidget; @@ -25,7 +25,7 @@ import org.sonar.api.web.UserRole; import org.sonar.api.web.WidgetCategory; @UserRole(UserRole.USER) -@WidgetCategory({ "Design" }) +@WidgetCategory({"Design"}) public final class PackageDesignWidget extends AbstractRubyTemplate implements RubyRailsWidget { public String getId() { @@ -38,6 +38,6 @@ public final class PackageDesignWidget extends AbstractRubyTemplate implements R @Override protected String getTemplatePath() { - return "/org/sonar/plugins/design/ui/widgets/package_design.html.erb"; + return "/org/sonar/server/design/package_design.html.erb"; } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index ace8404adfe..9ccca614c62 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -51,7 +51,13 @@ import org.sonar.core.measure.db.MeasureFilterDao; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; -import org.sonar.core.persistence.*; +import org.sonar.core.persistence.DaoUtils; +import org.sonar.core.persistence.DatabaseVersion; +import org.sonar.core.persistence.DefaultDatabase; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.persistence.PreviewDatabaseFactory; +import org.sonar.core.persistence.SemaphoreUpdater; +import org.sonar.core.persistence.SemaphoresImpl; import org.sonar.core.preview.PreviewCache; import org.sonar.core.profiling.Profiling; import org.sonar.core.purge.PurgeProfiler; @@ -77,25 +83,57 @@ import org.sonar.server.activity.index.ActivityNormalizer; import org.sonar.server.activity.ws.ActivitiesWebService; import org.sonar.server.activity.ws.ActivityMapping; import org.sonar.server.authentication.ws.AuthenticationWs; -import org.sonar.server.batch.*; +import org.sonar.server.batch.BatchIndex; +import org.sonar.server.batch.BatchWs; +import org.sonar.server.batch.GlobalReferentialsAction; +import org.sonar.server.batch.ProjectReferentialsAction; +import org.sonar.server.batch.UploadReportAction; import org.sonar.server.charts.ChartFactory; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.component.DefaultComponentFinder; import org.sonar.server.component.DefaultRubyComponentService; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; -import org.sonar.server.component.ws.*; +import org.sonar.server.component.ws.ComponentAppAction; +import org.sonar.server.component.ws.ComponentsWs; +import org.sonar.server.component.ws.EventsWs; +import org.sonar.server.component.ws.ProjectsWs; +import org.sonar.server.component.ws.ResourcesWs; import org.sonar.server.config.ws.PropertiesWs; import org.sonar.server.db.DatabaseChecker; import org.sonar.server.db.DbClient; import org.sonar.server.db.EmbeddedDatabaseFactory; import org.sonar.server.db.migrations.DatabaseMigrations; import org.sonar.server.db.migrations.DatabaseMigrator; -import org.sonar.server.debt.*; +import org.sonar.server.debt.DebtCharacteristicsXMLImporter; +import org.sonar.server.debt.DebtModelBackup; +import org.sonar.server.debt.DebtModelLookup; +import org.sonar.server.debt.DebtModelOperations; +import org.sonar.server.debt.DebtModelPluginRepository; +import org.sonar.server.debt.DebtModelService; +import org.sonar.server.debt.DebtModelXMLExporter; +import org.sonar.server.debt.DebtRulesXMLImporter; +import org.sonar.server.design.FileDesignWidget; +import org.sonar.server.design.PackageDesignWidget; import org.sonar.server.duplication.ws.DuplicationsJsonWriter; import org.sonar.server.duplication.ws.DuplicationsParser; import org.sonar.server.duplication.ws.DuplicationsWs; -import org.sonar.server.issue.*; +import org.sonar.server.issue.ActionService; +import org.sonar.server.issue.AssignAction; +import org.sonar.server.issue.CommentAction; +import org.sonar.server.issue.DefaultIssueFinder; +import org.sonar.server.issue.InternalRubyIssueService; +import org.sonar.server.issue.IssueBulkChangeService; +import org.sonar.server.issue.IssueChangelogFormatter; +import org.sonar.server.issue.IssueChangelogService; +import org.sonar.server.issue.IssueCommentService; +import org.sonar.server.issue.IssueService; +import org.sonar.server.issue.IssueStatsFinder; +import org.sonar.server.issue.PlanAction; +import org.sonar.server.issue.PublicRubyIssueService; +import org.sonar.server.issue.ServerIssueStorage; +import org.sonar.server.issue.SetSeverityAction; +import org.sonar.server.issue.TransitionAction; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.actionplan.ActionPlanWs; import org.sonar.server.issue.db.IssueAuthorizationDao; @@ -129,22 +167,84 @@ import org.sonar.server.platform.ws.L10nWs; import org.sonar.server.platform.ws.RestartHandler; import org.sonar.server.platform.ws.ServerWs; import org.sonar.server.platform.ws.SystemWs; -import org.sonar.server.plugins.*; +import org.sonar.server.plugins.InstalledPluginReferentialFactory; +import org.sonar.server.plugins.PluginDownloader; +import org.sonar.server.plugins.ServerExtensionInstaller; +import org.sonar.server.plugins.ServerPluginJarInstaller; +import org.sonar.server.plugins.ServerPluginJarsInstaller; +import org.sonar.server.plugins.ServerPluginRepository; +import org.sonar.server.plugins.UpdateCenterClient; +import org.sonar.server.plugins.UpdateCenterMatrixFactory; import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.qualitygate.RegisterQualityGates; -import org.sonar.server.qualitygate.ws.*; -import org.sonar.server.qualityprofile.*; +import org.sonar.server.qualitygate.ws.QGatesAppAction; +import org.sonar.server.qualitygate.ws.QGatesCopyAction; +import org.sonar.server.qualitygate.ws.QGatesCreateAction; +import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction; +import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction; +import org.sonar.server.qualitygate.ws.QGatesDeselectAction; +import org.sonar.server.qualitygate.ws.QGatesDestroyAction; +import org.sonar.server.qualitygate.ws.QGatesListAction; +import org.sonar.server.qualitygate.ws.QGatesRenameAction; +import org.sonar.server.qualitygate.ws.QGatesSearchAction; +import org.sonar.server.qualitygate.ws.QGatesSelectAction; +import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction; +import org.sonar.server.qualitygate.ws.QGatesShowAction; +import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction; +import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction; +import org.sonar.server.qualitygate.ws.QGatesWs; +import org.sonar.server.qualityprofile.BuiltInProfiles; +import org.sonar.server.qualityprofile.QProfileBackuper; +import org.sonar.server.qualityprofile.QProfileCopier; +import org.sonar.server.qualityprofile.QProfileExporters; +import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileLoader; +import org.sonar.server.qualityprofile.QProfileLookup; +import org.sonar.server.qualityprofile.QProfileProjectLookup; +import org.sonar.server.qualityprofile.QProfileProjectOperations; +import org.sonar.server.qualityprofile.QProfileRepositoryExporter; +import org.sonar.server.qualityprofile.QProfileReset; +import org.sonar.server.qualityprofile.QProfileService; +import org.sonar.server.qualityprofile.QProfiles; +import org.sonar.server.qualityprofile.RegisterQualityProfiles; +import org.sonar.server.qualityprofile.RuleActivator; +import org.sonar.server.qualityprofile.RuleActivatorContextFactory; import org.sonar.server.qualityprofile.db.ActiveRuleDao; import org.sonar.server.qualityprofile.index.ActiveRuleIndex; import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer; -import org.sonar.server.qualityprofile.ws.*; -import org.sonar.server.rule.*; +import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions; +import org.sonar.server.qualityprofile.ws.ProfilesWs; +import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction; +import org.sonar.server.qualityprofile.ws.QProfilesWs; +import org.sonar.server.qualityprofile.ws.RuleActivationActions; +import org.sonar.server.rule.DefaultRuleFinder; +import org.sonar.server.rule.DeprecatedRulesDefinition; +import org.sonar.server.rule.RegisterRules; +import org.sonar.server.rule.RubyRuleService; +import org.sonar.server.rule.RuleCreator; +import org.sonar.server.rule.RuleDefinitionsLoader; +import org.sonar.server.rule.RuleDeleter; +import org.sonar.server.rule.RuleOperations; +import org.sonar.server.rule.RuleRepositories; +import org.sonar.server.rule.RuleService; +import org.sonar.server.rule.RuleUpdater; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleNormalizer; -import org.sonar.server.rule.ws.*; -import org.sonar.server.search.*; +import org.sonar.server.rule.ws.ActiveRuleCompleter; +import org.sonar.server.rule.ws.AppAction; +import org.sonar.server.rule.ws.DeleteAction; +import org.sonar.server.rule.ws.RuleMapping; +import org.sonar.server.rule.ws.RulesWebService; +import org.sonar.server.rule.ws.SearchAction; +import org.sonar.server.rule.ws.TagsAction; +import org.sonar.server.rule.ws.UpdateAction; +import org.sonar.server.search.IndexClient; +import org.sonar.server.search.IndexQueue; +import org.sonar.server.search.IndexSynchronizer; +import org.sonar.server.search.SearchClient; +import org.sonar.server.search.SearchHealth; import org.sonar.server.source.CodeColorizers; import org.sonar.server.source.DeprecatedSourceDecorator; import org.sonar.server.source.HtmlSourceDecorator; @@ -153,9 +253,27 @@ import org.sonar.server.source.ws.ScmAction; import org.sonar.server.source.ws.ScmWriter; import org.sonar.server.source.ws.ShowAction; import org.sonar.server.source.ws.SourcesWs; -import org.sonar.server.startup.*; +import org.sonar.server.startup.CleanPreviewAnalysisCache; +import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules; +import org.sonar.server.startup.GeneratePluginIndex; +import org.sonar.server.startup.GwtPublisher; +import org.sonar.server.startup.JdbcDriverDeployer; +import org.sonar.server.startup.LogServerId; +import org.sonar.server.startup.RegisterDashboards; +import org.sonar.server.startup.RegisterDebtModel; +import org.sonar.server.startup.RegisterMetrics; +import org.sonar.server.startup.RegisterNewMeasureFilters; +import org.sonar.server.startup.RegisterPermissionTemplates; +import org.sonar.server.startup.RegisterServletFilters; +import org.sonar.server.startup.RenameDeprecatedPropertyKeys; +import org.sonar.server.startup.ServerMetadataPersister; import org.sonar.server.test.CoverageService; -import org.sonar.server.test.ws.*; +import org.sonar.server.test.ws.CoverageShowAction; +import org.sonar.server.test.ws.CoverageWs; +import org.sonar.server.test.ws.TestsCoveredFilesAction; +import org.sonar.server.test.ws.TestsShowAction; +import org.sonar.server.test.ws.TestsTestCasesAction; +import org.sonar.server.test.ws.TestsWs; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.RubyTextService; import org.sonar.server.ui.JRubyI18n; @@ -163,12 +281,23 @@ import org.sonar.server.ui.JRubyProfiling; import org.sonar.server.ui.PageDecorations; import org.sonar.server.ui.Views; import org.sonar.server.updatecenter.ws.UpdateCenterWs; -import org.sonar.server.user.*; +import org.sonar.server.user.DefaultUserService; +import org.sonar.server.user.DoPrivileged; +import org.sonar.server.user.GroupMembershipFinder; +import org.sonar.server.user.GroupMembershipService; +import org.sonar.server.user.NewUserNotifier; +import org.sonar.server.user.SecurityRealmFactory; import org.sonar.server.user.db.GroupDao; import org.sonar.server.user.ws.FavoritesWs; import org.sonar.server.user.ws.UserPropertiesWs; import org.sonar.server.user.ws.UsersWs; -import org.sonar.server.util.*; +import org.sonar.server.util.BooleanTypeValidation; +import org.sonar.server.util.FloatTypeValidation; +import org.sonar.server.util.IntegerTypeValidation; +import org.sonar.server.util.StringListTypeValidation; +import org.sonar.server.util.StringTypeValidation; +import org.sonar.server.util.TextTypeValidation; +import org.sonar.server.util.TypeValidations; import org.sonar.server.ws.ListingWs; import org.sonar.server.ws.WebServiceEngine; @@ -570,6 +699,10 @@ class ServerComponents { pico.addSingleton(StringTypeValidation.class); pico.addSingleton(StringListTypeValidation.class); + // Design + pico.addSingleton(FileDesignWidget.class); + pico.addSingleton(PackageDesignWidget.class); + for (Object components : level4AddedComponents) { pico.addSingleton(components); } diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/file_design.html.erb b/server/sonar-server/src/main/resources/org/sonar/server/design/file_design.html.erb index 2fcac1fc7a9..2fcac1fc7a9 100644 --- a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/file_design.html.erb +++ b/server/sonar-server/src/main/resources/org/sonar/server/design/file_design.html.erb diff --git a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/package_design.html.erb b/server/sonar-server/src/main/resources/org/sonar/server/design/package_design.html.erb index 5d9b7a2c796..5d9b7a2c796 100644 --- a/plugins/sonar-design-plugin/src/main/resources/org/sonar/plugins/design/ui/widgets/package_design.html.erb +++ b/server/sonar-server/src/main/resources/org/sonar/server/design/package_design.html.erb diff --git a/sonar-application/pom.xml b/sonar-application/pom.xml index 94495baba59..fda2e82eba3 100644 --- a/sonar-application/pom.xml +++ b/sonar-application/pom.xml @@ -92,13 +92,6 @@ <scope>provided</scope> </dependency> <dependency> - <groupId>org.codehaus.sonar.plugins</groupId> - <artifactId>sonar-design-plugin</artifactId> - <version>${project.version}</version> - <type>sonar-plugin</type> - <scope>provided</scope> - </dependency> - <dependency> <groupId>org.codehaus.sonar-plugins.java</groupId> <artifactId>sonar-findbugs-plugin</artifactId> <type>sonar-plugin</type> diff --git a/sonar-batch/pom.xml b/sonar-batch/pom.xml index 8a44063c151..d63d11bea9a 100644 --- a/sonar-batch/pom.xml +++ b/sonar-batch/pom.xml @@ -79,6 +79,11 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-dependency-tree</artifactId> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-project</artifactId> <scope>provided</scope> diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java index f7acd618a3a..8fcf38baafc 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java @@ -20,6 +20,12 @@ package org.sonar.batch.bootstrap; import com.google.common.collect.Lists; +import org.sonar.batch.design.DirectoryDsmDecorator; +import org.sonar.batch.design.DirectoryTangleIndexDecorator; +import org.sonar.batch.design.FileTangleIndexDecorator; +import org.sonar.batch.design.MavenDependenciesSensor; +import org.sonar.batch.design.ProjectDsmDecorator; +import org.sonar.batch.design.SubProjectDsmDecorator; import org.sonar.batch.maven.DefaultMavenPluginExecutor; import org.sonar.batch.maven.MavenProjectBootstrapper; import org.sonar.batch.maven.MavenProjectBuilder; @@ -37,7 +43,15 @@ public class BatchComponents { public static Collection all() { List components = Lists.newArrayList( // Maven - MavenProjectBootstrapper.class, DefaultMavenPluginExecutor.class, MavenProjectConverter.class, MavenProjectBuilder.class + MavenProjectBootstrapper.class, DefaultMavenPluginExecutor.class, MavenProjectConverter.class, MavenProjectBuilder.class, + + // Design + MavenDependenciesSensor.class, + ProjectDsmDecorator.class, + SubProjectDsmDecorator.class, + DirectoryDsmDecorator.class, + DirectoryTangleIndexDecorator.class, + FileTangleIndexDecorator.class ); components.addAll(CorePropertyDefinitions.all()); return components; diff --git a/sonar-batch/src/main/java/org/sonar/batch/dependency/OutgoingDependency.java b/sonar-batch/src/main/java/org/sonar/batch/dependency/OutgoingDependency.java index b768687b040..0869ee6cde6 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/dependency/OutgoingDependency.java +++ b/sonar-batch/src/main/java/org/sonar/batch/dependency/OutgoingDependency.java @@ -24,19 +24,19 @@ import org.sonar.api.batch.fs.InputFile; public class OutgoingDependency { private final InputFile to; - private final String usage; + private final int weight; - public OutgoingDependency(InputFile to, String usage) { + public OutgoingDependency(InputFile to, int weight) { this.to = to; - this.usage = usage; + this.weight = weight; } public InputFile to() { return to; } - public String usage() { - return usage; + public int weight() { + return weight; } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/design/DirectoryDsmDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/design/DirectoryDsmDecorator.java new file mode 100644 index 00000000000..0aaa2aa854d --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/design/DirectoryDsmDecorator.java @@ -0,0 +1,123 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.design; + +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.SonarIndex; +import org.sonar.api.design.Dependency; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.PersistenceMode; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.graph.Cycle; +import org.sonar.graph.Dsm; +import org.sonar.graph.DsmTopologicalSorter; +import org.sonar.graph.Edge; +import org.sonar.graph.IncrementalCyclesAndFESSolver; +import org.sonar.graph.MinimumFeedbackEdgeSetSolver; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public class DirectoryDsmDecorator implements Decorator { + + private SonarIndex index; + + public DirectoryDsmDecorator(SonarIndex index) { + this.index = index; + } + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + public void decorate(final Resource resource, DecoratorContext context) { + if (shouldDecorateResource(resource, context)) { + List<DecoratorContext> fileContexts = context.getChildren(); + List<Resource> files = new ArrayList<Resource>(fileContexts.size()); + for (DecoratorContext decoratorContext : fileContexts) { + files.add(decoratorContext.getResource()); + } + + IncrementalCyclesAndFESSolver<Resource> cycleDetector = new IncrementalCyclesAndFESSolver<Resource>(index, files); + Set<Cycle> cycles = cycleDetector.getCycles(); + + MinimumFeedbackEdgeSetSolver solver = new MinimumFeedbackEdgeSetSolver(cycles); + Set<Edge> feedbackEdges = solver.getEdges(); + int tangles = solver.getWeightOfFeedbackEdgeSet(); + + savePositiveMeasure(context, CoreMetrics.FILE_CYCLES, cycles.size()); + savePositiveMeasure(context, CoreMetrics.FILE_FEEDBACK_EDGES, feedbackEdges.size()); + savePositiveMeasure(context, CoreMetrics.FILE_TANGLES, tangles); + savePositiveMeasure(context, CoreMetrics.FILE_EDGES_WEIGHT, getEdgesWeight(files)); + + Dsm<Resource> dsm = getDsm(files, feedbackEdges); + saveDsm(context, dsm); + } + } + + private void savePositiveMeasure(DecoratorContext context, Metric<Integer> metric, double value) { + if (value >= 0.0) { + context.saveMeasure(new Measure(metric, value)); + } + } + + private int getEdgesWeight(Collection<Resource> sourceCodes) { + List<Dependency> edges = getEdges(sourceCodes); + int total = 0; + for (Dependency edge : edges) { + total += edge.getWeight(); + } + return total; + } + + public List<Dependency> getEdges(Collection<Resource> vertices) { + List<Dependency> result = new ArrayList<Dependency>(); + for (Resource vertice : vertices) { + Collection<Dependency> outgoingEdges = index.getOutgoingEdges(vertice); + if (outgoingEdges != null) { + result.addAll(outgoingEdges); + } + } + return result; + } + + private void saveDsm(DecoratorContext context, Dsm<Resource> dsm) { + Measure measure = new Measure(CoreMetrics.DEPENDENCY_MATRIX, DsmSerializer.serialize(dsm)); + measure.setPersistenceMode(PersistenceMode.DATABASE); + context.saveMeasure(measure); + } + + private Dsm<Resource> getDsm(Collection<Resource> files, Set<Edge> feedbackEdges) { + Dsm<Resource> dsm = new Dsm<Resource>(index, files, feedbackEdges); + DsmTopologicalSorter.sort(dsm); + return dsm; + } + + private boolean shouldDecorateResource(Resource resource, DecoratorContext context) { + return ResourceUtils.isDirectory(resource) && context.getMeasure(CoreMetrics.DEPENDENCY_MATRIX) == null; + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/PackageTangleIndexDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/design/DirectoryTangleIndexDecorator.java index 50072e3c8dd..b1fc52c9625 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/PackageTangleIndexDecorator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/design/DirectoryTangleIndexDecorator.java @@ -17,13 +17,13 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import org.sonar.api.measures.CoreMetrics; -public class PackageTangleIndexDecorator extends TangleIndexDecorator { +public class DirectoryTangleIndexDecorator extends TangleIndexDecorator { - public PackageTangleIndexDecorator() { + public DirectoryTangleIndexDecorator() { super(CoreMetrics.PACKAGE_TANGLES, CoreMetrics.PACKAGE_EDGES_WEIGHT, CoreMetrics.PACKAGE_TANGLE_INDEX); } diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/DsmSerializer.java b/sonar-batch/src/main/java/org/sonar/batch/design/DsmSerializer.java index 01415ebb98b..48da21bd0c2 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/DsmSerializer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/design/DsmSerializer.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import org.sonar.api.design.Dependency; import org.sonar.api.resources.Resource; diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/FileTangleIndexDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/design/FileTangleIndexDecorator.java index 49c365bb7e9..079e3774ebd 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/FileTangleIndexDecorator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/design/FileTangleIndexDecorator.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import org.sonar.api.measures.CoreMetrics; diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/MavenDependenciesSensor.java b/sonar-batch/src/main/java/org/sonar/batch/design/MavenDependenciesSensor.java index 49324d7340c..0f2e7157b22 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/MavenDependenciesSensor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/design/MavenDependenciesSensor.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import com.google.gson.Gson; import com.google.gson.GsonBuilder; diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/ProjectDsmDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/design/ProjectDsmDecorator.java index c84a98ebee0..03a74c830af 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/ProjectDsmDecorator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/design/ProjectDsmDecorator.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import com.google.common.collect.Lists; import org.sonar.api.batch.Decorator; @@ -29,19 +29,19 @@ import org.sonar.api.measures.PersistenceMode; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; -import org.sonar.graph.*; +import org.sonar.graph.Cycle; +import org.sonar.graph.CycleDetector; +import org.sonar.graph.Dsm; +import org.sonar.graph.DsmTopologicalSorter; +import org.sonar.graph.Edge; +import org.sonar.graph.MinimumFeedbackEdgeSetSolver; import java.util.Collection; import java.util.List; import java.util.Set; -/** - * For performance reasons, this decorator is currently limited to matrix between modules. - * Squid is optimized for cycle detections (better hashCode and equals methods of SourceCode classes than Resource). - */ public class ProjectDsmDecorator implements Decorator { - // hack as long as DecoratorContext does not implement SonarIndex private SonarIndex index; public ProjectDsmDecorator(SonarIndex index) { @@ -101,6 +101,6 @@ public class ProjectDsmDecorator implements Decorator { } private boolean shouldDecorateResource(Resource resource, DecoratorContext context) { - return ResourceUtils.isProject(resource) && context.getMeasure(CoreMetrics.DEPENDENCY_MATRIX) == null; + return ResourceUtils.isProject(resource) && !((Project) resource).getModules().isEmpty(); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/design/SubProjectDsmDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/design/SubProjectDsmDecorator.java new file mode 100644 index 00000000000..b0556819c1d --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/design/SubProjectDsmDecorator.java @@ -0,0 +1,123 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.design; + +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.SonarIndex; +import org.sonar.api.design.Dependency; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.PersistenceMode; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.graph.Cycle; +import org.sonar.graph.Dsm; +import org.sonar.graph.DsmTopologicalSorter; +import org.sonar.graph.Edge; +import org.sonar.graph.IncrementalCyclesAndFESSolver; +import org.sonar.graph.MinimumFeedbackEdgeSetSolver; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public class SubProjectDsmDecorator implements Decorator { + + private SonarIndex index; + + public SubProjectDsmDecorator(SonarIndex index) { + this.index = index; + } + + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + public void decorate(final Resource resource, DecoratorContext context) { + if (shouldDecorateResource(resource, context)) { + List<DecoratorContext> directoryContexts = context.getChildren(); + List<Resource> directories = new ArrayList<Resource>(directoryContexts.size()); + for (DecoratorContext decoratorContext : directoryContexts) { + directories.add(decoratorContext.getResource()); + } + + IncrementalCyclesAndFESSolver<Resource> cycleDetector = new IncrementalCyclesAndFESSolver<Resource>(index, directories); + Set<Cycle> cycles = cycleDetector.getCycles(); + + MinimumFeedbackEdgeSetSolver solver = new MinimumFeedbackEdgeSetSolver(cycles); + Set<Edge> feedbackEdges = solver.getEdges(); + int tangles = solver.getWeightOfFeedbackEdgeSet(); + + savePositiveMeasure(context, CoreMetrics.DIRECTORY_CYCLES, cycles.size()); + savePositiveMeasure(context, CoreMetrics.DIRECTORY_FEEDBACK_EDGES, feedbackEdges.size()); + savePositiveMeasure(context, CoreMetrics.DIRECTORY_TANGLES, tangles); + savePositiveMeasure(context, CoreMetrics.DIRECTORY_EDGES_WEIGHT, getEdgesWeight(directories)); + + Dsm<Resource> dsm = getDsm(directories, feedbackEdges); + saveDsm(context, dsm); + } + } + + private void savePositiveMeasure(DecoratorContext context, Metric<Integer> metric, double value) { + if (value >= 0.0) { + context.saveMeasure(new Measure(metric, value)); + } + } + + private int getEdgesWeight(Collection<Resource> sourceCodes) { + List<Dependency> edges = getEdges(sourceCodes); + int total = 0; + for (Dependency edge : edges) { + total += edge.getWeight(); + } + return total; + } + + public List<Dependency> getEdges(Collection<Resource> vertices) { + List<Dependency> result = new ArrayList<Dependency>(); + for (Resource vertice : vertices) { + Collection<Dependency> outgoingEdges = index.getOutgoingEdges(vertice); + if (outgoingEdges != null) { + result.addAll(outgoingEdges); + } + } + return result; + } + + private void saveDsm(DecoratorContext context, Dsm<Resource> dsm) { + Measure measure = new Measure(CoreMetrics.DEPENDENCY_MATRIX, DsmSerializer.serialize(dsm)); + measure.setPersistenceMode(PersistenceMode.DATABASE); + context.saveMeasure(measure); + } + + private Dsm<Resource> getDsm(Collection<Resource> directories, Set<Edge> feedbackEdges) { + Dsm<Resource> dsm = new Dsm<Resource>(index, directories, feedbackEdges); + DsmTopologicalSorter.sort(dsm); + return dsm; + } + + private boolean shouldDecorateResource(Resource resource, DecoratorContext context) { + return ResourceUtils.isProject(resource) && ((Project) resource).getModules().isEmpty(); + } +} diff --git a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/TangleIndexDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/design/TangleIndexDecorator.java index 8c5c5cead5a..c4c1cc3a241 100644 --- a/plugins/sonar-design-plugin/src/main/java/org/sonar/plugins/design/batch/TangleIndexDecorator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/design/TangleIndexDecorator.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import org.sonar.api.batch.Decorator; import org.sonar.api.batch.DecoratorContext; diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java index 17d935699cd..d73f1fcab1a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java @@ -53,6 +53,7 @@ import org.sonar.batch.ProjectTree; import org.sonar.batch.issue.DeprecatedViolations; import org.sonar.batch.issue.ModuleIssues; import org.sonar.batch.scan.measure.MeasureCache; +import org.sonar.batch.scan2.DefaultSensorContext; import org.sonar.core.component.ComponentKeys; import org.sonar.core.component.ScanGraph; @@ -214,6 +215,10 @@ public class DefaultIndex extends SonarIndex { if (metric == null) { throw new SonarException("Unknown metric: " + measure.getMetricKey()); } + if (DefaultSensorContext.INTERNAL_METRICS.contains(metric)) { + LOG.warn("Metric " + metric + " is an internal metric computed by SonarQube. Please update your plugin."); + return measure; + } measure.setMetric(metric); if (measureCache.contains(resource, measure)) { throw new SonarException("Can not add the same measure twice on " + resource + ": " + measure); diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java index e17c5a087d5..001fc1ad72d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java @@ -20,7 +20,6 @@ package org.sonar.batch.mediumtest; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.SonarPlugin; @@ -235,7 +234,7 @@ public class BatchMediumTester { private Map<InputFile, SymbolData> symbolTablePerFile = new HashMap<InputFile, SymbolData>(); private Map<String, Map<String, TestCase>> testCasesPerFile = new HashMap<String, Map<String, TestCase>>(); private Map<String, Map<String, Map<String, List<Integer>>>> coveragePerTest = new HashMap<String, Map<String, Map<String, List<Integer>>>>(); - private Map<String, Map<String, String>> dependencies = new HashMap<String, Map<String, String>>(); + private Map<String, Map<String, Integer>> dependencies = new HashMap<String, Map<String, Integer>>(); @Override public void scanTaskCompleted(ProjectScanContainer container) { @@ -322,9 +321,9 @@ public class BatchMediumTester { String fromKey = entry.key()[1].toString(); String toKey = entry.key()[2].toString(); if (!dependencies.containsKey(fromKey)) { - dependencies.put(fromKey, new HashMap<String, String>()); + dependencies.put(fromKey, new HashMap<String, Integer>()); } - dependencies.get(fromKey).put(toKey, StringUtils.trimToEmpty(entry.value().usage())); + dependencies.get(fromKey).put(toKey, entry.value().weight()); } } @@ -409,10 +408,10 @@ public class BatchMediumTester { } /** - * @return null if no dependency else return dependency usage. + * @return null if no dependency else return dependency weight. */ @CheckForNull - public String dependencyUsage(InputFile from, InputFile to) { + public Integer dependencyWeight(InputFile from, InputFile to) { String fromKey = ((DefaultInputFile) from).key(); String toKey = ((DefaultInputFile) to).key(); return dependencies.containsKey(fromKey) ? dependencies.get(fromKey).get(toKey) : null; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java index 64ef5fb2ddc..ae6b1aa4ee6 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java @@ -147,7 +147,7 @@ public class ModuleScanContainer extends ComponentContainer { TimeMachineConfiguration.class, DefaultSensorContext.class, - SensorContextAdaptor.class, + SensorContextAdapter.class, BatchExtensionDictionnary.class, DefaultTimeMachine.class, ViolationFilters.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java index 59375015b11..121a106a9be 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java @@ -20,7 +20,10 @@ package org.sonar.batch.scan; import com.google.common.base.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SonarIndex; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputDir; import org.sonar.api.batch.fs.InputFile; @@ -67,21 +70,25 @@ import java.util.List; * Will be dropped once old {@link Sensor} API is dropped. * */ -public class SensorContextAdaptor extends BaseSensorContext { +public class SensorContextAdapter extends BaseSensorContext { + + private static final Logger LOG = LoggerFactory.getLogger(SensorContextAdapter.class); private final org.sonar.api.batch.SensorContext sensorContext; private final MetricFinder metricFinder; private final Project project; private final ResourcePerspectives perspectives; + private final SonarIndex sonarIndex; - public SensorContextAdaptor(org.sonar.api.batch.SensorContext sensorContext, MetricFinder metricFinder, Project project, ResourcePerspectives perspectives, + public SensorContextAdapter(org.sonar.api.batch.SensorContext sensorContext, MetricFinder metricFinder, Project project, ResourcePerspectives perspectives, Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache, - DuplicationCache duplicationCache) { + DuplicationCache duplicationCache, SonarIndex sonarIndex) { super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache); this.sensorContext = sensorContext; this.metricFinder = metricFinder; this.project = project; this.perspectives = perspectives; + this.sonarIndex = sonarIndex; } @Override @@ -139,7 +146,6 @@ public class SensorContextAdaptor extends BaseSensorContext { if (m == null) { throw new IllegalStateException("Unknow metric with key: " + measure.metric().key()); } - org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m); setValueAccordingToMetricType(measure, m, measureToSave); if (measure.inputFile() != null) { @@ -297,18 +303,27 @@ public class SensorContextAdaptor extends BaseSensorContext { } @Override - public void saveDependency(InputFile from, InputFile to, String usage) { + public void saveDependency(InputFile from, InputFile to, int weight) { File fromResource = getFile(from); File toResource = getFile(to); + if (sonarIndex.getEdge(fromResource, toResource) != null) { + throw new IllegalStateException("Dependency between " + from + " and " + to + " was already saved."); + } Directory fromParent = fromResource.getParent(); Directory toParent = toResource.getParent(); Dependency parentDep = null; if (!fromParent.equals(toParent)) { - parentDep = new Dependency(fromParent, toParent).setUsage("USES"); - parentDep = sensorContext.saveDependency(parentDep); + parentDep = sonarIndex.getEdge(fromParent, toParent); + if (parentDep != null) { + parentDep.setWeight(parentDep.getWeight() + 1); + } else { + parentDep = new Dependency(fromParent, toParent).setUsage("USES").setWeight(1); + parentDep = sensorContext.saveDependency(parentDep); + } } sensorContext.saveDependency(new Dependency(fromResource, toResource) - .setUsage(usage) + .setUsage("USES") + .setWeight(weight) .setParent(parentDep)); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java index 48a74cccd81..ddbfd0c5d3f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java @@ -43,7 +43,7 @@ import org.sonar.batch.duplication.DefaultTokenBuilder; import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.highlighting.DefaultHighlightingBuilder; import org.sonar.batch.index.ComponentDataCache; -import org.sonar.batch.scan.SensorContextAdaptor; +import org.sonar.batch.scan.SensorContextAdapter; import org.sonar.batch.symbol.DefaultSymbolTableBuilder; import org.sonar.duplications.internal.pmd.PmdBlockChunker; @@ -51,7 +51,7 @@ import java.io.Serializable; import java.util.List; /** - * Common bits between {@link DefaultSensorContext} and {@link SensorContextAdaptor} + * Common bits between {@link DefaultSensorContext} and {@link SensorContextAdapter} * @author julien * */ diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java index 1ceee76c6d7..57d362c699d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java @@ -21,6 +21,8 @@ package org.sonar.batch.scan2; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; @@ -35,6 +37,7 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.batch.sensor.test.TestCase; import org.sonar.api.batch.sensor.test.internal.DefaultTestCase; import org.sonar.api.config.Settings; +import org.sonar.api.measures.CoreMetrics; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.MessageException; import org.sonar.batch.dependency.DependencyCache; @@ -43,16 +46,31 @@ import org.sonar.batch.duplication.BlockCache; import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.index.ComponentDataCache; import org.sonar.batch.issue.IssueFilters; -import org.sonar.batch.scan.SensorContextAdaptor; +import org.sonar.batch.scan.SensorContextAdapter; import org.sonar.batch.test.CoveragePerTestCache; import org.sonar.batch.test.TestCaseCache; import org.sonar.core.component.ComponentKeys; import java.io.Serializable; +import java.util.Arrays; import java.util.List; public class DefaultSensorContext extends BaseSensorContext { + private static final Logger LOG = LoggerFactory.getLogger(DefaultSensorContext.class); + + public static final List<Metric> INTERNAL_METRICS = Arrays.<Metric>asList(CoreMetrics.DEPENDENCY_MATRIX, + CoreMetrics.DIRECTORY_CYCLES, + CoreMetrics.DIRECTORY_EDGES_WEIGHT, + CoreMetrics.DIRECTORY_FEEDBACK_EDGES, + CoreMetrics.DIRECTORY_TANGLE_INDEX, + CoreMetrics.DIRECTORY_TANGLES, + CoreMetrics.FILE_CYCLES, + CoreMetrics.FILE_EDGES_WEIGHT, + CoreMetrics.FILE_FEEDBACK_EDGES, + CoreMetrics.FILE_TANGLE_INDEX, + CoreMetrics.FILE_TANGLES + ); private final AnalyzerMeasureCache measureCache; private final AnalyzerIssueCache issueCache; private final ProjectDefinition def; @@ -98,6 +116,10 @@ public class DefaultSensorContext extends BaseSensorContext { @Override public void addMeasure(Measure<?> measure) { + if (INTERNAL_METRICS.contains(measure.metric())) { + LOG.warn("Metric " + measure.metric() + " is an internal metric computed by SonarQube. Please update your plugin."); + return; + } InputFile inputFile = measure.inputFile(); if (inputFile != null) { measureCache.put(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), inputFile), (DefaultMeasure) measure); @@ -126,7 +148,7 @@ public class DefaultSensorContext extends BaseSensorContext { updateIssue((DefaultIssue) issue, activeRule); - if (issueFilters.accept(SensorContextAdaptor.toDefaultIssue(def.getKey(), resourceKey, issue), null)) { + if (issueFilters.accept(SensorContextAdapter.toDefaultIssue(def.getKey(), resourceKey, issue), null)) { issueCache.put(def.getKey(), resourceKey, (DefaultIssue) issue); return true; } @@ -165,10 +187,10 @@ public class DefaultSensorContext extends BaseSensorContext { } @Override - public void saveDependency(InputFile from, InputFile to, String usage) { + public void saveDependency(InputFile from, InputFile to, int weight) { Preconditions.checkNotNull(from); Preconditions.checkNotNull(to); - OutgoingDependency dep = new OutgoingDependency(to, usage); + OutgoingDependency dep = new OutgoingDependency(to, weight); dependencyCache.put(def.getKey(), from, dep); } diff --git a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/DsmSerializerTest.java b/sonar-batch/src/test/java/org/sonar/batch/design/DsmSerializerTest.java index 4cff2b11f1b..24d949d000c 100644 --- a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/DsmSerializerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/design/DsmSerializerTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import org.apache.commons.io.IOUtils; import org.junit.Test; @@ -54,7 +54,7 @@ public class DsmSerializerTest { Dsm<Resource> dsm = new Dsm<Resource>(graph); DsmManualSorter.sort(dsm, bar, foo); // for test reproductibility - String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/plugins/design/batch/DsmSerializerTest/dsm.json")).trim(); + String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/batch/design/DsmSerializerTest/dsm.json")).trim(); assertThat(DsmSerializer.serialize(dsm), is(json)); } } diff --git a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/MavenDependenciesSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/design/MavenDependenciesSensorTest.java index cf3221d7bf9..504b82981a0 100644 --- a/plugins/sonar-design-plugin/src/test/java/org/sonar/plugins/design/batch/MavenDependenciesSensorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/design/MavenDependenciesSensorTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.design.batch; +package org.sonar.batch.design; import org.junit.Before; import org.junit.Test; diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java index addf1f8bb0c..f6fd70f4a5c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.SonarIndex; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.DefaultInputFile; @@ -58,7 +59,7 @@ public class SensorContextAdapterTest { private ActiveRules activeRules; private DefaultFileSystem fs; - private SensorContextAdaptor adaptor; + private SensorContextAdapter adaptor; private SensorContext sensorContext; private Settings settings; private ResourcePerspectives resourcePerspectives; @@ -74,8 +75,8 @@ public class SensorContextAdapterTest { resourcePerspectives = mock(ResourcePerspectives.class); ComponentDataCache componentDataCache = mock(ComponentDataCache.class); BlockCache blockCache = mock(BlockCache.class); - adaptor = new SensorContextAdaptor(sensorContext, metricFinder, new Project("myProject"), - resourcePerspectives, settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class)); + adaptor = new SensorContextAdapter(sensorContext, metricFinder, new Project("myProject"), + resourcePerspectives, settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class), mock(SonarIndex.class)); } @Test diff --git a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/DsmSerializerTest/dsm.json b/sonar-batch/src/test/resources/org/sonar/batch/design/DsmSerializerTest/dsm.json index 57996b089e7..57996b089e7 100644 --- a/plugins/sonar-design-plugin/src/test/resources/org/sonar/plugins/design/batch/DsmSerializerTest/dsm.json +++ b/sonar-batch/src/test/resources/org/sonar/batch/design/DsmSerializerTest/dsm.json diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java index ea96a8678b1..4ad0c7999df 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java @@ -187,9 +187,6 @@ public interface SensorContext { // ----------- DEPENDENCIES BETWEEN RESOURCES -------------- - /** - * Build a new dependency : from depends upon to. The dependency is NOT saved. The method saveDependency() must still be executed. - */ Dependency saveDependency(Dependency dependency); Set<Dependency> getDependencies(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index 1729795b06d..f04ad6a9d7f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -194,9 +194,9 @@ public interface SensorContext { /** * Declare a dependency between 2 files. - * @param usage A qualifier for the dependency. + * @param weight Weight of the dependency * @since 5.0 */ - void saveDependency(InputFile from, InputFile to, String usage); + void saveDependency(InputFile from, InputFile to, int weight); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java index 3269bd99336..aa19c57b6f1 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java @@ -29,6 +29,7 @@ import org.sonar.api.utils.SonarException; import javax.annotation.Nullable; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.List; /** @@ -1806,7 +1807,15 @@ public final class CoreMetrics { .setHidden(true) .create(); + /** + * @deprecated since 5.0 this is an internal metric that should not be accessed by plugins + */ + @Deprecated public static final String DEPENDENCY_MATRIX_KEY = "dsm"; + /** + * @deprecated since 5.0 this is an internal metric that should not be accessed by plugins + */ + @Deprecated public static final Metric<String> DEPENDENCY_MATRIX = new Metric.Builder(DEPENDENCY_MATRIX_KEY, "Dependency Matrix", Metric.ValueType.DATA) .setDescription("Dependency Matrix") .setDirection(Metric.DIRECTION_NONE) @@ -1815,9 +1824,9 @@ public final class CoreMetrics { .setDeleteHistoricalData(true) .create(); - public static final String PACKAGE_CYCLES_KEY = "package_cycles"; - public static final Metric<Integer> PACKAGE_CYCLES = new Metric.Builder(PACKAGE_CYCLES_KEY, "Package cycles", Metric.ValueType.INT) - .setDescription("Package cycles") + public static final String DIRECTORY_CYCLES_KEY = "package_cycles"; + public static final Metric<Integer> DIRECTORY_CYCLES = new Metric.Builder(DIRECTORY_CYCLES_KEY, "Directory cycles", Metric.ValueType.INT) + .setDescription("Directory cycles") .setDirection(Metric.DIRECTION_WORST) .setQualitative(true) .setDomain(DOMAIN_DESIGN) @@ -1825,17 +1834,39 @@ public final class CoreMetrics { .setFormula(new SumChildValuesFormula(false)) .create(); - public static final String PACKAGE_TANGLE_INDEX_KEY = "package_tangle_index"; - public static final Metric<Double> PACKAGE_TANGLE_INDEX = new Metric.Builder(PACKAGE_TANGLE_INDEX_KEY, "Package tangle index", Metric.ValueType.PERCENT) - .setDescription("Package tangle index") + /** + * @deprecated since 5.0 use {@link #DIRECTORY_CYCLES_KEY} + */ + @Deprecated + public transient static final String PACKAGE_CYCLES_KEY = DIRECTORY_CYCLES_KEY; + /** + * @deprecated since 5.0 use {@link #DIRECTORY_CYCLES} + */ + @Deprecated + public transient static final Metric<Integer> PACKAGE_CYCLES = DIRECTORY_CYCLES; + + public static final String DIRECTORY_TANGLE_INDEX_KEY = "package_tangle_index"; + public static final Metric<Double> DIRECTORY_TANGLE_INDEX = new Metric.Builder(DIRECTORY_TANGLE_INDEX_KEY, "Directory tangle index", Metric.ValueType.PERCENT) + .setDescription("Directory tangle index") .setDirection(Metric.DIRECTION_WORST) .setQualitative(true) .setBestValue(0.0) .setDomain(DOMAIN_DESIGN) .create(); - public static final String PACKAGE_TANGLES_KEY = "package_tangles"; - public static final Metric<Integer> PACKAGE_TANGLES = new Metric.Builder(PACKAGE_TANGLES_KEY, "File dependencies to cut", Metric.ValueType.INT) + /** + * @deprecated since 5.0 use {@link #DIRECTORY_TANGLE_INDEX_KEY} + */ + @Deprecated + public transient static final String PACKAGE_TANGLE_INDEX_KEY = DIRECTORY_TANGLE_INDEX_KEY; + /** + * @deprecated since 5.0 use {@link #DIRECTORY_TANGLE_INDEX} + */ + @Deprecated + public transient static final Metric<Double> PACKAGE_TANGLE_INDEX = DIRECTORY_TANGLE_INDEX; + + public static final String DIRECTORY_TANGLES_KEY = "package_tangles"; + public static final Metric<Integer> DIRECTORY_TANGLES = new Metric.Builder(DIRECTORY_TANGLES_KEY, "File dependencies to cut", Metric.ValueType.INT) .setDescription("File dependencies to cut") .setDirection(Metric.DIRECTION_WORST) .setQualitative(false) @@ -1843,8 +1874,19 @@ public final class CoreMetrics { .setFormula(new SumChildValuesFormula(false)) .create(); - public static final String PACKAGE_FEEDBACK_EDGES_KEY = "package_feedback_edges"; - public static final Metric<Integer> PACKAGE_FEEDBACK_EDGES = new Metric.Builder(PACKAGE_FEEDBACK_EDGES_KEY, "Package dependencies to cut", Metric.ValueType.INT) + /** + * @deprecated since 5.0 use {@link #DIRECTORY_TANGLES_KEY} + */ + @Deprecated + public transient static final String PACKAGE_TANGLES_KEY = DIRECTORY_TANGLES_KEY; + /** + * @deprecated since 5.0 use {@link #DIRECTORY_TANGLES} + */ + @Deprecated + public transient static final Metric<Integer> PACKAGE_TANGLES = DIRECTORY_TANGLES; + + public static final String DIRECTORY_FEEDBACK_EDGES_KEY = "package_feedback_edges"; + public static final Metric<Integer> DIRECTORY_FEEDBACK_EDGES = new Metric.Builder(DIRECTORY_FEEDBACK_EDGES_KEY, "Package dependencies to cut", Metric.ValueType.INT) .setDescription("Package dependencies to cut") .setDirection(Metric.DIRECTION_WORST) .setQualitative(false) @@ -1853,9 +1895,20 @@ public final class CoreMetrics { .setBestValue(0.0) .create(); - public static final String PACKAGE_EDGES_WEIGHT_KEY = "package_edges_weight"; - public static final Metric<Integer> PACKAGE_EDGES_WEIGHT = new Metric.Builder(PACKAGE_EDGES_WEIGHT_KEY, "Package edges weight", Metric.ValueType.INT) - .setDescription("Package edges weight") + /** + * @deprecated since 5.0 use {@link #DIRECTORY_FEEDBACK_EDGES_KEY} + */ + @Deprecated + public transient static final String PACKAGE_FEEDBACK_EDGES_KEY = DIRECTORY_FEEDBACK_EDGES_KEY; + /** + * @deprecated since 5.0 use {@link #DIRECTORY_FEEDBACK_EDGES} + */ + @Deprecated + public transient static final Metric<Integer> PACKAGE_FEEDBACK_EDGES = DIRECTORY_FEEDBACK_EDGES; + + public static final String DIRECTORY_EDGES_WEIGHT_KEY = "package_edges_weight"; + public static final Metric<Integer> DIRECTORY_EDGES_WEIGHT = new Metric.Builder(DIRECTORY_EDGES_WEIGHT_KEY, "Directory edges weight", Metric.ValueType.INT) + .setDescription("Directory edges weight") .setDirection(Metric.DIRECTION_BETTER) .setQualitative(false) .setDomain(DOMAIN_DESIGN) @@ -1864,6 +1917,17 @@ public final class CoreMetrics { .setDeleteHistoricalData(true) .create(); + /** + * @deprecated since 5.0 use {@link #DIRECTORY_EDGES_WEIGHT_KEY} + */ + @Deprecated + public transient static final String PACKAGE_EDGES_WEIGHT_KEY = DIRECTORY_EDGES_WEIGHT_KEY; + /** + * @deprecated since 5.0 use {@link #DIRECTORY_EDGES_WEIGHT} + */ + @Deprecated + public transient static final Metric<Integer> PACKAGE_EDGES_WEIGHT = DIRECTORY_EDGES_WEIGHT; + public static final String FILE_CYCLES_KEY = "file_cycles"; public static final Metric<Integer> FILE_CYCLES = new Metric.Builder(FILE_CYCLES_KEY, "File cycles", Metric.ValueType.INT) .setDescription("File cycles") @@ -2321,7 +2385,7 @@ public final class CoreMetrics { static { METRICS = Lists.newLinkedList(); for (Field field : CoreMetrics.class.getFields()) { - if (Metric.class.isAssignableFrom(field.getType())) { + if (!Modifier.isTransient(field.getModifiers()) && Metric.class.isAssignableFrom(field.getType())) { try { Metric metric = (Metric) field.get(null); METRICS.add(metric); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java index 92b832e2993..eca54787ee4 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoverageMeasuresBuilder.java @@ -21,6 +21,8 @@ package org.sonar.api.measures; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.utils.KeyValueFormat; import java.util.Arrays; @@ -109,6 +111,10 @@ public final class CoverageMeasuresBuilder { return Collections.unmodifiableSortedMap(coveredConditionsByLine); } + /** + * @deprecated since 5.0 use {@link #createMeasures(SensorContext, InputFile)} + */ + @Deprecated public Collection<Measure> createMeasures() { Collection<Measure> measures = Lists.newArrayList(); if (getLinesToCover() > 0) { @@ -125,6 +131,42 @@ public final class CoverageMeasuresBuilder { return measures; } + public Collection<org.sonar.api.batch.sensor.measure.Measure> createMeasures(SensorContext context, InputFile onFile) { + Collection<org.sonar.api.batch.sensor.measure.Measure> measures = Lists.newArrayList(); + if (getLinesToCover() > 0) { + measures.add(context.<Integer>measureBuilder() + .onFile(onFile) + .forMetric(CoreMetrics.LINES_TO_COVER) + .withValue(getLinesToCover()) + .build()); + measures.add(context.<Integer>measureBuilder() + .onFile(onFile) + .forMetric(CoreMetrics.UNCOVERED_LINES) + .withValue(getLinesToCover() - getCoveredLines()) + .build()); + measures.add(context.<String>measureBuilder() + .onFile(onFile) + .forMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA) + .withValue(KeyValueFormat.format(hitsByLine)) + .build()); + } + if (getConditions() > 0) { + measures.add(context.<Integer>measureBuilder() + .onFile(onFile) + .forMetric(CoreMetrics.CONDITIONS_TO_COVER) + .withValue(getConditions()) + .build()); + measures.add(context.<Integer>measureBuilder() + .onFile(onFile) + .forMetric(CoreMetrics.UNCOVERED_CONDITIONS) + .withValue(getConditions() - getCoveredConditions()) + .build()); + measures.add(createConditionsByLine(context, onFile)); + measures.add(createCoveredConditionsByLine(context, onFile)); + } + return measures; + } + private Measure createCoveredConditionsByLine() { return new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE) .setData(KeyValueFormat.format(coveredConditionsByLine)) @@ -137,7 +179,24 @@ public final class CoverageMeasuresBuilder { .setPersistenceMode(PersistenceMode.DATABASE); } + private org.sonar.api.batch.sensor.measure.Measure createCoveredConditionsByLine(SensorContext context, InputFile onFile) { + return context.<String>measureBuilder() + .onFile(onFile) + .forMetric(CoreMetrics.COVERED_CONDITIONS_BY_LINE) + .withValue(KeyValueFormat.format(coveredConditionsByLine)) + .build(); + } + + private org.sonar.api.batch.sensor.measure.Measure createConditionsByLine(SensorContext context, InputFile onFile) { + return context.<String>measureBuilder() + .onFile(onFile) + .forMetric(CoreMetrics.CONDITIONS_BY_LINE) + .withValue(KeyValueFormat.format(conditionsByLine)) + .build(); + } + public static CoverageMeasuresBuilder create() { return new CoverageMeasuresBuilder(); } + } |