Skip to content

Commit 0316a6a

Browse files
committed
Initial set of Clang rules. Add Clang profile.
1 parent 9bc5130 commit 0316a6a

File tree

13 files changed

+424
-11
lines changed

13 files changed

+424
-11
lines changed

src/main/java/org/sonar/plugins/objectivec/ObjectiveCPlugin.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import org.sonar.api.SonarPlugin;
2424
import org.sonar.api.config.PropertyDefinition;
2525
import org.sonar.api.resources.Qualifiers;
26+
import org.sonar.plugins.objectivec.clang.ClangProfile;
27+
import org.sonar.plugins.objectivec.clang.ClangProfileImporter;
2628
import org.sonar.plugins.objectivec.clang.ClangRulesDefinition;
2729
import org.sonar.plugins.objectivec.clang.ClangSensor;
2830
import org.sonar.plugins.objectivec.cobertura.CoberturaSensor;
@@ -56,6 +58,8 @@ public List getExtensions() {
5658

5759
extensions.add(ClangRulesDefinition.class);
5860
extensions.add(ClangSensor.class);
61+
extensions.add(ClangProfile.class);
62+
extensions.add(ClangProfileImporter.class);
5963
extensions.add(PropertyDefinition.builder(ClangSensor.REPORTS_PATH_KEY)
6064
.name("Clang Static Analyzer Reports")
6165
.description("Path to the directory containing all the *.plist Clang report files. The path may be absolute or relative to the project base directory.")

src/main/java/org/sonar/plugins/objectivec/clang/ClangPlistParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
/**
4040
* @author Matthew DeTullio
4141
*/
42-
public class ClangPlistParser {
42+
public final class ClangPlistParser {
4343
private static final Logger LOGGER = LoggerFactory.getLogger(ClangPlistParser.class);
4444

4545
public static List<ClangWarning> parse(final File reportsDir) {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Sonar Objective-C Plugin
3+
* Copyright (C) 2012 OCTO Technology, Backelite,
4+
* Denis Bregeon, Mete Balci, Andrés Gil Herrera, Matthew DeTullio
5+
* dev@sonar.codehaus.org
6+
*
7+
* This program is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 3 of the License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
20+
*/
21+
package org.sonar.plugins.objectivec.clang;
22+
23+
import com.google.common.io.Closeables;
24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
26+
import org.sonar.api.profiles.ProfileDefinition;
27+
import org.sonar.api.profiles.RulesProfile;
28+
import org.sonar.api.utils.ValidationMessages;
29+
import org.sonar.plugins.objectivec.ObjectiveC;
30+
31+
import java.io.InputStreamReader;
32+
import java.io.Reader;
33+
34+
public final class ClangProfile extends ProfileDefinition {
35+
private static final Logger LOGGER = LoggerFactory.getLogger(ClangProfile.class);
36+
37+
private final ClangProfileImporter importer;
38+
39+
public ClangProfile(final ClangProfileImporter importer) {
40+
this.importer = importer;
41+
}
42+
43+
@Override
44+
public RulesProfile createProfile(final ValidationMessages messages) {
45+
LOGGER.info("Creating Clang Profile");
46+
Reader profileXmlReader = null;
47+
48+
try {
49+
profileXmlReader = new InputStreamReader(ClangProfile.class.getResourceAsStream(
50+
"/org/sonar/plugins/objectivec/profile-clang.xml"));
51+
52+
RulesProfile profile = importer.importProfile(profileXmlReader, messages);
53+
profile.setLanguage(ObjectiveC.KEY);
54+
profile.setName(ClangRulesDefinition.REPOSITORY_NAME);
55+
56+
return profile;
57+
} finally {
58+
Closeables.closeQuietly(profileXmlReader);
59+
}
60+
}
61+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Sonar Objective-C Plugin
3+
* Copyright (C) 2012 OCTO Technology, Backelite,
4+
* Denis Bregeon, Mete Balci, Andrés Gil Herrera, Matthew DeTullio
5+
* dev@sonar.codehaus.org
6+
*
7+
* This program is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 3 of the License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
20+
*/
21+
package org.sonar.plugins.objectivec.clang;
22+
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
import org.sonar.api.profiles.ProfileImporter;
26+
import org.sonar.api.profiles.RulesProfile;
27+
import org.sonar.api.profiles.XMLProfileParser;
28+
import org.sonar.api.utils.ValidationMessages;
29+
import org.sonar.plugins.objectivec.ObjectiveC;
30+
31+
import java.io.Reader;
32+
33+
public final class ClangProfileImporter extends ProfileImporter {
34+
private static final Logger LOGGER = LoggerFactory.getLogger(ClangProfileImporter.class);
35+
private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default Clang profile";
36+
37+
private final XMLProfileParser profileParser;
38+
39+
public ClangProfileImporter(final XMLProfileParser xmlProfileParser) {
40+
super(ClangRulesDefinition.REPOSITORY_KEY, ClangRulesDefinition.REPOSITORY_NAME);
41+
setSupportedLanguages(ObjectiveC.KEY);
42+
profileParser = xmlProfileParser;
43+
}
44+
45+
@Override
46+
public RulesProfile importProfile(final Reader reader,
47+
final ValidationMessages messages) {
48+
final RulesProfile profile = profileParser.parse(reader, messages);
49+
50+
if (null == profile) {
51+
messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE);
52+
LOGGER.error(UNABLE_TO_LOAD_DEFAULT_PROFILE);
53+
}
54+
55+
return profile;
56+
}
57+
}

src/main/java/org/sonar/plugins/objectivec/clang/ClangRulesDefinition.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,39 @@
2020
*/
2121
package org.sonar.plugins.objectivec.clang;
2222

23+
import com.google.common.collect.ImmutableMap;
2324
import org.sonar.api.server.rule.RulesDefinition;
2425
import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
2526
import org.sonar.plugins.objectivec.ObjectiveC;
2627
import org.sonar.squidbridge.rules.SqaleXmlLoader;
2728

29+
import java.util.Map;
30+
2831
/**
2932
* @author Matthew DeTullio
3033
*/
31-
public class ClangRulesDefinition implements RulesDefinition {
34+
public final class ClangRulesDefinition implements RulesDefinition {
3235
public static final String REPOSITORY_KEY = "clang";
3336
public static final String REPOSITORY_NAME = "Clang";
3437

38+
/**
39+
* Map of Clang plist report <code>type</code>s to their corresponding rules. Multiple types can map to a single
40+
* rule.
41+
*/
42+
public static final Map<String, String> REPORT_TYPE_TO_RULE_MAP = ImmutableMap.<String, String>builder()
43+
.put("Assigned value is garbage or undefined", "core.uninitialized.Assign") // Logic error
44+
.put("Bad return type when passing NSError**", "osx.cocoa.NSError") // Coding conventions (Apple)
45+
.put("Branch condition evaluates to a garbage value", "core.uninitialized.Branch") // Logic error
46+
.put("Dead assignment", "deadcode.DeadStores") // Dead store
47+
.put("Dead increment", "deadcode.DeadStores") // Dead store
48+
.put("Dead initialization", "deadcode.DeadStores") // Dead store
49+
.put("Garbage return value", "core.uninitialized.UndefReturn") // Logic error
50+
.put("Leak", "osx.cocoa.RetainCount") // Memory (Core Foundation/Objective-C)
51+
.put("Missing call to superclass", "osx.cocoa.MissingSuperCall") // Core Foundation/Objective-C
52+
.put("Nil value used as mutex for @synchronized() (no synchronization will occur)", "osx.cocoa.AtSync") // Logic error
53+
.put("Result of operation is garbage or undefined", "core.UndefinedBinaryOperatorResult") // Logic error
54+
.build();
55+
3556
@Override
3657
public void define(Context context) {
3758
NewRepository repository = context

src/main/java/org/sonar/plugins/objectivec/clang/ClangSensor.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
/**
4343
* @author Matthew DeTullio
4444
*/
45-
public class ClangSensor implements Sensor {
45+
public final class ClangSensor implements Sensor {
4646
private static final Logger LOGGER = LoggerFactory.getLogger(ClangSensor.class.getName());
4747

4848
public static final String REPORTS_PATH_KEY = "sonar.objectivec.clang.reportsPath";
@@ -84,7 +84,15 @@ protected void collect(Project project, SensorContext context, File reportsDir)
8484
List<ClangWarning> clangWarnings = ClangPlistParser.parse(reportsDir);
8585

8686
for (ClangWarning clangWarning : clangWarnings) {
87-
// TODO: Add check for enabled rule if/when rules get split up
87+
String type = clangWarning.getType();
88+
String ruleKeyName;
89+
90+
if (ClangRulesDefinition.REPORT_TYPE_TO_RULE_MAP.containsKey(type)) {
91+
ruleKeyName = ClangRulesDefinition.REPORT_TYPE_TO_RULE_MAP.get(type);
92+
} else {
93+
ruleKeyName = "other";
94+
LOGGER.debug("Type '{}' is not mapped to a rule -- using default rule '{}'", type, ruleKeyName);
95+
}
8896

8997
Resource resource = context.getResource(
9098
org.sonar.api.resources.File.fromIOFile(clangWarning.getFile(), project));
@@ -98,8 +106,8 @@ protected void collect(Project project, SensorContext context, File reportsDir)
98106

99107
if (issuable != null) {
100108
Issue issue = issuable.newIssueBuilder()
101-
.ruleKey(RuleKey.of(ClangRulesDefinition.REPOSITORY_KEY, "other"))
102-
.message(String.format("%s - %s", clangWarning.getCategory(), clangWarning.getType()))
109+
.ruleKey(RuleKey.of(ClangRulesDefinition.REPOSITORY_KEY, ruleKeyName))
110+
.message(String.format("%s - %s", clangWarning.getCategory(), type))
103111
.line(clangWarning.getLine())
104112
.build();
105113

src/main/java/org/sonar/plugins/objectivec/oclint/OCLintProfile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public RulesProfile createProfile(final ValidationMessages messages) {
5151

5252
RulesProfile profile = importer.importProfile(profileXmlReader, messages);
5353
profile.setLanguage(ObjectiveC.KEY);
54-
profile.setName(OCLintRulesDefinition.REPOSITORY_KEY);
54+
profile.setName(OCLintRulesDefinition.REPOSITORY_NAME);
5555
profile.setDefaultProfile(true);
5656

5757
return profile;

src/main/java/org/sonar/plugins/objectivec/oclint/OCLintProfileImporter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public final class OCLintProfileImporter extends ProfileImporter {
3737
private final XMLProfileParser profileParser;
3838

3939
public OCLintProfileImporter(final XMLProfileParser xmlProfileParser) {
40-
super(OCLintRulesDefinition.REPOSITORY_KEY, OCLintRulesDefinition.REPOSITORY_KEY);
40+
super(OCLintRulesDefinition.REPOSITORY_KEY, OCLintRulesDefinition.REPOSITORY_NAME);
4141
setSupportedLanguages(ObjectiveC.KEY);
4242
profileParser = xmlProfileParser;
4343
}

src/main/java/org/sonar/plugins/objectivec/surefire/SurefireParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
import java.util.List;
4949
import java.util.Set;
5050

51-
public class SurefireParser {
51+
public final class SurefireParser {
5252
private static final Logger LOGGER = LoggerFactory.getLogger(SurefireParser.class);
5353

5454
private final Project project;

src/main/java/org/sonar/plugins/objectivec/surefire/SurefireSensor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
import java.io.File;
3434

35-
public class SurefireSensor implements Sensor {
35+
public final class SurefireSensor implements Sensor {
3636
private static final Logger LOGGER = LoggerFactory.getLogger(SurefireSensor.class);
3737

3838
public static final String REPORTS_PATH_KEY = "sonar.objectivec.junit.reportsPath";

0 commit comments

Comments
 (0)