<div class="js-rule-custom-rules"></div>
<div class="js-rule-profiles"></div>
+<div class="js-rule-issues"></div>
--- /dev/null
+<h3 class="coding-rules-detail-title">
+ {{t 'coding_rules.issues'}} (<a class="js-rule-issues" href="{{baseSearchUrl}}" target="_blank">{{total}}</a>)
+</h3>
+
+{{#notEmpty projects}}
+ <table class="coding-rules-detail-list coding-rules-most-violated-projects">
+ <tr>
+ <td class="coding-rules-detail-list-name" colspan="2">{{t 'coding_rules.most_violated_projects'}}</td>
+ </tr>
+ {{#each projects}}
+ <tr>
+ <td class="coding-rules-detail-list-name">{{name}}</td>
+ <td class="coding-rules-detail-list-parameters">
+ <a href="{{../baseSearchUrl}}|projectUuids={{val}}" target="_blank">{{count}}</a>
+ </td>
+ </tr>
+ {{/each}}
+ </table>
+{{/notEmpty}}
'coding-rules/rule/rule-parameters-view',
'coding-rules/rule/rule-profiles-view',
'coding-rules/rule/custom-rules-view',
- 'coding-rules/rule/manual-rule-creation-view'
+ 'coding-rules/rule/manual-rule-creation-view',
+ 'coding-rules/rule/rule-issues-view'
],
function (Backbone,
Marionette,
ParamView,
ProfilesView,
CustomRulesView,
- ManualRuleCreationView) {
+ ManualRuleCreationView,
+ IssuesView) {
var $ = jQuery;
descRegion: '.js-rule-description',
paramRegion: '.js-rule-parameters',
profilesRegion: '.js-rule-profiles',
- customRulesRegion: '.js-rule-custom-rules'
+ customRulesRegion: '.js-rule-custom-rules',
+ issuesRegion: '.js-rule-issues'
},
events: {
model: this.model,
collection: this.customRules
}));
+ this.issuesRegion.show(new IssuesView({
+ app: this.options.app,
+ model: this.model
+ }));
this.$el.scrollParent().scrollTop(30);
},
--- /dev/null
+define([
+ 'backbone.marionette',
+ 'templates/coding-rules'
+], function (Marionette, Templates) {
+
+ var $ = jQuery;
+
+ return Marionette.ItemView.extend({
+ template: Templates['coding-rules-rule-issues'],
+
+ initialize: function () {
+ var that = this;
+ this.total = null;
+ this.projects = [];
+ this.requestIssues().done(function () {
+ that.render();
+ });
+ },
+
+ requestIssues: function () {
+ var that = this,
+ url = baseUrl + '/api/issues/search',
+ options = {
+ rules: this.model.id,
+ resolved: false,
+ ps: 1,
+ facets: 'projectUuids'
+ };
+ return $.get(url, options).done(function (r) {
+ var projectsFacet = _.findWhere(r.facets, { property: 'projectUuids' }),
+ projects = projectsFacet != null ? projectsFacet.values : [];
+ projects = projects.map(function (project) {
+ var projectBase = _.findWhere(r.projects, { uuid: project.val });
+ return _.extend(project, {
+ name: projectBase != null ? projectBase.longName : ''
+ });
+ });
+ that.projects = projects;
+ that.total = r.total;
+ });
+ },
+
+ serializeData: function () {
+ return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), {
+ total: this.total,
+ projects: this.projects,
+ baseSearchUrl: baseUrl + '/issues/search#resolved=false|rules=' + encodeURIComponent(this.model.id)
+ });
+ }
+ });
+
+});
lib.mockRequestFromFile('/api/rules/app', 'app.json');
lib.mockRequestFromFile('/api/rules/search', 'search.json');
lib.mockRequestFromFile('/api/rules/show', 'show.json');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
lib.mockRequestFromFile('/api/rules/search', 'search.json');
this.showMock = lib.mockRequestFromFile('/api/rules/show', 'show.json');
lib.mockRequest('/api/qualityprofiles/activate_rule', '{}');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
this.searchMock = lib.mockRequestFromFile('/api/rules/search', 'search.json');
lib.mockRequestFromFile('/api/rules/show', 'show.json');
lib.mockRequest('/api/rules/create', '{}');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
lib.mockRequestFromFile('/api/rules/search', 'search.json');
lib.mockRequestFromFile('/api/rules/create', 'show.json');
lib.mockRequestFromFile('/api/rules/show', 'show.json');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
lib.mockRequestFromFile('/api/rules/search', 'search.json');
lib.mockRequestFromFile('/api/rules/show', 'show.json');
lib.mockRequest('/api/rules/delete', '{}');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
this.searchMock = lib.mockRequestFromFile('/api/rules/search', 'search-before.json');
lib.mockRequestFromFile('/api/rules/show', 'show.json');
lib.mockRequest('/api/rules/delete', '{}');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
{ data: { template_key: 'squid:ArchitecturalConstraint' } });
lib.mockRequestFromFile('/api/rules/search', 'search.json');
lib.mockRequestFromFile('/api/rules/show', 'show.json');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
lib.mockRequestFromFile('/api/rules/app', 'app.json');
lib.mockRequestFromFile('/api/rules/search', 'search.json');
lib.mockRequestFromFile('/api/rules/show', 'show.json');
+ lib.mockRequest('/api/issues/search', '{}');
})
.then(function () {
--- /dev/null
+/* global casper:false */
+
+var lib = require('../lib');
+
+lib.initMessages();
+lib.changeWorkingDirectory('coding-rules-page-should-show-rule-issues');
+
+
+casper.test.begin('coding-rules-page-should-show-rule-issues', 5, function (test) {
+ casper
+ .start(lib.buildUrl('coding-rules'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequest('/api/l10n/index', '{}');
+ lib.mockRequestFromFile('/api/rules/app', 'app.json');
+ lib.mockRequestFromFile('/api/rules/search', 'search.json');
+ lib.mockRequestFromFile('/api/rules/show', 'show.json');
+ lib.mockRequestFromFile('/api/issues/search', 'issues-search.json');
+ })
+
+ .then(function () {
+ casper.waitForSelector('.coding-rule.selected', function () {
+ casper.click('.coding-rule.selected .js-rule');
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('.coding-rules-most-violated-projects');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('.js-rule-issues', '7');
+ test.assertSelectorContains('.coding-rules-most-violated-projects', 'SonarQube');
+ test.assertSelectorContains('.coding-rules-most-violated-projects', '2');
+ test.assertSelectorContains('.coding-rules-most-violated-projects', 'SonarQube Runner');
+ test.assertSelectorContains('.coding-rules-most-violated-projects', '1');
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
--- /dev/null
+{
+ "canWrite": false,
+ "qualityprofiles": [
+ {
+ "key": "java-default-with-mojo-conventions-49307",
+ "name": "Default - Maven Conventions",
+ "lang": "java",
+ "parentKey": "java-top-profile-without-formatting-conventions-50037"
+ },
+ {
+ "key": "java-default-with-sonarsource-conventions-27339",
+ "name": "Default - SonarSource conventions",
+ "lang": "java",
+ "parentKey": "java-top-profile-without-formatting-conventions-50037"
+ },
+ {
+ "key": "java-top-profile-without-formatting-conventions-50037",
+ "name": "Default - Top",
+ "lang": "java"
+ },
+ {
+ "key": "java-findbugs-14954",
+ "name": "FindBugs",
+ "lang": "java"
+ },
+ {
+ "key": "java-for-sq-java-plugin-only-92289",
+ "name": "For SQ Java Plugin Only",
+ "lang": "java",
+ "parentKey": "java-default-with-sonarsource-conventions-27339"
+ },
+ {
+ "key": "java-for-sq-only-95381",
+ "name": "For SQ Only",
+ "lang": "java",
+ "parentKey": "java-default-with-sonarsource-conventions-27339"
+ },
+ {
+ "key": "php-psr-2-06315",
+ "name": "PSR-2",
+ "lang": "php"
+ },
+ {
+ "key": "java-sonar-way-80423",
+ "name": "Sonar way",
+ "lang": "java"
+ },
+ {
+ "key": "js-sonar-way",
+ "name": "Sonar way",
+ "lang": "js"
+ },
+ {
+ "key": "php-sonar-way-05548",
+ "name": "Sonar way",
+ "lang": "php"
+ },
+ {
+ "key": "py-sonar-way-80265",
+ "name": "Sonar way",
+ "lang": "py"
+ },
+ {
+ "key": "java-without-findbugs",
+ "name": "Without Findbugs",
+ "lang": "java"
+ }
+ ],
+ "languages": {
+ "py": "Python",
+ "js": "JavaScript",
+ "php": "PHP",
+ "java": "Java"
+ },
+ "repositories": [
+ {
+ "key": "common-java",
+ "name": "Common SonarQube",
+ "language": "java"
+ },
+ {
+ "key": "common-js",
+ "name": "Common SonarQube",
+ "language": "js"
+ },
+ {
+ "key": "common-php",
+ "name": "Common SonarQube",
+ "language": "php"
+ },
+ {
+ "key": "common-py",
+ "name": "Common SonarQube",
+ "language": "py"
+ },
+ {
+ "key": "Pylint",
+ "name": "Pylint",
+ "language": "py"
+ },
+ {
+ "key": "javascript",
+ "name": "SonarQube",
+ "language": "js"
+ },
+ {
+ "key": "php",
+ "name": "SonarQube",
+ "language": "php"
+ },
+ {
+ "key": "python",
+ "name": "SonarQube",
+ "language": "py"
+ },
+ {
+ "key": "squid",
+ "name": "SonarQube",
+ "language": "java"
+ }
+ ],
+ "statuses": {
+ "BETA": "Beta",
+ "DEPRECATED": "Deprecated",
+ "READY": "Ready"
+ },
+ "characteristics": {
+ "UNDERSTANDABILITY": "Maintainability: Understandability",
+ "MAINTAINABILITY": "Maintainability",
+ "TIME_ZONE_RELATED_PORTABILITY": "Portability: Time zone related portability",
+ "READABILITY": "Maintainability: Readability",
+ "SECURITY_FEATURES": "Security: Security features",
+ "ARCHITECTURE_RELIABILITY": "Reliability: Architecture related reliability",
+ "OS_RELATED_PORTABILITY": "Portability: OS related portability",
+ "EXCEPTION_HANDLING": "Reliability: Exception handling",
+ "LOGIC_CHANGEABILITY": "Changeability: Logic related changeability",
+ "SOFTWARE_RELATED_PORTABILITY": "Portability: Software related portability",
+ "INPUT_VALIDATION_AND_REPRESENTATION": "Security: Input validation and representation",
+ "LANGUAGE_RELATED_PORTABILITY": "Portability: Language related portability",
+ "ERRORS": "Security: Errors",
+ "SECURITY": "Security",
+ "RELIABILITY": "Reliability",
+ "PORTABILITY": "Portability",
+ "HARDWARE_RELATED_PORTABILITY": "Portability: Hardware related portability",
+ "SYNCHRONIZATION_RELIABILITY": "Reliability: Synchronization related reliability",
+ "TRANSPORTABILITY": "Reusability: Transportability",
+ "COMPILER_RELATED_PORTABILITY": "Portability: Compiler related portability",
+ "RESOURCE_RELIABILITY": "Reliability: Resource",
+ "CPU_EFFICIENCY": "Efficiency: Processor use",
+ "EFFICIENCY": "Efficiency",
+ "CHANGEABILITY": "Changeability",
+ "DATA_CHANGEABILITY": "Changeability: Data related changeability",
+ "API_ABUSE": "Security: API abuse",
+ "ARCHITECTURE_CHANGEABILITY": "Changeability: Architecture related changeability",
+ "UNIT_TESTS": "Reliability: Unit tests",
+ "INSTRUCTION_RELIABILITY": "Reliability: Instruction related reliability",
+ "REUSABILITY": "Reusability",
+ "MODULARITY": "Reusability: Modularity",
+ "UNIT_TESTABILITY": "Testability: Unit level testability",
+ "TESTABILITY": "Testability",
+ "INTEGRATION_TESTABILITY": "Testability: Integration level testability",
+ "NETWORK_USE": "Efficiency: Network use",
+ "MEMORY_EFFICIENCY": "Efficiency: Memory use",
+ "DATA_RELIABILITY": "Reliability: Data related reliability",
+ "FAULT_TOLERANCE": "Reliability: Fault tolerance",
+ "LOGIC_RELIABILITY": "Reliability: Logic related reliability"
+ }
+}
--- /dev/null
+{
+ "total": 7,
+ "p": 1,
+ "ps": 1,
+ "projects": [
+ {
+ "uuid": "3b22f38e-ad68-4792-9791-1435584a686c",
+ "key": "org.codehaus.sonar.runner:sonar-runner",
+ "id": 17226,
+ "qualifier": "TRK",
+ "name": "SonarQube Runner",
+ "longName": "SonarQube Runner"
+ },
+ {
+ "uuid": "69e57151-be0d-4157-adff-c06741d88879",
+ "key": "org.codehaus.sonar:sonar",
+ "id": 2865,
+ "qualifier": "TRK",
+ "name": "SonarQube",
+ "longName": "SonarQube"
+ }
+ ],
+ "components": [],
+ "issues": [],
+ "rules": [],
+ "users": [],
+ "languages": [],
+ "maxResultsReached": false,
+ "paging": {
+ "pageIndex": 1,
+ "pageSize": 1,
+ "total": 7,
+ "fTotal": "7",
+ "pages": 7
+ },
+ "facets": [
+ {
+ "property": "projectUuids",
+ "values": [
+ {
+ "val": "69e57151-be0d-4157-adff-c06741d88879",
+ "count": 2
+ },
+ {
+ "val": "3b22f38e-ad68-4792-9791-1435584a686c",
+ "count": 1
+ }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "total": 1,
+ "p": 1,
+ "ps": 200,
+ "rules": [
+ {
+ "key": "squid:S2096",
+ "name": "\"main\" should not \"throw\" anything",
+ "lang": "java",
+ "langName": "Java",
+ "sysTags": [
+ "bug"
+ ],
+ "tags": [],
+ "status": "READY"
+ }
+ ],
+ "facets": [
+ {
+ "property": "tags",
+ "values": [
+ {
+ "val": "bug",
+ "count": 1
+ }
+ ]
+ },
+ {
+ "property": "languages",
+ "values": [
+ {
+ "val": "java",
+ "count": 1
+ }
+ ]
+ },
+ {
+ "property": "repositories",
+ "values": [
+ {
+ "val": "squid",
+ "count": 1
+ }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "rule": {
+ "key": "squid:S1181",
+ "repo": "squid",
+ "name": "Throwable and Error classes should not be caught",
+ "createdAt": "2013-08-09T14:40:54+0200",
+ "severity": "BLOCKER",
+ "status": "READY",
+ "internalKey": "S1181",
+ "isTemplate": false,
+ "tags": [],
+ "sysTags": [
+ "error-handling"
+ ],
+ "lang": "java",
+ "langName": "Java",
+ "htmlDesc": "<p>\n<code>Throwable</code> is the superclass of all errors and exceptions in Java.\n<code>Error</code> is the superclass of all errors which are not meant to be caught by applications.\n</p>\n\n<p>\nCatching either <code>Throwable</code> or <code>Error</code> will also catch <code>OutOfMemoryError</code> or <code>InternalError</code> from which an application should not attempt to recover.\n</p>\n\n<p>Only <code>Exception</code> and its subclasses should be caught.</p>\n\n<h2>Noncompliant Code Example</h2>\n\n<pre>\ntry { /* ... */ } catch (Throwable t) { /* ... */ }\ntry { /* ... */ } catch (Error e) { /* ... */ } \n</pre>\n\n<h2>Compliant Solution</h2>\n\n<pre>\ntry { /* ... */ } catch (Exception e) { /* ... */ } \ntry { /* ... */ } catch (RuntimeException e) { /* ... */ } \ntry { /* ... */ } catch (MyException e) { /* ... */ } \n</pre>",
+ "defaultDebtChar": "RELIABILITY",
+ "defaultDebtSubChar": "EXCEPTION_HANDLING",
+ "debtChar": "RELIABILITY",
+ "debtSubChar": "EXCEPTION_HANDLING",
+ "debtCharName": "Reliability",
+ "debtSubCharName": "Exception handling",
+ "defaultDebtRemFnType": "CONSTANT_ISSUE",
+ "defaultDebtRemFnOffset": "20min",
+ "debtOverloaded": true,
+ "debtRemFnType": "LINEAR",
+ "debtRemFnCoeff": "20min",
+ "params": [
+ {
+ "key": "max",
+ "htmlDesc": "Maximum authorized number of parameters",
+ "type": "INTEGER",
+ "defaultValue": "7"
+ }
+ ]
+ },
+ "actives": [
+ {
+ "qProfile": "java-top-profile-without-formatting-conventions-50037",
+ "inherit": "NONE",
+ "severity": "BLOCKER",
+ "params": []
+ },
+ {
+ "qProfile": "java-default-with-sonarsource-conventions-27339",
+ "inherit": "INHERITED",
+ "severity": "BLOCKER",
+ "params": []
+ },
+ {
+ "qProfile": "java-for-sq-java-plugin-only-92289",
+ "inherit": "INHERITED",
+ "severity": "BLOCKER",
+ "params": []
+ },
+ {
+ "qProfile": "java-for-sq-only-95381",
+ "inherit": "INHERITED",
+ "severity": "BLOCKER",
+ "params": []
+ },
+ {
+ "qProfile": "java-default-with-mojo-conventions-49307",
+ "inherit": "INHERITED",
+ "severity": "BLOCKER",
+ "params": []
+ },
+ {
+ "qProfile": "java-sonar-way-80423",
+ "inherit": "NONE",
+ "severity": "BLOCKER",
+ "params": []
+ }
+ ]
+}
coding_rules.deactivate_in_all_quality_profiles=Deactivate In All {0} Profiles
coding_rules.found=Found
coding_rules.inherits="{0}" inherits from "{1}"
+coding_rules.issues=Issues
coding_rules.key=Key:
coding_rules.manual_rule=Manual Rule
coding_rules.manual_rules=Manual Rules
+coding_rules.most_violated_projects=Most Violated Projects
coding_rules.new_search=New Search
coding_rules.no_results=No Coding Rules
coding_rules.no_tags=No tags