diff --git a/.gitignore b/.gitignore index f1d4a1d9..2dd13ef3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ -# Maven +# Android +local.properties + +/# Maven target/ # Gradle .gradle/ +build/ # Ant Working Directory .sonar/ @@ -11,6 +15,7 @@ target/ *.iws *.iml *.ipr +.idea/ # Eclipse .classpath @@ -18,7 +23,7 @@ target/ .settings # ---- Mac OS X -.DS_Store? +.DS_Store Icon? # Thumbnails ._* diff --git a/.sonarsource.properties b/.sonarsource.properties new file mode 100644 index 00000000..bfb4e7b9 --- /dev/null +++ b/.sonarsource.properties @@ -0,0 +1,6 @@ +# Sonarsource meta data file for this project + +# Wallboard +# teamAtSonarSource drives in which wallboard the alerting will be sent +# platform , language, infra , po , support +wallboard.teamAtSonarSource=support diff --git a/.whitesource b/.whitesource new file mode 100644 index 00000000..55b922e8 --- /dev/null +++ b/.whitesource @@ -0,0 +1,12 @@ +{ + "scanSettings": { + "baseBranches": [] + }, + "checkRunSettings": { + "vulnerableCheckRunConclusionLevel": "failure", + "displayMode": "diff" + }, + "issueSettings": { + "minSeverityLevel": "LOW" + } +} \ No newline at end of file diff --git a/README.md b/README.md index e3ccd5b8..91768667 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,17 @@ -# Sonar Usage and Examples - -Please add usage scenarios or links to articles that mention special use-cases below. -Note that these examples are usually for Sonar 2.10 and greater versions. - ## Configuration of Projects -The directory /projects contains some typical configurations of projects for the multiple supported build tools (Maven, Ant, Java Runner). +The directory /projects contains sample projects for: + * the different analyzers (SonarQube Runner, Maven, Ant) + * the different languages (Java, Cobol, .Net, etc.) + * the different ways to execute unit tests and get code coverage data -## Sonar Plugins +## SonarQube Plugins -The directory /plugins contains the most frequent kinds of plugins : - - * Extensions of rule engines like Checkstyle or PMD +The directory /plugins contains the most frequent kinds of plugins: + * Extensions of rule engines like Java and JavaScript * Define a new metric, compute measures and display them in web app +## SonarQube Web Service API - +The directory /ws contains project samples using the SonarQube web service API. + diff --git a/plugins/java-custom-rules/README.md b/plugins/java-custom-rules/README.md new file mode 100644 index 00000000..27e63097 --- /dev/null +++ b/plugins/java-custom-rules/README.md @@ -0,0 +1,3 @@ +This example demonstrates how to write new *custom* rules for the Java analyzer. + +It requires to install the **Java Plugin**, at least version **3.13.1**, which is compatible with SonarQube 4.5.6 LTS. diff --git a/plugins/java-custom-rules/pom.xml b/plugins/java-custom-rules/pom.xml new file mode 100644 index 00000000..ca4bb695 --- /dev/null +++ b/plugins/java-custom-rules/pom.xml @@ -0,0 +1,135 @@ + + + 4.0.0 + + org.sonar.samples + java-custom-rules + 1.0-SNAPSHOT + sonar-plugin + + + 7.15.0.30507 + + + Java Custom Rules + Java Custom Rules + + + + org.codehaus.sonar + sonar-plugin-api + 5.0 + provided + + + + org.sonarsource.java + sonar-java-plugin + sonar-plugin + ${java.plugin.version} + provided + + + + org.sonarsource.java + java-frontend + ${java.plugin.version} + + + + org.sonarsource.sslr-squid-bridge + sslr-squid-bridge + 2.7.1.392 + + + org.codehaus.sonar.sslr + sslr-core + + + + + + org.sonarsource.java + java-checks-testkit + ${java.plugin.version} + test + + + + org.codehaus.sonar.sslr + sslr-testing-harness + 1.19.2 + test + + + junit + junit + 4.11 + test + + + org.easytesting + fest-assert + 1.4 + test + + + ch.qos.logback + logback-classic + 0.9.30 + test + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + org.sonar.samples.java.MyJavaRulesPlugin + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.10 + + + copy + test-compile + + copy + + + + + org.apache.commons + commons-collections4 + 4.0 + jar + + + ${project.build.directory}/test-jars + + + + + + + + diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaFileCheckRegistrar.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaFileCheckRegistrar.java new file mode 100644 index 00000000..647a1dfe --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaFileCheckRegistrar.java @@ -0,0 +1,53 @@ +package org.sonar.samples.java; + +import java.util.Arrays; + +import org.sonar.plugins.java.api.CheckRegistrar; +import org.sonar.plugins.java.api.JavaCheck; +import org.sonar.samples.java.checks.AvoidAnnotationRule; +import org.sonar.samples.java.checks.AvoidBrandInMethodNamesRule; +import org.sonar.samples.java.checks.AvoidMethodDeclarationRule; +import org.sonar.samples.java.checks.AvoidSuperClassRule; +import org.sonar.samples.java.checks.AvoidUnmodifiableListRule; +import org.sonar.samples.java.checks.MyCustomSubscriptionRule; +import org.sonar.samples.java.checks.SecurityAnnotationMandatoryRule; + +/** + * Provide the "checks" (implementations of rules) classes that are gonna be executed during + * source code analysis. + * + * This class is a batch extension by implementing the {@link org.sonar.plugins.java.api.CheckRegistrar} interface. + */ +public class MyJavaFileCheckRegistrar implements CheckRegistrar { + + /** + * Register the classes that will be used to instantiate checks during analysis. + */ + @Override + public void register(RegistrarContext registrarContext) { + // Call to registerClassesForRepository to associate the classes with the correct repository key + registrarContext.registerClassesForRepository(MyJavaRulesDefinition.REPOSITORY_KEY, Arrays.asList(checkClasses()), Arrays.asList(testCheckClasses())); + } + + /** + * Lists all the checks provided by the plugin + */ + public static Class[] checkClasses() { + return new Class[] { + AvoidAnnotationRule.class, + AvoidBrandInMethodNamesRule.class, + AvoidMethodDeclarationRule.class, + AvoidSuperClassRule.class, + AvoidUnmodifiableListRule.class, + MyCustomSubscriptionRule.class, + SecurityAnnotationMandatoryRule.class + }; + } + + /** + * Lists all the test checks provided by the plugin + */ + public static Class[] testCheckClasses() { + return new Class[] {}; + } +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaRulesDefinition.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaRulesDefinition.java new file mode 100644 index 00000000..f2d8530b --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaRulesDefinition.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009-2014 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.java; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.plugins.java.Java; +import org.sonar.squidbridge.annotations.AnnotationBasedRulesDefinition; + +/** + * Declare rule metadata in server repository of rules. + * That allows to list the rules in the page "Rules". + */ +public class MyJavaRulesDefinition implements RulesDefinition { + + public static final String REPOSITORY_KEY = "myrepo"; + + @Override + public void define(Context context) { + NewRepository repository = context.createRepository(REPOSITORY_KEY, Java.KEY); + repository.setName("MyRepo"); + + AnnotationBasedRulesDefinition.load(repository, "java", RulesList.getChecks()); + repository.done(); + } +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaRulesPlugin.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaRulesPlugin.java new file mode 100644 index 00000000..3b4ef0cc --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/MyJavaRulesPlugin.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009-2014 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.java; + +import java.util.Arrays; +import java.util.List; + +import org.sonar.api.SonarPlugin; + +/** + * Entry point of plugin + */ +public class MyJavaRulesPlugin extends SonarPlugin { + + @Override + public List getExtensions() { + return Arrays.asList( + // server extensions -> objects are instantiated during server startup + MyJavaRulesDefinition.class, + + // batch extensions -> objects are instantiated during code analysis + MyJavaFileCheckRegistrar.class); + } +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/RulesList.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/RulesList.java new file mode 100644 index 00000000..a9ab3340 --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/RulesList.java @@ -0,0 +1,41 @@ +package org.sonar.samples.java; + +import java.util.List; + +import org.sonar.plugins.java.api.JavaCheck; +import org.sonar.samples.java.checks.AvoidAnnotationRule; +import org.sonar.samples.java.checks.AvoidBrandInMethodNamesRule; +import org.sonar.samples.java.checks.AvoidMethodDeclarationRule; +import org.sonar.samples.java.checks.AvoidSuperClassRule; +import org.sonar.samples.java.checks.AvoidUnmodifiableListRule; +import org.sonar.samples.java.checks.MyCustomSubscriptionRule; +import org.sonar.samples.java.checks.SecurityAnnotationMandatoryRule; + +import com.google.common.collect.ImmutableList; + +public final class RulesList { + + private RulesList() { + } + + public static List getChecks() { + return ImmutableList.builder().addAll(getJavaChecks()).addAll(getJavaTestChecks()).build(); + } + + public static List> getJavaChecks() { + return ImmutableList.>builder() + .add(AvoidAnnotationRule.class) + .add(AvoidBrandInMethodNamesRule.class) + .add(AvoidMethodDeclarationRule.class) + .add(AvoidSuperClassRule.class) + .add(AvoidUnmodifiableListRule.class) + .add(MyCustomSubscriptionRule.class) + .add(SecurityAnnotationMandatoryRule.class) + .build(); + } + + public static List> getJavaTestChecks() { + return ImmutableList.>builder() + .build(); + } +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidAnnotationRule.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidAnnotationRule.java new file mode 100644 index 00000000..9ccfafd4 --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidAnnotationRule.java @@ -0,0 +1,66 @@ +package org.sonar.samples.java.checks; + +import java.util.List; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; +import org.sonar.plugins.java.api.JavaFileScanner; +import org.sonar.plugins.java.api.JavaFileScannerContext; +import org.sonar.plugins.java.api.tree.AnnotationTree; +import org.sonar.plugins.java.api.tree.BaseTreeVisitor; +import org.sonar.plugins.java.api.tree.IdentifierTree; +import org.sonar.plugins.java.api.tree.MethodTree; +import org.sonar.plugins.java.api.tree.Tree; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +@Rule(key = "AvoidAnnotation", + name = "Avoid usage of annotation", + description = "This rule detects usage of configured annotation", + tags = {"example"}) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY) +@SqaleConstantRemediation("10min") +public class AvoidAnnotationRule extends BaseTreeVisitor implements JavaFileScanner { + + private static final String DEFAULT_VALUE = "Inject"; + + private JavaFileScannerContext context; + + /** + * Name of the annotation to avoid. Value can be set by users in Quality profiles. + * The key + */ + @RuleProperty( + defaultValue = DEFAULT_VALUE, + description = "Name of the annotation to avoid, without the prefix @, for instance 'Override'") + protected String name; + + @Override + public void scanFile(JavaFileScannerContext context) { + this.context = context; + + scan(context.getTree()); + + System.out.println(PrinterVisitor.print(context.getTree())); + } + + @Override + public void visitMethod(MethodTree tree) { + List annotations = tree.modifiers().annotations(); + for (AnnotationTree annotationTree : annotations) { + if (annotationTree.annotationType().is(Tree.Kind.IDENTIFIER)) { + IdentifierTree idf = (IdentifierTree) annotationTree.annotationType(); + System.out.println(idf.name()); + + if (idf.name().equals(name)) { + context.addIssue(idf, this, String.format("Avoid using annotation @%s", name)); + } + } + } + + // The call to the super implementation allows to continue the visit of the AST. + // Be careful to always call this method to visit every node of the tree. + super.visitMethod(tree); + } +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidBrandInMethodNamesRule.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidBrandInMethodNamesRule.java new file mode 100644 index 00000000..5449d4be --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidBrandInMethodNamesRule.java @@ -0,0 +1,53 @@ +package org.sonar.samples.java.checks; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.JavaFileScanner; +import org.sonar.plugins.java.api.JavaFileScannerContext; +import org.sonar.plugins.java.api.tree.BaseTreeVisitor; +import org.sonar.plugins.java.api.tree.MethodTree; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +@Rule(key = "AvoidBrandInMethodNames", + name = "Avoid Brand in Method Names", + description = "Avoid Brand in Method Names", + tags = {"company"}) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY) +@SqaleConstantRemediation("10min") +public class AvoidBrandInMethodNamesRule extends BaseTreeVisitor implements JavaFileScanner { + + private JavaFileScannerContext context; + + protected static final String COMPANY_NAME = "MyCompany"; + + @Override + public void scanFile(JavaFileScannerContext context) { + this.context = context; + + // The call to the scan method on the root of the tree triggers the visit of the AST by this visitor + scan(context.getTree()); + + // For debugging purpose, you can print out the entire AST of the analyzed file + System.out.println(PrinterVisitor.print(context.getTree())); + } + + /** + * Overriding the visitor method to implement the logic of the rule. + * @param tree AST of the visited method. + */ + @Override + public void visitMethod(MethodTree tree) { + + if (tree.simpleName().name().toUpperCase().contains(COMPANY_NAME.toUpperCase())) { + // Adds an issue by attaching it with the tree and the rule + context.addIssue(tree, this, "Avoid using Brand in method name"); + } + // The call to the super implementation allows to continue the visit of the AST. + // Be careful to always call this method to visit every node of the tree. + super.visitMethod(tree); + + // All the code located after the call to the overridden method is executed when leaving the node + } + +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidMethodDeclarationRule.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidMethodDeclarationRule.java new file mode 100644 index 00000000..d6916775 --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidMethodDeclarationRule.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2009-2014 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.java.checks; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.JavaFileScanner; +import org.sonar.plugins.java.api.JavaFileScannerContext; +import org.sonar.plugins.java.api.tree.BaseTreeVisitor; +import org.sonar.plugins.java.api.tree.MethodTree; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +/** + * This class is an example of how to implement your own rules. + * The (stupid) rule raises a minor issue each time a method is encountered. + * The @Rule annotation allows to specify metadata like rule key, name, description + * or default severity. + */ +@Rule(key = "MethodDeclaration", + name = "Avoid using methods", + description = "My stupid rule to avoid calling methods", + tags = {"stupid", "example"}, + // default severity (formerly "priority") when rule is enabled in Quality profile + priority = Priority.MINOR) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY) +@SqaleConstantRemediation("10min") +/** + * The class extends BaseTreeVisitor: the visitor for the Java AST. + * The logic of the rule is implemented by overriding its methods. + * It also implements the JavaFileScanner interface to be injected with the JavaFileScannerContext to attach issues to this context. + */ +public class AvoidMethodDeclarationRule extends BaseTreeVisitor implements JavaFileScanner { + + /** + * Private field to store the context: this is the object used to create issues. + */ + private JavaFileScannerContext context; + + /** + * Implementation of the method of the JavaFileScanner interface. + * @param context Object used to attach issues to source file. + */ + @Override + public void scanFile(JavaFileScannerContext context) { + this.context = context; + + // The call to the scan method on the root of the tree triggers the visit of the AST by this visitor + scan(context.getTree()); + + // For debugging purpose, you can print out the entire AST of the analyzed file + System.out.println(PrinterVisitor.print(context.getTree())); + + } + + /** + * Overriding the visitor method to implement the logic of the rule. + * @param tree AST of the visited method. + */ + @Override + public void visitMethod(MethodTree tree) { + + // All the code located before the call to the overridden method is executed before visiting the node + + // Adds an issue by attaching it with the tree and the rule + context.addIssue(tree, this, "Avoid method calls (don't ask why)"); + + // The call to the super implementation allows to continue the visit of the AST. + // Be careful to always call this method to visit every node of the tree. + super.visitMethod(tree); + + // All the code located after the call to the overridden method is executed when leaving the node + } + +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidSuperClassRule.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidSuperClassRule.java new file mode 100644 index 00000000..09abf6fb --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidSuperClassRule.java @@ -0,0 +1,56 @@ +/* + * Creation : 20 avr. 2015 + */ +package org.sonar.samples.java.checks; + +import java.util.List; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.tree.ClassTree; +import org.sonar.plugins.java.api.tree.Tree; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +import com.google.common.collect.ImmutableList; + +/** + * Only to bring out the unit test requirement about classpath when bytecode methods used (see rule unit test class) + */ +@Rule(key = "avoid_super_class", + name = "Avoid using SuperClass", + description = "My stupid rule to avoid extends some SuperClass", + tags = {"stupid", "example"}) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY) +@SqaleConstantRemediation("10min") +public class AvoidSuperClassRule extends IssuableSubscriptionVisitor { + + public static final List SUPER_CLASS_AVOID = ImmutableList.of("org.apache.log4j.Logger"); + + @Override + public List nodesToVisit() { + // Register to the kind of nodes you want to be called upon visit. + return ImmutableList.of(Tree.Kind.CLASS); + } + + @Override + public void visitNode(Tree tree) { + // Visit CLASS node only => cast could be done + ClassTree treeClazz = (ClassTree) tree; + + // No extends => stop to visit class + if (treeClazz.superClass() == null) { + return; + } + + // For 'symbolType' usage, jar in dependencies must be on classpath, !unknownSymbol! result otherwise + String superClassName = treeClazz.superClass().symbolType().fullyQualifiedName(); + + // Check if superClass avoid + if (SUPER_CLASS_AVOID.contains(superClassName)) { + addIssue(tree, String.format("The usage of super class %s is forbidden", superClassName)); + } + } + +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidUnmodifiableListRule.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidUnmodifiableListRule.java new file mode 100644 index 00000000..c024ffee --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/AvoidUnmodifiableListRule.java @@ -0,0 +1,36 @@ +package org.sonar.samples.java.checks; + +import java.util.List; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.tree.NewClassTree; +import org.sonar.plugins.java.api.tree.Tree; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +import com.google.common.collect.ImmutableList; + +@Rule( + key = "AvoidUnmodifiableList", + name = "Avoid usage of UnmodifiableList", + description = "This rule detects instanciation of apache commons collections UnmodifableList", + tags = {"example"}) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY) +@SqaleConstantRemediation("10min") +public class AvoidUnmodifiableListRule extends IssuableSubscriptionVisitor { + + @Override + public List nodesToVisit() { + return ImmutableList.of(Tree.Kind.NEW_CLASS); + } + + @Override + public void visitNode(Tree tree) { + if (((NewClassTree) tree).symbolType().isSubtypeOf("org.apache.commons.collections4.list.UnmodifiableList")) { + addIssue(tree, "Avoid using UnmodifiableList"); + } + } + +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/MyCustomSubscriptionRule.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/MyCustomSubscriptionRule.java new file mode 100644 index 00000000..db4fda11 --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/MyCustomSubscriptionRule.java @@ -0,0 +1,53 @@ +package org.sonar.samples.java.checks; + +import java.util.List; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Rule; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.semantic.Symbol.MethodSymbol; +import org.sonar.plugins.java.api.semantic.Type; +import org.sonar.plugins.java.api.tree.MethodTree; +import org.sonar.plugins.java.api.tree.Tree; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +import com.google.common.collect.ImmutableList; + +@Rule(key = "method_with_same_type_as_arg", + name = "method with same return type as argument", + description = "This rule detects methods with same type as argument", + tags = {"example"}) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY) +@SqaleConstantRemediation("10min") +/** + * To use subsctiption visitor, just extend the IssuableSubscriptionVisitor. + */ +public class MyCustomSubscriptionRule extends IssuableSubscriptionVisitor { + + @Override + public List nodesToVisit() { + // Register to the kind of nodes you want to be called upon visit. + return ImmutableList.of(Tree.Kind.METHOD); + } + + @Override + public void visitNode(Tree tree) { + // Cast the node to the correct type : + // in this case we registered only to one kind so we will only receive MethodTree see Tree.Kind enum to know about which type you can + // cast depending on Kind. + MethodTree methodTree = (MethodTree) tree; + // Retrieve symbol of method. + MethodSymbol methodSymbol = methodTree.symbol(); + Type returnType = methodSymbol.returnType().type(); + // Check method has only one argument. + if (methodSymbol.parameterTypes().size() == 1) { + Type argType = methodSymbol.parameterTypes().get(0); + // Verify argument type is same as return type. + if (argType.is(returnType.fullyQualifiedName())) { + // raise an issue on this node of the SyntaxTree + addIssue(tree, "message"); + } + } + } +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/PrinterVisitor.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/PrinterVisitor.java new file mode 100644 index 00000000..e7514fff --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/PrinterVisitor.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009-2014 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.java.checks; + +import java.util.List; + +import javax.annotation.Nullable; + +import org.apache.commons.lang.StringUtils; +import org.sonar.plugins.java.api.tree.BaseTreeVisitor; +import org.sonar.plugins.java.api.tree.Tree; + +public class PrinterVisitor extends BaseTreeVisitor { + + private static final int INDENT_SPACES = 2; + + private final StringBuilder sb; + private int indentLevel; + + public PrinterVisitor() { + sb = new StringBuilder(); + indentLevel = 0; + } + + public static String print(Tree tree) { + PrinterVisitor pv = new PrinterVisitor(); + pv.scan(tree); + return pv.sb.toString(); + } + + private StringBuilder indent() { + return sb.append(StringUtils.leftPad("", INDENT_SPACES * indentLevel)); + } + + @Override + protected void scan(List trees) { + if (!trees.isEmpty()) { + sb.deleteCharAt(sb.length() - 1); + sb.append(" : [\n"); + super.scan(trees); + indent().append("]\n"); + } + } + + @Override + protected void scan(@Nullable Tree tree) { + if (tree != null && tree.getClass().getInterfaces() != null && tree.getClass().getInterfaces().length > 0) { + String nodeName = tree.getClass().getInterfaces()[0].getSimpleName(); + indent().append(nodeName).append("\n"); + } + indentLevel++; + super.scan(tree); + indentLevel--; + } +} diff --git a/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/SecurityAnnotationMandatoryRule.java b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/SecurityAnnotationMandatoryRule.java new file mode 100644 index 00000000..f1441cd4 --- /dev/null +++ b/plugins/java-custom-rules/src/main/java/org/sonar/samples/java/checks/SecurityAnnotationMandatoryRule.java @@ -0,0 +1,101 @@ +package org.sonar.samples.java.checks; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; +import org.sonar.java.model.PackageUtils; +import org.sonar.plugins.java.api.JavaFileScanner; +import org.sonar.plugins.java.api.JavaFileScannerContext; +import org.sonar.plugins.java.api.tree.AnnotationTree; +import org.sonar.plugins.java.api.tree.BaseTreeVisitor; +import org.sonar.plugins.java.api.tree.ClassTree; +import org.sonar.plugins.java.api.tree.CompilationUnitTree; +import org.sonar.plugins.java.api.tree.IdentifierTree; +import org.sonar.plugins.java.api.tree.MethodTree; +import org.sonar.plugins.java.api.tree.Tree; +import org.sonar.plugins.java.api.tree.TypeTree; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +@Rule(key = "SecurityAnnotationMandatory", + name = "Security Annotation Mandatory", + description = "Security Annotation Mandatory", + tags = {"security"}) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY) +@SqaleConstantRemediation("10min") +public class SecurityAnnotationMandatoryRule extends BaseTreeVisitor implements JavaFileScanner { + + private static final Logger LOGGER = LoggerFactory.getLogger(SecurityAnnotationMandatoryRule.class); + + private static final String DEFAULT_VALUE = "MySecurityAnnotation"; + + private boolean implementsSpecificInterface = Boolean.FALSE; + + private JavaFileScannerContext context; + + @RuleProperty( + defaultValue = DEFAULT_VALUE, + description = "Name of the mandatory annotation") + protected String name; + + @Override + public void scanFile(JavaFileScannerContext context) { + this.context = context; + scan(context.getTree()); + } + + @Override + public void visitClass(ClassTree tree) { + List interfaces = tree.superInterfaces(); + for (TypeTree typeTree : interfaces) { + LOGGER.info("implements Interface : " + typeTree); + if ("MySecurityInterface".equals(typeTree.toString())) { + implementsSpecificInterface = Boolean.TRUE; + } + } + + super.visitClass(tree); + } + + @Override + public void visitCompilationUnit(CompilationUnitTree tree) { + + if (tree.packageDeclaration() != null) { + String packageName = PackageUtils.packageName(tree.packageDeclaration(), "."); + LOGGER.info("PackageName : " + packageName); + } + + super.visitCompilationUnit(tree); + } + + @Override + public void visitMethod(MethodTree tree) { + if (implementsSpecificInterface) { + List annotations = tree.modifiers().annotations(); + + boolean isHavingMandatoryAnnotation = Boolean.FALSE; + + for (AnnotationTree annotationTree : annotations) { + if (annotationTree.annotationType().is(Tree.Kind.IDENTIFIER)) { + IdentifierTree idf = (IdentifierTree) annotationTree.annotationType(); + LOGGER.info("Method Name {}", idf.name()); + + if (idf.name().equals(name)) { + isHavingMandatoryAnnotation = Boolean.TRUE; + } + } + } + if (!isHavingMandatoryAnnotation) { + context.addIssue(tree, this, String.format("Mandatory Annotation not set @%s", name)); + } + + } + // The call to the super implementation allows to continue the visit of the AST. + // Be careful to always call this method to visit every node of the tree. + super.visitMethod(tree); + } +} diff --git a/plugins/java-custom-rules/src/test/files/AvoidAnnotationCheck.java b/plugins/java-custom-rules/src/test/files/AvoidAnnotationCheck.java new file mode 100644 index 00000000..d3df6680 --- /dev/null +++ b/plugins/java-custom-rules/src/test/files/AvoidAnnotationCheck.java @@ -0,0 +1,19 @@ +/** + *This file is the sample code against we run our unit test. + *It is placed src/test/files in order to not be part of the maven compilation. + **/ +class AvoidAnnotationCheck { + + int aField; + + @MyAnnotation + public void aMethod() { + + } + + @Zuper // Noncompliant {{Avoid using annotation @Zuper}} + public void aMethod() { + + } + +} diff --git a/plugins/java-custom-rules/src/test/files/AvoidBrandInMethodNamesCheck.java b/plugins/java-custom-rules/src/test/files/AvoidBrandInMethodNamesCheck.java new file mode 100644 index 00000000..a3d952f3 --- /dev/null +++ b/plugins/java-custom-rules/src/test/files/AvoidBrandInMethodNamesCheck.java @@ -0,0 +1,21 @@ +/** + *This file is the sample code against we run our unit test. + *It is placed src/test/files in order to not be part of the maven compilation. + **/ +class AvoidBrandInNamesCheck { + + int aField; + + public void methodWithMYCOMPANY() { // Noncompliant {{Avoid using Brand in method name}} + + } + + public void methodWithMyCompany() { // Noncompliant {{Avoid using Brand in method name}} + + } + + public void methodWithMyOtherCompany() { + + } + +} diff --git a/plugins/java-custom-rules/src/test/files/AvoidMethodDeclarationCheck.java b/plugins/java-custom-rules/src/test/files/AvoidMethodDeclarationCheck.java new file mode 100644 index 00000000..24b9b620 --- /dev/null +++ b/plugins/java-custom-rules/src/test/files/AvoidMethodDeclarationCheck.java @@ -0,0 +1,13 @@ +/** + *This file is the sample code against we run our unit test. + *It is placed src/test/files in order to not be part of the maven compilation. + **/ +class AvoidMethodDeclarationCheck { + + int aField; + + public void aMethod() { // Noncompliant {{Avoid method calls (don't ask why)}} + + } + +} diff --git a/plugins/java-custom-rules/src/test/files/AvoidSuperClassCheck.java b/plugins/java-custom-rules/src/test/files/AvoidSuperClassCheck.java new file mode 100644 index 00000000..a4e3d660 --- /dev/null +++ b/plugins/java-custom-rules/src/test/files/AvoidSuperClassCheck.java @@ -0,0 +1,17 @@ +/* + * Creation : 20 avr. 2015 + */ +package org.sonar.samples.java; + +import org.apache.log4j.Logger; + +/** + * A class with extends another class outside the JVM but in classpath + */ +public class AvoidSuperClassCheck extends Logger { // Noncompliant {{The usage of super class org.apache.log4j.Logger is forbidden}} + + protected AvoidSuperClassCheck(String name) { + super(name); + } + +} diff --git a/plugins/java-custom-rules/src/test/files/AvoidUnmodifiableList.java b/plugins/java-custom-rules/src/test/files/AvoidUnmodifiableList.java new file mode 100644 index 00000000..a6acadbb --- /dev/null +++ b/plugins/java-custom-rules/src/test/files/AvoidUnmodifiableList.java @@ -0,0 +1,17 @@ +import org.apache.commons.collections4.list.UnmodifiableList; +import java.util.ArrayList; + +import java.util.ArrayList; + +class A { + void foo() { + UnmodifiableList myList = new UnmodifiableList(new ArrayList<>()); // Noncompliant {{Avoid using UnmodifiableList}} + // Noncompliant@+1 + MyList myOtherList = new MyList(); // as MyList extends the UnmodifiableList, we expect an issue here + } +} + +class MyList extends UnmodifiableList { + public MyList() { + } +} diff --git a/plugins/java-custom-rules/src/test/files/MyCustomRule.java b/plugins/java-custom-rules/src/test/files/MyCustomRule.java new file mode 100644 index 00000000..29cde439 --- /dev/null +++ b/plugins/java-custom-rules/src/test/files/MyCustomRule.java @@ -0,0 +1,10 @@ +class A { + + int foo() {} + int foo(int a) {} // Noncompliant {{message}} + int foo(int a, int b) {} + + Object foo(Object a){} // Noncompliant {{message}} + String foo(String a){} // Noncompliant {{message}} + String foo(Object a){} +} \ No newline at end of file diff --git a/plugins/java-custom-rules/src/test/files/SecurityAnnotationMandatoryCheck.java b/plugins/java-custom-rules/src/test/files/SecurityAnnotationMandatoryCheck.java new file mode 100644 index 00000000..e3b8e263 --- /dev/null +++ b/plugins/java-custom-rules/src/test/files/SecurityAnnotationMandatoryCheck.java @@ -0,0 +1,20 @@ +package company.demo; + +/** + *This file is the sample code against we run our unit test. + *It is placed src/test/files in order to not be part of the maven compilation. + **/ +class BusinessClassDelegate implements MySecurityInterface, SecondInterface { + + int aField; + + @MySecurityAnnotation + public void aMethod() { + + } + + public void aMethod() { // Noncompliant {{Mandatory Annotation not set @MySecurityAnnotation}} + + } + +} diff --git a/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidAnnotationCheckTest.java b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidAnnotationCheckTest.java new file mode 100644 index 00000000..694ec699 --- /dev/null +++ b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidAnnotationCheckTest.java @@ -0,0 +1,22 @@ +package org.sonar.samples.java.checks; + +import org.junit.Test; +import org.sonar.java.checks.verifier.JavaCheckVerifier; + +public class AvoidAnnotationCheckTest { + + @Test + public void detected() { + + // Use an instance of the check under test to raise the issue. + AvoidAnnotationRule check = new AvoidAnnotationRule(); + + // define the forbidden annotation name + check.name = "Zuper"; + + // Verifies that the check will raise the adequate issues with the expected message. + // In the test file, lines which should raise an issue have been commented out + // by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}" + JavaCheckVerifier.verify("src/test/files/AvoidAnnotationCheck.java", check); + } +} diff --git a/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidBrandInMethodNamesCheckTest.java b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidBrandInMethodNamesCheckTest.java new file mode 100644 index 00000000..45f96d16 --- /dev/null +++ b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidBrandInMethodNamesCheckTest.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2009-2014 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ + +package org.sonar.samples.java.checks; + +import org.junit.Test; +import org.sonar.java.checks.verifier.JavaCheckVerifier; + +public class AvoidBrandInMethodNamesCheckTest { + + @Test + public void detected() { + // Verifies that the check will raise the adequate issues with the expected message. + // In the test file, lines which should raise an issue have been commented out + // by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}" + JavaCheckVerifier.verify("src/test/files/AvoidBrandInMethodNamesCheck.java", new AvoidBrandInMethodNamesRule()); + } +} diff --git a/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidMethodDeclarationCheckTest.java b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidMethodDeclarationCheckTest.java new file mode 100644 index 00000000..f37a8469 --- /dev/null +++ b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidMethodDeclarationCheckTest.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009-2014 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ + +package org.sonar.samples.java.checks; + +import org.junit.Test; +import org.sonar.java.checks.verifier.JavaCheckVerifier; + +/** + * This class is the test of the ExampleCheck. + * Checks by running it against a minimal valid file. + */ +public class AvoidMethodDeclarationCheckTest { + + @Test + public void detected() { + // Verifies that the check will raise the adequate issues with the expected message. + // In the test file, lines which should raise an issue have been commented out + // by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}" + JavaCheckVerifier.verify("src/test/files/AvoidMethodDeclarationCheck.java", new AvoidMethodDeclarationRule()); + } +} diff --git a/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidSuperClassCheckTest.java b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidSuperClassCheckTest.java new file mode 100644 index 00000000..a0ae03d1 --- /dev/null +++ b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidSuperClassCheckTest.java @@ -0,0 +1,39 @@ +/* + * Creation : 20 avr. 2015 + */ +package org.sonar.samples.java.checks; + +import org.junit.Test; +import org.sonar.java.checks.verifier.JavaCheckVerifier; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class AvoidSuperClassCheckTest { + + /** JAR dependencies for classpath execution */ + private static final List CLASSPATH_JAR; + + static { + // Jar ClassPath construction. Don't use 'ClassLoader.getSystemClassLoader()', because with Maven+Surefire/Jacoco execution, only + // surefirebooter.jar & jacoco.agent-version-runtime.jar are on classpath => 'old schoold way' + CLASSPATH_JAR = new ArrayList<>(); + for (String jar : System.getProperty("java.class.path").split(File.pathSeparator)) { + if (jar.endsWith(".jar")) { + CLASSPATH_JAR.add(new File(jar)); + } + } + } + + @Test + public void checkWithJarDependenciesInClassPath() throws Exception { + // As external sources are required to run the rule ('symbolType' used in custom rule, which is + // part of the semantic API), the test requires external dependencies in order to be run correctly. + + // Verifies that the check will raise the adequate issues with the expected message. + // In the test file, lines which should raise an issue have been commented out + // by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}" + JavaCheckVerifier.verify("src/test/files/AvoidSuperClassCheck.java", new AvoidSuperClassRule(), CLASSPATH_JAR); + } +} diff --git a/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidUnmodifiableListTest.java b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidUnmodifiableListTest.java new file mode 100644 index 00000000..2658b75f --- /dev/null +++ b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/AvoidUnmodifiableListTest.java @@ -0,0 +1,18 @@ +package org.sonar.samples.java.checks; + +import org.junit.Test; +import org.sonar.java.checks.verifier.JavaCheckVerifier; + +public class AvoidUnmodifiableListTest { + + @Test + public void verify() { + // In order to test this check efficiently, we added the test-jar "org.apache.commons.commons-collections4" to the pom, + // which is normally not used by the code of our custom plugin. + // All the classes from this jar will then be read when verifying the ticket, allowing correct type resolution. + + // Verifies automatically that the check will raise the adequate issues with the expected message + JavaCheckVerifier.verify("src/test/files/AvoidUnmodifiableList.java", new AvoidUnmodifiableListRule()); + } + +} diff --git a/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/MyCustomSubscriptionRuleTest.java b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/MyCustomSubscriptionRuleTest.java new file mode 100644 index 00000000..dc00bf48 --- /dev/null +++ b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/MyCustomSubscriptionRuleTest.java @@ -0,0 +1,15 @@ +package org.sonar.samples.java.checks; + +import org.junit.Test; +import org.sonar.java.checks.verifier.JavaCheckVerifier; + +public class MyCustomSubscriptionRuleTest { + + @Test + public void check() { + // Verifies that the check will raise the adequate issues with the expected message. + // In the test file, lines which should raise an issue have been commented out + // by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}" + JavaCheckVerifier.verify("src/test/files/MyCustomRule.java", new MyCustomSubscriptionRule()); + } +} diff --git a/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/SecurityAnnotationMandatoryCheckTest.java b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/SecurityAnnotationMandatoryCheckTest.java new file mode 100644 index 00000000..5735f9b7 --- /dev/null +++ b/plugins/java-custom-rules/src/test/java/org/sonar/samples/java/checks/SecurityAnnotationMandatoryCheckTest.java @@ -0,0 +1,27 @@ +package org.sonar.samples.java.checks; + +import org.junit.Rule; +import org.junit.Test; +import org.sonar.java.checks.verifier.JavaCheckVerifier; +import org.sonar.squidbridge.checks.CheckMessagesVerifierRule; + +public class SecurityAnnotationMandatoryCheckTest { + + @Rule + public CheckMessagesVerifierRule checkMessagesVerifier = new CheckMessagesVerifierRule(); + + @Test + public void detected() { + + // Use an instance of the check under test to raise the issue. + SecurityAnnotationMandatoryRule check = new SecurityAnnotationMandatoryRule(); + + // define the mandatory annotation name + check.name = "MySecurityAnnotation"; + + // Verifies that the check will raise the adequate issues with the expected message. + // In the test file, lines which should raise an issue have been commented out + // by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}" + JavaCheckVerifier.verify("src/test/files/SecurityAnnotationMandatoryCheck.java", check); + } +} diff --git a/plugins/javascript-custom-rules/pom.xml b/plugins/javascript-custom-rules/pom.xml new file mode 100644 index 00000000..13e982a6 --- /dev/null +++ b/plugins/javascript-custom-rules/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + com.sonarsource.it.javascript + javascript-custom-rules-plugin + 1.0-SNAPSHOT + sonar-plugin + + JavaScript Custom Rules Plugin + JavaScript Custom Rules + + + 8.7.0.17093 + + + + + org.codehaus.sonar + sonar-plugin-api + 5.0 + provided + + + + org.sonarsource.javascript + sonar-javascript-plugin + sonar-plugin + ${javascript.version} + provided + + + + org.sonarsource.javascript + javascript-checks-testkit + ${javascript.version} + test + + + + junit + junit + 4.13.2 + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + org.sonar.samples.javascript.JavaScriptCustomRulesPlugin + javascript + custom + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + diff --git a/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/JavaScriptCustomRulesPlugin.java b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/JavaScriptCustomRulesPlugin.java new file mode 100644 index 00000000..605f5703 --- /dev/null +++ b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/JavaScriptCustomRulesPlugin.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.javascript; + +import com.google.common.collect.ImmutableList; +import org.sonar.api.SonarPlugin; + +import java.util.List; + +/** + * Extension point to define a Sonar Plugin. + */ +public class JavaScriptCustomRulesPlugin extends SonarPlugin { + + @Override + public List getExtensions() { + return ImmutableList.of( + JavascriptCustomRulesDefinition.class + ); + } + +} diff --git a/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/JavascriptCustomRulesDefinition.java b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/JavascriptCustomRulesDefinition.java new file mode 100644 index 00000000..1130e8c9 --- /dev/null +++ b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/JavascriptCustomRulesDefinition.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.javascript; + + +import org.sonar.plugins.javascript.api.CustomJavaScriptRulesDefinition; +import org.sonar.samples.javascript.checks.ForbiddenFunctionUseCheck; +import org.sonar.samples.javascript.checks.OtherForbiddenFunctionUseCheck; + +/** + * Extension point to define a javascript JavaScript rule repository. + */ +public class JavascriptCustomRulesDefinition extends CustomJavaScriptRulesDefinition { + + /** + * Provide the repository name + */ + @Override + public String repositoryName() { + return "Custom Repository"; + } + + /** + * Provide the repository key + */ + @Override + public String repositoryKey() { + return "custom"; + } + + /** + * Provide the list of checks class that implements rules + * to be part of the rule repository + */ + @Override + public Class[] checkClasses() { + return new Class[] {ForbiddenFunctionUseCheck.class, OtherForbiddenFunctionUseCheck.class}; + } +} diff --git a/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/checks/ForbiddenFunctionUseCheck.java b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/checks/ForbiddenFunctionUseCheck.java new file mode 100644 index 00000000..a3a51ada --- /dev/null +++ b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/checks/ForbiddenFunctionUseCheck.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.javascript.checks; + +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.plugins.javascript.api.tree.Tree.Kind; +import org.sonar.plugins.javascript.api.tree.expression.CallExpressionTree; +import org.sonar.plugins.javascript.api.tree.expression.ExpressionTree; +import org.sonar.plugins.javascript.api.tree.expression.IdentifierTree; +import org.sonar.plugins.javascript.api.visitors.DoubleDispatchVisitorCheck; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +/** + * Example of implementation of a check by extending {@link DoubleDispatchVisitorCheck}. + * DoubleDispatchVisitorCheck provides methods to visit nodes of the Abstract Syntax Tree + * that represents the source code. + *

+ * Those methods can be overridden to process information + * related to node and issues can be created via {@link DoubleDispatchVisitorCheck#addIssue} methods}. + */ +@Rule( + key = "S1", + priority = Priority.MAJOR, + name = "Forbidden function should not be used.", + tags = {"convention"} +// Description can either be given in this annotation or through HTML name .html located in package src/resources/org/sonar/l10n/javascript/rules/ +// description = "

The following functions should not be used:

  • foo
  • bar
", + ) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.DATA_RELIABILITY) +@SqaleConstantRemediation("5min") +public class ForbiddenFunctionUseCheck extends DoubleDispatchVisitorCheck { + + private static final Set FORBIDDEN_FUNCTIONS = ImmutableSet.of("foo", "bar"); + + /** + * Overriding method visiting the call expression to create an issue + * each time a call to "foo()" or "bar()" is done. + */ + @Override + public void visitCallExpression(CallExpressionTree tree) { + ExpressionTree callee = tree.callee(); + + if (callee.is(Kind.IDENTIFIER_REFERENCE) && FORBIDDEN_FUNCTIONS.contains(((IdentifierTree) callee).name())) { + addIssue(tree, "Remove the usage of this forbidden function."); + } + + // super method must be called in order to visit what is under the function node in the syntax tree + super.visitCallExpression(tree); + } + +} diff --git a/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/checks/OtherForbiddenFunctionUseCheck.java b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/checks/OtherForbiddenFunctionUseCheck.java new file mode 100644 index 00000000..dd5289de --- /dev/null +++ b/plugins/javascript-custom-rules/src/main/java/org/sonar/samples/javascript/checks/OtherForbiddenFunctionUseCheck.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.javascript.checks; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import java.util.List; +import java.util.Set; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.plugins.javascript.api.tree.Tree; +import org.sonar.plugins.javascript.api.tree.Tree.Kind; +import org.sonar.plugins.javascript.api.tree.expression.CallExpressionTree; +import org.sonar.plugins.javascript.api.tree.expression.ExpressionTree; +import org.sonar.plugins.javascript.api.tree.expression.IdentifierTree; +import org.sonar.plugins.javascript.api.visitors.SubscriptionVisitorCheck; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +/** + * Example of a check extending {@link SubscriptionVisitorCheck}. + * + * We define the kinds of the nodes that we subscribe to in {@link #nodesToVisit()}. + * We can then override visitNode or leaveNode: these methods will be called for all nodes + * of the kinds we subscribed to. + */ +@Rule( + key = "S2", + priority = Priority.MINOR, + name = "'baz' function should not be used.", + tags = {"convention"}, + description = "It's better not to use the 'baz' function." + ) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.DATA_RELIABILITY) +@SqaleConstantRemediation("5min") +public class OtherForbiddenFunctionUseCheck extends SubscriptionVisitorCheck { + + private static final Set FORBIDDEN_FUNCTIONS = ImmutableSet.of("baz"); + + @Override + public List nodesToVisit() { + return ImmutableList.of(Kind.CALL_EXPRESSION); + } + + @Override + public void visitNode(Tree tree) { + // we can do this cast because we subscribed only to nodes of kind CALL_EXPRESSION + CallExpressionTree callExpressionTree = (CallExpressionTree) tree; + ExpressionTree callee = callExpressionTree.callee(); + if (callee.is(Kind.IDENTIFIER_REFERENCE) && FORBIDDEN_FUNCTIONS.contains(((IdentifierTree) callee).name())) { + addIssue(tree, "Remove the usage of this forbidden function."); + } + } + +} diff --git a/plugins/javascript-custom-rules/src/main/resources/org/sonar/l10n/javascript/rules/custom/S1.html b/plugins/javascript-custom-rules/src/main/resources/org/sonar/l10n/javascript/rules/custom/S1.html new file mode 100644 index 00000000..1bf97c04 --- /dev/null +++ b/plugins/javascript-custom-rules/src/main/resources/org/sonar/l10n/javascript/rules/custom/S1.html @@ -0,0 +1,7 @@ +

+ The following functions should not be used: +

+
    +
  • foo
  • +
  • bar
  • +
\ No newline at end of file diff --git a/plugins/javascript-custom-rules/src/test/java/org/sonar/samples/javascript/checks/ForbiddenFunctionUseCheckTest.java b/plugins/javascript-custom-rules/src/test/java/org/sonar/samples/javascript/checks/ForbiddenFunctionUseCheckTest.java new file mode 100644 index 00000000..f0dad742 --- /dev/null +++ b/plugins/javascript-custom-rules/src/test/java/org/sonar/samples/javascript/checks/ForbiddenFunctionUseCheckTest.java @@ -0,0 +1,22 @@ +package org.sonar.samples.javascript.checks; + +import java.io.File; +import org.junit.Test; +import org.sonar.javascript.checks.verifier.JavaScriptCheckVerifier; + +/** + * Test class to test the check implementation. + */ +public class ForbiddenFunctionUseCheckTest { + + @Test + public void test() throws Exception { + JavaScriptCheckVerifier.issues(new ForbiddenFunctionUseCheck(), new File("src/test/resources/checks/forbiddenFunctionUseCheck.js")) + .next().atLine(1).withMessage("Remove the usage of this forbidden function.") + .next().atLine(2) + .next().atLine(4) + .next().atLine(5) + .noMore(); + } + +} diff --git a/plugins/javascript-custom-rules/src/test/java/org/sonar/samples/javascript/checks/OtherForbiddenFunctionUseCheckTest.java b/plugins/javascript-custom-rules/src/test/java/org/sonar/samples/javascript/checks/OtherForbiddenFunctionUseCheckTest.java new file mode 100644 index 00000000..ea361f0a --- /dev/null +++ b/plugins/javascript-custom-rules/src/test/java/org/sonar/samples/javascript/checks/OtherForbiddenFunctionUseCheckTest.java @@ -0,0 +1,17 @@ +package org.sonar.samples.javascript.checks; + +import java.io.File; +import org.junit.Test; +import org.sonar.javascript.checks.verifier.JavaScriptCheckVerifier; + +/** + * Test class to test the check implementation. + */ +public class OtherForbiddenFunctionUseCheckTest { + + @Test + public void test() throws Exception { + JavaScriptCheckVerifier.verify(new OtherForbiddenFunctionUseCheck(), new File("src/test/resources/checks/otherForbiddenFunctionUseCheck.js")); + } + +} diff --git a/plugins/javascript-custom-rules/src/test/resources/checks/forbiddenFunctionUseCheck.js b/plugins/javascript-custom-rules/src/test/resources/checks/forbiddenFunctionUseCheck.js new file mode 100644 index 00000000..773a9332 --- /dev/null +++ b/plugins/javascript-custom-rules/src/test/resources/checks/forbiddenFunctionUseCheck.js @@ -0,0 +1,20 @@ +foo(); // NOK +foo(1); // NOK + +bar(); // NOK +bar(1); // NOK + +var Obj = { + foo : function () { + return "foo"; + }, + + bar : function () { + return "bar"; + } +}; + +var myObj = new Obj(); + +myObj.foo(); // OK +myObj.bar(); // OK \ No newline at end of file diff --git a/plugins/javascript-custom-rules/src/test/resources/checks/otherForbiddenFunctionUseCheck.js b/plugins/javascript-custom-rules/src/test/resources/checks/otherForbiddenFunctionUseCheck.js new file mode 100644 index 00000000..5ef61f24 --- /dev/null +++ b/plugins/javascript-custom-rules/src/test/resources/checks/otherForbiddenFunctionUseCheck.js @@ -0,0 +1,6 @@ +baz(); // Noncompliant +baz(1); // Noncompliant {{Remove the usage of this forbidden function.}} [[sc=1;ec=7]] + +foo(); + +x.baz(); // OK diff --git a/plugins/sonar-checkstyle-extension-plugin/pom.xml b/plugins/php-custom-rules/pom.xml similarity index 53% rename from plugins/sonar-checkstyle-extension-plugin/pom.xml rename to plugins/php-custom-rules/pom.xml index 083e32f2..31310099 100644 --- a/plugins/sonar-checkstyle-extension-plugin/pom.xml +++ b/plugins/php-custom-rules/pom.xml @@ -2,47 +2,62 @@ 4.0.0 - org.codehaus.sonar.examples - sonar-checkstyle-extension-plugin + + org.sonar.examples + php-custom-rules 1.0-SNAPSHOT sonar-plugin - Sonar Examples :: Checkstyle Extension Plugin + + PHP Custom Rules + PHP Custom Rules org.codehaus.sonar sonar-plugin-api - 2.11 + 5.0 + provided + + + + org.sonarsource.php + sonar-php-plugin + sonar-plugin + 3.23.0.8726 + provided + - com.puppycrawl.tools - checkstyle - 5.5 + junit + junit + 4.13.1 - org.codehaus.sonar + org.sonarsource.sonar-packaging-maven-plugin sonar-packaging-maven-plugin - 1.1 + 1.15 true - org.sonar.examples.checkstyle.CheckstyleExtensionPlugin - checkstyle + org.sonar.samples.php.PHPCustomRulesPlugin + php + custom + org.apache.maven.plugins maven-compiler-plugin 2.3.2 - 1.5 - 1.5 - UTF-8 + 1.7 + 1.7 + diff --git a/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/PHPCustomRulesPlugin.java b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/PHPCustomRulesPlugin.java new file mode 100644 index 00000000..2d2f7327 --- /dev/null +++ b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/PHPCustomRulesPlugin.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.php; + +import com.google.common.collect.ImmutableList; +import org.sonar.api.SonarPlugin; + +import java.util.List; + +/** + * Extension point to define a Sonar Plugin. + */ +public class PHPCustomRulesPlugin extends SonarPlugin { + + @Override + public List getExtensions() { + return ImmutableList.of( + PHPRulesDefinition.class + ); + } + +} diff --git a/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/PHPRulesDefinition.java b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/PHPRulesDefinition.java new file mode 100644 index 00000000..f26e2a44 --- /dev/null +++ b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/PHPRulesDefinition.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.php; + + +import com.google.common.collect.ImmutableList; + +import org.sonar.plugins.php.api.visitors.PHPCustomRulesDefinition; +import org.sonar.samples.php.checks.ForbiddenFunctionUseCheck; + +/** + * Extension point to define a PHP rule repository. + */ +public class PHPRulesDefinition extends PHPCustomRulesDefinition { + + /** + * Provide the repository name + */ + @Override + public String repositoryName() { + return "Custom Repository"; + } + + /** + * Provide the repository key + */ + @Override + public String repositoryKey() { + return "custom"; + } + + /** + * Provide the list of checks class that implements rules + * to be part of the rule repository + */ + @Override + public ImmutableList checkClasses() { + return ImmutableList.of(ForbiddenFunctionUseCheck.class); + } +} diff --git a/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/checks/ForbiddenFunctionUseCheck.java b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/checks/ForbiddenFunctionUseCheck.java new file mode 100644 index 00000000..2ff7d882 --- /dev/null +++ b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/checks/ForbiddenFunctionUseCheck.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.php.checks; + +import com.google.common.collect.ImmutableSet; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.plugins.php.api.tree.Tree.Kind; +import org.sonar.plugins.php.api.tree.declaration.NamespaceNameTree; +import org.sonar.plugins.php.api.tree.expression.ExpressionTree; +import org.sonar.plugins.php.api.tree.expression.FunctionCallTree; +import org.sonar.plugins.php.api.visitors.PHPVisitorCheck; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +import java.util.Set; + +/** + * Example of implementation of a check by extending {@link PHPVisitorCheck}. + * PHPVisitorCheck provides methods to visit nodes of the Abstract Syntax Tree + * that represents the source code. + *

+ * Those methods can be overridden to process information + * related to node and issue can be created via the context that can be + * accessed through {@link PHPVisitorCheck#context()}. + */ +@Rule( + key = "S1", + priority = Priority.MAJOR, + name = "Forbidden function should not be used.", + tags = {"convention"} +// Description can either be given in this annotation or through HTML name .html located in package src/resources/org/sonar/l10n/php/rules/ +// description = "

The following functions should not be used:

  • foo
  • bar
" + ) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.DATA_RELIABILITY) +@SqaleConstantRemediation("5min") +public class ForbiddenFunctionUseCheck extends PHPVisitorCheck { + + private static final Set FORBIDDEN_FUNCTIONS = ImmutableSet.of("foo", "bar"); + + /** + * Overriding method visiting the call expression to create an issue + * each time a call to "foo()" or "bar()" is done. + */ + @Override + public void visitFunctionCall(FunctionCallTree tree) { + ExpressionTree callee = tree.callee(); + + if (callee.is(Kind.NAMESPACE_NAME) && FORBIDDEN_FUNCTIONS.contains(((NamespaceNameTree) callee).qualifiedName())) { + context().newIssue(this, "Remove the usage of this forbidden function.").tree(tree); + } + + // super method must be called in order to visit function call node's children + super.visitFunctionCall(tree); + } + +} diff --git a/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/checks/OtherForbiddenFunctionUseCheck.java b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/checks/OtherForbiddenFunctionUseCheck.java new file mode 100644 index 00000000..b535bd2e --- /dev/null +++ b/plugins/php-custom-rules/src/main/java/org/sonar/samples/php/checks/OtherForbiddenFunctionUseCheck.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.samples.php.checks; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.plugins.php.api.tree.Tree; +import org.sonar.plugins.php.api.tree.Tree.Kind; +import org.sonar.plugins.php.api.tree.declaration.NamespaceNameTree; +import org.sonar.plugins.php.api.tree.expression.ExpressionTree; +import org.sonar.plugins.php.api.tree.expression.FunctionCallTree; +import org.sonar.plugins.php.api.visitors.PHPSubscriptionCheck; +import org.sonar.plugins.php.api.visitors.PHPVisitorCheck; +import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.squidbridge.annotations.SqaleSubCharacteristic; + +import java.util.List; +import java.util.Set; + +/** + * Example of implementation of a check by extending {@link PHPSubscriptionCheck}. + * PHPSubscriptionCheck provides method {@link PHPSubscriptionCheck#visitNode} to visit nodes of the Abstract Syntax Tree + * that represents the source code. Provide the list of nodes you want to visit through {@link PHPSubscriptionCheck#nodesToVisit}. + *

+ * Those methods should be overridden to process information + * related to node and issue can be created via the context that can be + * accessed through {@link PHPVisitorCheck#context()}. + */ +@Rule( + key = "S1", + priority = Priority.MAJOR, + name = "Forbidden function should not be used.", + tags = {"convention"} +// Description can either be given in this annotation or through HTML name .html located in package src/resources/org/sonar/l10n/php/rules/ +// description = "

The following functions should not be used:

  • foo
  • bar
", + ) +@SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.DATA_RELIABILITY) +@SqaleConstantRemediation("5min") +public class OtherForbiddenFunctionUseCheck extends PHPSubscriptionCheck { + + private static final Set FORBIDDEN_FUNCTIONS = ImmutableSet.of("foo", "bar"); + + @Override + public List nodesToVisit() { + return ImmutableList.of(Kind.FUNCTION_CALL); + } + + /** + * Overriding method visiting the call expression to create an issue + * each time a call to "foo()" or "bar()" is done. + */ + @Override + public void visitNode(Tree tree) { + ExpressionTree callee = ((FunctionCallTree) tree).callee(); + + if (callee.is(Kind.NAMESPACE_NAME) && FORBIDDEN_FUNCTIONS.contains(((NamespaceNameTree) callee).qualifiedName())) { + context().newIssue(this, "Remove the usage of this forbidden function.").tree(tree); + } + } + +} diff --git a/plugins/php-custom-rules/src/main/resources/org/sonar/l10n/php/rules/custom/S1.html b/plugins/php-custom-rules/src/main/resources/org/sonar/l10n/php/rules/custom/S1.html new file mode 100644 index 00000000..1bf97c04 --- /dev/null +++ b/plugins/php-custom-rules/src/main/resources/org/sonar/l10n/php/rules/custom/S1.html @@ -0,0 +1,7 @@ +

+ The following functions should not be used: +

+
    +
  • foo
  • +
  • bar
  • +
\ No newline at end of file diff --git a/plugins/php-custom-rules/src/test/java/org/sonar/samples/php/checks/ForbiddenFunctionUseCheckTest.java b/plugins/php-custom-rules/src/test/java/org/sonar/samples/php/checks/ForbiddenFunctionUseCheckTest.java new file mode 100644 index 00000000..5037d0e6 --- /dev/null +++ b/plugins/php-custom-rules/src/test/java/org/sonar/samples/php/checks/ForbiddenFunctionUseCheckTest.java @@ -0,0 +1,18 @@ +package org.sonar.samples.php.checks; + +import org.junit.Test; +import org.sonar.plugins.php.api.tests.PHPCheckTest; + +import java.io.File; + +/** + * Test class to test the check implementation. + */ +public class ForbiddenFunctionUseCheckTest { + + @Test + public void test() throws Exception { + PHPCheckTest.check(new ForbiddenFunctionUseCheck(), new File("src/test/resources/checks/forbiddenFunctionUseCheck.js")); + } + +} diff --git a/plugins/php-custom-rules/src/test/java/org/sonar/samples/php/checks/OtherForbiddenFunctionUseCheckTest.java b/plugins/php-custom-rules/src/test/java/org/sonar/samples/php/checks/OtherForbiddenFunctionUseCheckTest.java new file mode 100644 index 00000000..ffb8e3ec --- /dev/null +++ b/plugins/php-custom-rules/src/test/java/org/sonar/samples/php/checks/OtherForbiddenFunctionUseCheckTest.java @@ -0,0 +1,18 @@ +package org.sonar.samples.php.checks; + +import org.junit.Test; +import org.sonar.plugins.php.api.tests.PHPCheckTest; + +import java.io.File; + +/** + * Test class to test the check implementation. + */ +public class OtherForbiddenFunctionUseCheckTest { + + @Test + public void test() throws Exception { + PHPCheckTest.check(new OtherForbiddenFunctionUseCheck(), new File("src/test/resources/checks/forbiddenFunctionUseCheck.js")); + } + +} diff --git a/plugins/php-custom-rules/src/test/resources/checks/forbiddenFunctionUseCheck.js b/plugins/php-custom-rules/src/test/resources/checks/forbiddenFunctionUseCheck.js new file mode 100644 index 00000000..cd501c59 --- /dev/null +++ b/plugins/php-custom-rules/src/test/resources/checks/forbiddenFunctionUseCheck.js @@ -0,0 +1,20 @@ +foo(); // NOK {{Remove the usage of this forbidden function.}} +foo(1); // NOK + +bar(); // NOK +bar(1); // NOK + +var Obj = { + foo : function () { + return "foo"; + }, + + bar : function () { + return "bar"; + } +}; + +var myObj = new Obj(); + +myObj.foo(); // OK +myObj.bar(); // OK diff --git a/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/CheckstyleExtensionPlugin.java b/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/CheckstyleExtensionPlugin.java deleted file mode 100644 index 7fe7ea36..00000000 --- a/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/CheckstyleExtensionPlugin.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.sonar.examples.checkstyle; - -import org.sonar.api.SonarPlugin; - -import java.util.Arrays; -import java.util.List; - -public final class CheckstyleExtensionPlugin extends SonarPlugin { - public List getExtensions() { - return Arrays.asList(CheckstyleExtensionRepository.class); - } -} diff --git a/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/CheckstyleExtensionRepository.java b/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/CheckstyleExtensionRepository.java deleted file mode 100644 index 458fcf16..00000000 --- a/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/CheckstyleExtensionRepository.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.sonar.examples.checkstyle; - -import org.apache.commons.io.IOUtils; -import org.sonar.api.resources.Java; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleRepository; -import org.sonar.api.rules.XMLRuleParser; - -import java.io.InputStream; -import java.util.List; - -public final class CheckstyleExtensionRepository extends RuleRepository { - - private XMLRuleParser xmlRuleParser; - - public CheckstyleExtensionRepository(XMLRuleParser xmlRuleParser) { - super("checkstyle", Java.KEY); - setName("Checkstyle"); - this.xmlRuleParser = xmlRuleParser; - } - - @Override - public List createRules() { - InputStream input = getClass().getResourceAsStream("/org/sonar/examples/checkstyle/checkstyle-extensions.xml"); - try { - return xmlRuleParser.parse(input); - - } finally { - IOUtils.closeQuietly(input); - } - } -} diff --git a/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/MethodsCountCheck.java b/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/MethodsCountCheck.java deleted file mode 100644 index 85653968..00000000 --- a/plugins/sonar-checkstyle-extension-plugin/src/main/java/org/sonar/examples/checkstyle/MethodsCountCheck.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.sonar.examples.checkstyle; - -import com.puppycrawl.tools.checkstyle.api.Check; -import com.puppycrawl.tools.checkstyle.api.DetailAST; -import com.puppycrawl.tools.checkstyle.api.TokenTypes; - -public class MethodsCountCheck extends Check { - - private int maxMethodsCount = 1; - - private int methodsCount = 0; - private DetailAST classAST = null; - - public void setMaxMethodsCount(int maxMethodsCount) { - this.maxMethodsCount = maxMethodsCount; - } - - public int[] getDefaultTokens() { - return new int[]{TokenTypes.CLASS_DEF, TokenTypes.METHOD_DEF}; - } - - public void beginTree(DetailAST rootAST) { - methodsCount = 0; - classAST = null; - } - - public void visitToken(DetailAST ast) { - //ensure this is an unit test. - if (ast.getType() == TokenTypes.CLASS_DEF) { - classAST = ast; - - } else if (ast.getType() == TokenTypes.METHOD_DEF) { - methodsCount++; - } - } - - public void finishTree(DetailAST rootAST) { - super.finishTree(rootAST); - if (classAST != null && methodsCount > maxMethodsCount) { - log(classAST.getLineNo(), classAST.getColumnNo(), "Too many methods (" + methodsCount + ") in class"); - } - } -} diff --git a/plugins/sonar-checkstyle-extension-plugin/src/main/resources/org/sonar/examples/checkstyle/checkstyle-extensions.xml b/plugins/sonar-checkstyle-extension-plugin/src/main/resources/org/sonar/examples/checkstyle/checkstyle-extensions.xml deleted file mode 100644 index 61ff7b1b..00000000 --- a/plugins/sonar-checkstyle-extension-plugin/src/main/resources/org/sonar/examples/checkstyle/checkstyle-extensions.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - org.sonar.examples.checkstyle.MethodsCountCheck - Methods Count Check - Checker/TreeWalker/org.sonar.examples.checkstyle.MethodsCountCheck - - Count methods - - maxMethodsCount - Maximum number of methods. Default is 10. - - - \ No newline at end of file diff --git a/plugins/sonar-reference-plugin/pom.xml b/plugins/sonar-example-plugin/pom.xml similarity index 55% rename from plugins/sonar-reference-plugin/pom.xml rename to plugins/sonar-example-plugin/pom.xml index 4795e768..d6856a64 100644 --- a/plugins/sonar-reference-plugin/pom.xml +++ b/plugins/sonar-example-plugin/pom.xml @@ -1,33 +1,47 @@ - + 4.0.0 - org.codehaus.sonar.examples - sonar-reference-plugin + + org.sonarsource.plugins.example + sonar-example-plugin sonar-plugin 0.1-SNAPSHOT - Sonar Examples :: Reference Plugin - plugin description will be displayed in Sonar + + Example Plugin for SonarQube + Example of plugin for SonarQube - 2.10 UTF-8 - 1.5 + 7.4 + 1.8 - org.codehaus.sonar + org.sonarsource.sonarqube sonar-plugin-api - ${sonar.buildVersion} + ${sonar.apiVersion} provided + + + commons-lang + commons-lang + 2.6 + + - org.codehaus.sonar + org.sonarsource.sonarqube sonar-testing-harness - ${sonar.buildVersion} + ${sonar.apiVersion} + test + + + junit + junit + 4.11 test @@ -35,18 +49,18 @@ - org.codehaus.sonar + org.sonarsource.sonar-packaging-maven-plugin sonar-packaging-maven-plugin - 1.1 + 1.16 true - com.mycompany.sonar.reference.ExamplePlugin + org.sonarsource.plugins.example.ExamplePlugin org.apache.maven.plugins maven-compiler-plugin - 2.0.2 + 3.5.1 ${jdk.min.version} ${jdk.min.version} @@ -56,21 +70,16 @@ org.codehaus.mojo native2ascii-maven-plugin - 1.0-alpha-1 + 1.0-beta-1 native2ascii - - UTF8 - ${basedir}/src/main/resources - ${project.build.outputDirectory} - **/*.properties - + diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/ExamplePlugin.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/ExamplePlugin.java new file mode 100644 index 00000000..6337095f --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/ExamplePlugin.java @@ -0,0 +1,51 @@ +package org.sonarsource.plugins.example; + +import org.sonar.api.Plugin; +import org.sonarsource.plugins.example.hooks.DisplayIssuesInScanner; +import org.sonarsource.plugins.example.hooks.DisplayQualityGateStatus; +import org.sonarsource.plugins.example.languages.FooLanguage; +import org.sonarsource.plugins.example.languages.FooQualityProfile; +import org.sonarsource.plugins.example.measures.ComputeSizeAverage; +import org.sonarsource.plugins.example.measures.ComputeSizeRating; +import org.sonarsource.plugins.example.measures.ExampleMetrics; +import org.sonarsource.plugins.example.measures.SetSizeOnFilesSensor; +import org.sonarsource.plugins.example.rules.CreateIssuesOnJavaFilesSensor; +import org.sonarsource.plugins.example.rules.FooLintIssuesLoaderSensor; +import org.sonarsource.plugins.example.rules.FooLintRulesDefinition; +import org.sonarsource.plugins.example.rules.JavaRulesDefinition; +import org.sonarsource.plugins.example.settings.ExampleProperties; +import org.sonarsource.plugins.example.settings.SayHelloFromScanner; +import org.sonarsource.plugins.example.web.ExampleFooter; +import org.sonarsource.plugins.example.web.ExampleWidget; + +/** + * This class is the entry point for all extensions. It is referenced in pom.xml. + */ +public class ExamplePlugin implements Plugin { + + @Override + public void define(Context context) { + // tutorial on hooks + // http://docs.sonarqube.org/display/DEV/Adding+Hooks + context.addExtensions(DisplayIssuesInScanner.class, DisplayQualityGateStatus.class); + + // tutorial on languages + context.addExtensions(FooLanguage.class, FooQualityProfile.class); + + // tutorial on measures + context + .addExtensions(ExampleMetrics.class, SetSizeOnFilesSensor.class, ComputeSizeAverage.class, ComputeSizeRating.class); + + // tutorial on rules + context.addExtensions(JavaRulesDefinition.class, CreateIssuesOnJavaFilesSensor.class); + context.addExtensions(FooLintRulesDefinition.class, FooLintIssuesLoaderSensor.class); + + // tutorial on settings + context + .addExtensions(ExampleProperties.definitions()) + .addExtension(SayHelloFromScanner.class); + + // tutorial on web extensions + context.addExtensions(ExampleFooter.class, ExampleWidget.class); + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/hooks/DisplayIssuesInScanner.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/hooks/DisplayIssuesInScanner.java new file mode 100644 index 00000000..ad48cf70 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/hooks/DisplayIssuesInScanner.java @@ -0,0 +1,39 @@ +package org.sonarsource.plugins.example.hooks; + +import org.sonar.api.batch.postjob.PostJob; +import org.sonar.api.batch.postjob.PostJobContext; +import org.sonar.api.batch.postjob.PostJobDescriptor; +import org.sonar.api.batch.postjob.issue.PostJobIssue; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +public class DisplayIssuesInScanner implements PostJob { + + private static final Logger LOGGER = Loggers.get(DisplayIssuesInScanner.class); + + @Override + public void describe(PostJobDescriptor descriptor) { + descriptor.name("Display issues"); + } + + @Override + public void execute(PostJobContext context) { + // issues are not accessible when the mode "issues" is not enabled + // with the scanner property "sonar.analysis.mode=issues" + if (context.analysisMode().isIssues()) { + // all open issues + for (PostJobIssue issue : context.issues()) { + String ruleKey = issue.ruleKey().toString(); + Integer issueLine = issue.line(); + + // just to illustrate, we dump some fields of the 'issue' in sysout (bad, very bad) + LOGGER.info("OPEN {} : {}({})", ruleKey, issue.componentKey(), issueLine); + } + + // all resolved issues + for (PostJobIssue issue : context.resolvedIssues()) { + LOGGER.info("RESOLVED {} : {}({})", issue.ruleKey(), issue.componentKey(), issue.line()); + } + } + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/hooks/DisplayQualityGateStatus.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/hooks/DisplayQualityGateStatus.java new file mode 100644 index 00000000..dcfc0437 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/hooks/DisplayQualityGateStatus.java @@ -0,0 +1,20 @@ +package org.sonarsource.plugins.example.hooks; + +import org.sonar.api.ce.posttask.PostProjectAnalysisTask; +import org.sonar.api.ce.posttask.QualityGate; +import org.sonar.api.utils.log.Loggers; + +/** + * Logs the Quality gate status in Compute Engine when analysis is finished (browse + * Administration > Projects > Background Tasks). + * A real use-case would be to send an email or to notify an IRC channel. + */ +public class DisplayQualityGateStatus implements PostProjectAnalysisTask { + @Override + public void finished(ProjectAnalysis analysis) { + QualityGate gate = analysis.getQualityGate(); + if (gate != null) { + Loggers.get(getClass()).info("Quality gate is " + gate.getStatus()); + } + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/languages/FooLanguage.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/languages/FooLanguage.java new file mode 100644 index 00000000..5e51be88 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/languages/FooLanguage.java @@ -0,0 +1,45 @@ +package org.sonarsource.plugins.example.languages; + +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.config.Settings; +import org.sonar.api.resources.AbstractLanguage; + +/** + * This class defines the fictive Foo language. + */ +public final class FooLanguage extends AbstractLanguage { + + public static final String NAME = "Foo"; + public static final String KEY = "foo"; + public static final String FILE_SUFFIXES_PROPERTY_KEY = "sonar.foo.file.suffixes"; + public static final String DEFAULT_FILE_SUFFIXES = "foo"; + + private final Settings settings; + + public FooLanguage(Settings settings) { + super(KEY, NAME); + this.settings = settings; + } + + @Override + public String[] getFileSuffixes() { + String[] suffixes = filterEmptyStrings(settings.getStringArray(FILE_SUFFIXES_PROPERTY_KEY)); + if (suffixes.length == 0) { + suffixes = StringUtils.split(DEFAULT_FILE_SUFFIXES, ","); + } + return suffixes; + } + + private String[] filterEmptyStrings(String[] stringArray) { + List nonEmptyStrings = new ArrayList<>(); + for (String string : stringArray) { + if (StringUtils.isNotBlank(string.trim())) { + nonEmptyStrings.add(string.trim()); + } + } + return nonEmptyStrings.toArray(new String[nonEmptyStrings.size()]); + } + +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/languages/FooQualityProfile.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/languages/FooQualityProfile.java new file mode 100644 index 00000000..3999a6e2 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/languages/FooQualityProfile.java @@ -0,0 +1,35 @@ +/* + * SonarQube Protocol Buffers Plugin + * Copyright (C) 2015 SonarSource + * sonarqube@googlegroups.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonarsource.plugins.example.languages; + +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.utils.ValidationMessages; + +/** + * Default Quality profile for the projects having files of language "foo" + */ +public final class FooQualityProfile extends ProfileDefinition { + + @Override + public RulesProfile createProfile(ValidationMessages validation) { + return RulesProfile.create("FooLint Rules", FooLanguage.KEY); + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ComputeSizeAverage.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ComputeSizeAverage.java new file mode 100644 index 00000000..cb31299d --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ComputeSizeAverage.java @@ -0,0 +1,33 @@ +package org.sonarsource.plugins.example.measures; + +import org.sonar.api.ce.measure.Component; +import org.sonar.api.ce.measure.Measure; +import org.sonar.api.ce.measure.MeasureComputer; + +import static org.sonarsource.plugins.example.measures.ExampleMetrics.FILENAME_SIZE; + +public class ComputeSizeAverage implements MeasureComputer { + + @Override + public MeasureComputerDefinition define(MeasureComputerDefinitionContext def) { + return def.newDefinitionBuilder() + .setOutputMetrics(FILENAME_SIZE.key()) + .build(); + } + + @Override + public void compute(MeasureComputerContext context) { + // measure is already defined on files by {@link SetSizeOnFilesSensor} + // in scanner stack + if (context.getComponent().getType() != Component.Type.FILE) { + int sum = 0; + int count = 0; + for (Measure child : context.getChildrenMeasures(FILENAME_SIZE.key())) { + sum += child.getIntValue(); + count++; + } + int average = count == 0 ? 0 : sum / count; + context.addMeasure(FILENAME_SIZE.key(), average); + } + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ComputeSizeRating.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ComputeSizeRating.java new file mode 100644 index 00000000..2e48a8e7 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ComputeSizeRating.java @@ -0,0 +1,38 @@ +package org.sonarsource.plugins.example.measures; + +import org.sonar.api.ce.measure.Measure; +import org.sonar.api.ce.measure.MeasureComputer; + +import static org.sonarsource.plugins.example.measures.ExampleMetrics.FILENAME_SIZE; +import static org.sonarsource.plugins.example.measures.ExampleMetrics.FILENAME_SIZE_RATING; + +/** + * Rating is computed from value of metric {@link ExampleMetrics#FILENAME_SIZE}. + */ +public class ComputeSizeRating implements MeasureComputer { + + private static final int THRESHOLD = 20; + private static final int RATING_A = 1; + private static final int RATING_B = 2; + + @Override + public MeasureComputerDefinition define(MeasureComputerDefinitionContext def) { + return def.newDefinitionBuilder() + .setInputMetrics(FILENAME_SIZE.key()) + .setOutputMetrics(FILENAME_SIZE_RATING.key()) + .build(); + } + + @Override + public void compute(MeasureComputerContext context) { + Measure size = context.getMeasure(FILENAME_SIZE.key()); + if (size != null) { + // rating values are currently implemented as integers in API + int rating = RATING_A; + if (size.getIntValue() > THRESHOLD) { + rating = RATING_B; + } + context.addMeasure(FILENAME_SIZE_RATING.key(), rating); + } + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ExampleMetrics.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ExampleMetrics.java new file mode 100644 index 00000000..3815347c --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/ExampleMetrics.java @@ -0,0 +1,30 @@ +package org.sonarsource.plugins.example.measures; + +import java.util.List; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.Metrics; + +import static java.util.Arrays.asList; + +public class ExampleMetrics implements Metrics { + + public static final Metric FILENAME_SIZE = new Metric.Builder("filename_size", "Filename Size", Metric.ValueType.INT) + .setDescription("Number of characters of file names") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_GENERAL) + .create(); + + public static final Metric FILENAME_SIZE_RATING = new Metric.Builder("filename_size_rating", "Filename Size Rating", Metric.ValueType.RATING) + .setDescription("Rating based on size of file names") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setDomain(CoreMetrics.DOMAIN_GENERAL) + .create(); + + @Override + public List getMetrics() { + return asList(FILENAME_SIZE, FILENAME_SIZE_RATING); + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/SetSizeOnFilesSensor.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/SetSizeOnFilesSensor.java new file mode 100644 index 00000000..b5f6f030 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/measures/SetSizeOnFilesSensor.java @@ -0,0 +1,34 @@ +package org.sonarsource.plugins.example.measures; + +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; + +import static org.sonarsource.plugins.example.measures.ExampleMetrics.FILENAME_SIZE; + +/** + * Scanner feeds raw measures on files but must not aggregate values to directories and project. + * This class emulates loading of file measures from a 3rd-party analyser. + */ +public class SetSizeOnFilesSensor implements Sensor { + @Override + public void describe(SensorDescriptor descriptor) { + descriptor.name("Compute size of file names"); + } + + @Override + public void execute(SensorContext context) { + FileSystem fs = context.fileSystem(); + // only "main" files, but not "tests" + Iterable files = fs.inputFiles(fs.predicates().hasType(InputFile.Type.MAIN)); + for (InputFile file : files) { + context.newMeasure() + .forMetric(FILENAME_SIZE) + .on(file) + .withValue(file.file().getName().length()) + .save(); + } + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/CreateIssuesOnJavaFilesSensor.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/CreateIssuesOnJavaFilesSensor.java new file mode 100644 index 00000000..86c579ec --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/CreateIssuesOnJavaFilesSensor.java @@ -0,0 +1,52 @@ +package org.sonarsource.plugins.example.rules; + +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; +import org.sonar.api.batch.sensor.issue.NewIssue; +import org.sonar.api.batch.sensor.issue.NewIssueLocation; + +/** + * Generates issues on all java files at line 1. This rule + * must be activated in the Quality profile. + */ +public class CreateIssuesOnJavaFilesSensor implements Sensor { + + private static final double ARBITRARY_GAP = 2.0; + private static final int LINE_1 = 1; + + @Override + public void describe(SensorDescriptor descriptor) { + descriptor.name("Add issues on line 1 of all Java files"); + + // optimisation to disable execution of sensor if project does + // not contain Java files or if the example rule is not activated + // in the Quality profile + descriptor.onlyOnLanguage("java"); + descriptor.createIssuesForRuleRepositories(JavaRulesDefinition.REPOSITORY); + } + + @Override + public void execute(SensorContext context) { + FileSystem fs = context.fileSystem(); + Iterable javaFiles = fs.inputFiles(fs.predicates().hasLanguage("java")); + for (InputFile javaFile : javaFiles) { + // no need to define the severity as it is automatically set according + // to the configured Quality profile + NewIssue newIssue = context.newIssue() + .forRule(JavaRulesDefinition.RULE_ON_LINE_1) + + // gap is used to estimate the remediation cost to fix the debt + .gap(ARBITRARY_GAP); + + NewIssueLocation primaryLocation = newIssue.newLocation() + .on(javaFile) + .at(javaFile.selectLine(LINE_1)) + .message("You can't do anything. This is first line!"); + newIssue.at(primaryLocation); + newIssue.save(); + } + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/FooLintIssuesLoaderSensor.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/FooLintIssuesLoaderSensor.java new file mode 100644 index 00000000..fec7abb2 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/FooLintIssuesLoaderSensor.java @@ -0,0 +1,198 @@ +package org.sonarsource.plugins.example.rules; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import javax.xml.stream.XMLStreamException; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.config.Settings; +import org.sonar.api.issue.Issuable; +import org.sonar.api.issue.Issue; +import org.sonar.api.resources.Project; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +import static java.lang.String.format; + +/** + * The goal of this Sensor is to load the results of an analysis performed by a fictive external tool named: FooLint + * Results are provided as an xml file and are corresponding to the rules defined in 'rules.xml'. + * To be very abstract, these rules are applied on source files made with the fictive language Foo. + */ +public class FooLintIssuesLoaderSensor implements Sensor { + + private static final Logger LOGGER = Loggers.get(FooLintIssuesLoaderSensor.class); + + protected static final String REPORT_PATH_KEY = "sonar.foolint.reportPath"; + + protected final Settings settings; + protected final FileSystem fileSystem; + protected final RuleFinder ruleFinder; + protected final ResourcePerspectives perspectives; + + /** + * Use of IoC to get Settings, FileSystem, RuleFinder and ResourcePerspectives + */ + public FooLintIssuesLoaderSensor(final Settings settings, final FileSystem fileSystem, final RuleFinder ruleFinder, final ResourcePerspectives perspectives) { + this.settings = settings; + this.fileSystem = fileSystem; + this.ruleFinder = ruleFinder; + this.perspectives = perspectives; + } + + @Override + public boolean shouldExecuteOnProject(final Project project) { + return !StringUtils.isEmpty(getReportPath()); + } + + protected String reportPathKey() { + return REPORT_PATH_KEY; + } + + protected String getReportPath() { + String reportPath = settings.getString(reportPathKey()); + if (!StringUtils.isEmpty(reportPath)) { + return reportPath; + } else { + return null; + } + } + + @Override + public void analyse(final Project project, final SensorContext context) { + String reportPath = getReportPath(); + File analysisResultsFile = new File(reportPath); + try { + parseAndSaveResults(analysisResultsFile); + + } catch (XMLStreamException e) { + throw new IllegalStateException("Unable to parse the provided FooLint file", e); + } + } + + protected void parseAndSaveResults(final File file) throws XMLStreamException { + LOGGER.info("(mock) Parsing 'FooLint' Analysis Results"); + FooLintAnalysisResultsParser parser = new FooLintAnalysisResultsParser(); + List errors = parser.parse(file); + for (FooLintError error : errors) { + getResourceAndSaveIssue(error); + } + } + + private void getResourceAndSaveIssue(FooLintError error) { + LOGGER.debug(error.toString()); + + InputFile inputFile = fileSystem.inputFile( + fileSystem.predicates().and( + fileSystem.predicates().hasRelativePath(error.getFilePath()), + fileSystem.predicates().hasType(InputFile.Type.MAIN))); + + LOGGER.debug("inputFile null ? " + (inputFile == null)); + + if (inputFile != null) { + saveIssue(inputFile, error.getLine(), error.getType(), error.getDescription()); + } else { + LOGGER.error("Not able to find a InputFile with " + error.getFilePath()); + } + } + + private boolean saveIssue(InputFile inputFile, int line, String externalRuleKey, String message) { + RuleKey rule = RuleKey.of(FooLintRulesDefinition.getRepositoryKeyForLanguage(inputFile.language()), externalRuleKey); + + Issuable issuable = perspectives.as(Issuable.class, inputFile); + boolean result = false; + if (issuable != null) { + LOGGER.debug("Issuable is not null: %s", issuable.toString()); + Issuable.IssueBuilder issueBuilder = issuable.newIssueBuilder() + .ruleKey(rule) + .message(message); + if (line > 0) { + LOGGER.debug("line is > 0"); + issueBuilder = issueBuilder.line(line); + } + Issue issue = issueBuilder.build(); + LOGGER.debug("issue == null? " + (issue == null)); + try { + result = issuable.addIssue(issue); + LOGGER.debug("after addIssue: result={}", result); + } catch (org.sonar.api.utils.MessageException me) { + LOGGER.error(format("Can't add issue on file %s at line %d.", inputFile.absolutePath(), line), me); + } + + } else { + LOGGER.debug("Can't find an Issuable corresponding to InputFile:" + inputFile.absolutePath()); + } + return result; + } + + @Override + public String toString() { + return "FooLintIssuesLoaderSensor"; + } + + private class FooLintError { + + private final String type; + private final String description; + private final String filePath; + private final int line; + + public FooLintError(final String type, final String description, final String filePath, final int line) { + this.type = type; + this.description = description; + this.filePath = filePath; + this.line = line; + } + + public String getType() { + return type; + } + + public String getDescription() { + return description; + } + + public String getFilePath() { + return filePath; + } + + public int getLine() { + return line; + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(type); + s.append("|"); + s.append(description); + s.append("|"); + s.append(filePath); + s.append("("); + s.append(line); + s.append(")"); + return s.toString(); + } + } + + private class FooLintAnalysisResultsParser { + + public List parse(final File file) throws XMLStreamException { + LOGGER.info("Parsing file {}", file.getAbsolutePath()); + + // as the goal of this example is not to demonstrate how to parse an xml file we return an hard coded list of FooError + + FooLintError fooError1 = new FooLintError("ExampleRule1", "More precise description of the error", "src/MyClass.foo", 5); + FooLintError fooError2 = new FooLintError("ExampleRule2", "More precise description of the error", "src/MyClass.foo", 9); + + return Arrays.asList(fooError1, fooError2); + } + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/FooLintRulesDefinition.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/FooLintRulesDefinition.java new file mode 100644 index 00000000..a6f39279 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/FooLintRulesDefinition.java @@ -0,0 +1,45 @@ +package org.sonarsource.plugins.example.rules; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.api.server.rule.RulesDefinitionXmlLoader; +import org.sonarsource.plugins.example.languages.FooLanguage; + +public final class FooLintRulesDefinition implements RulesDefinition { + + protected static final String KEY = "foolint"; + protected static final String NAME = "FooLint"; + + protected String rulesDefinitionFilePath() { + return "/example/foolint-rules.xml"; + } + + private void defineRulesForLanguage(Context context, String repositoryKey, String repositoryName, String languageKey) { + NewRepository repository = context.createRepository(repositoryKey, languageKey).setName(repositoryName); + + InputStream rulesXml = this.getClass().getResourceAsStream(rulesDefinitionFilePath()); + if (rulesXml != null) { + RulesDefinitionXmlLoader rulesLoader = new RulesDefinitionXmlLoader(); + rulesLoader.load(repository, rulesXml, StandardCharsets.UTF_8.name()); + } + + repository.done(); + } + + @Override + public void define(Context context) { + String repositoryKey = FooLintRulesDefinition.getRepositoryKeyForLanguage(FooLanguage.KEY); + String repositoryName = FooLintRulesDefinition.getRepositoryNameForLanguage(FooLanguage.KEY); + defineRulesForLanguage(context, repositoryKey, repositoryName, FooLanguage.KEY); + } + + public static String getRepositoryKeyForLanguage(String languageKey) { + return languageKey.toLowerCase() + "-" + KEY; + } + + public static String getRepositoryNameForLanguage(String languageKey) { + return languageKey.toUpperCase() + " " + NAME; + } + +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/JavaRulesDefinition.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/JavaRulesDefinition.java new file mode 100644 index 00000000..952968a9 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/rules/JavaRulesDefinition.java @@ -0,0 +1,36 @@ +package org.sonarsource.plugins.example.rules; + +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; +import org.sonar.api.server.rule.RulesDefinition; + +public class JavaRulesDefinition implements RulesDefinition { + + public static final String REPOSITORY = "java-example"; + public static final String JAVA_LANGUAGE = "java"; + public static final RuleKey RULE_ON_LINE_1 = RuleKey.of(REPOSITORY, "line1"); + + @Override + public void define(Context context) { + NewRepository repository = context.createRepository(REPOSITORY, JAVA_LANGUAGE).setName("My Custom Java Analyzer"); + + NewRule x1Rule = repository.createRule(RULE_ON_LINE_1.rule()) + .setName("Stupid rule") + .setHtmlDescription("Generates an issue on every line 1 of Java files") + + // optional tags + .setTags("style", "stupid") + + // optional status. Default value is READY. + .setStatus(RuleStatus.BETA) + + // default severity when the rule is activated on a Quality profile. Default value is MAJOR. + .setSeverity(Severity.MINOR); + + x1Rule.setDebtRemediationFunction(x1Rule.debtRemediationFunctions().linearWithOffset("1h", "30min")); + + // don't forget to call done() to finalize the definition + repository.done(); + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/settings/ExampleProperties.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/settings/ExampleProperties.java new file mode 100644 index 00000000..0bc6ed09 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/settings/ExampleProperties.java @@ -0,0 +1,27 @@ +package org.sonarsource.plugins.example.settings; + +import java.util.List; +import org.sonar.api.config.PropertyDefinition; + +import static java.util.Arrays.asList; + +public class ExampleProperties { + + public static final String HELLO_KEY = "sonar.example.hello"; + public static final String CATEGORY = "Example"; + + private ExampleProperties() { + // only statics + } + + public static List definitions() { + return asList( + PropertyDefinition.builder(HELLO_KEY) + .name("Hello") + .description("Say Hello") + .defaultValue(String.valueOf(false)) + .category(CATEGORY) + .build() + ); + } +} diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/settings/SayHelloFromScanner.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/settings/SayHelloFromScanner.java new file mode 100644 index 00000000..a05046dc --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/settings/SayHelloFromScanner.java @@ -0,0 +1,21 @@ +package org.sonarsource.plugins.example.settings; + +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; +import org.sonar.api.utils.log.Loggers; + +public class SayHelloFromScanner implements Sensor { + @Override + public void describe(SensorDescriptor descriptor) { + descriptor.name(getClass().getName()); + } + + @Override + public void execute(SensorContext context) { + if (context.settings().getBoolean(ExampleProperties.HELLO_KEY)) { + // print log only if property is set to true + Loggers.get(getClass()).info("Hello world!"); + } + } +} diff --git a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ui/ExampleFooter.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/web/ExampleFooter.java similarity index 76% rename from plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ui/ExampleFooter.java rename to plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/web/ExampleFooter.java index 1ee91b64..7083e5ea 100644 --- a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ui/ExampleFooter.java +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/web/ExampleFooter.java @@ -1,8 +1,10 @@ -package com.mycompany.sonar.reference.ui; +package org.sonarsource.plugins.example.web; import org.sonar.api.web.Footer; public final class ExampleFooter implements Footer { + + @Override public String getHtml() { return "

Footer Example - This is static HTML

"; } diff --git a/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/web/ExampleWidget.java b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/web/ExampleWidget.java new file mode 100644 index 00000000..c4c979d8 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/java/org/sonarsource/plugins/example/web/ExampleWidget.java @@ -0,0 +1,48 @@ +package org.sonarsource.plugins.example.web; + +import org.sonar.api.web.AbstractRubyTemplate; +import org.sonar.api.web.Description; +import org.sonar.api.web.RubyRailsWidget; +import org.sonar.api.web.UserRole; +import org.sonar.api.web.WidgetCategory; +import org.sonar.api.web.WidgetProperties; +import org.sonar.api.web.WidgetProperty; +import org.sonar.api.web.WidgetPropertyType; + +@UserRole(UserRole.USER) +@Description("Show how to use Ruby Widget API") +@WidgetCategory("Sample") +@WidgetProperties({ + @WidgetProperty(key = "param1", + description = "This is a mandatory parameter", + optional = false + ), + @WidgetProperty(key = "max", + description = "max threshold", + type = WidgetPropertyType.INTEGER, + defaultValue = "80" + ), + @WidgetProperty(key = "param2", + description = "This is an optional parameter" + ), + @WidgetProperty(key = "floatprop", + description = "test description" + ) +}) +public class ExampleWidget extends AbstractRubyTemplate implements RubyRailsWidget { + + @Override + public String getId() { + return "example"; + } + + @Override + public String getTitle() { + return "Example"; + } + + @Override + protected String getTemplatePath() { + return "/example/example_widget.html.erb"; + } +} diff --git a/plugins/sonar-reference-plugin/src/main/resources/example/example_widget.html.erb b/plugins/sonar-example-plugin/src/main/resources/example/example_widget.html.erb similarity index 56% rename from plugins/sonar-reference-plugin/src/main/resources/example/example_widget.html.erb rename to plugins/sonar-example-plugin/src/main/resources/example/example_widget.html.erb index b6c4bcc6..d8f58249 100644 --- a/plugins/sonar-reference-plugin/src/main/resources/example/example_widget.html.erb +++ b/plugins/sonar-example-plugin/src/main/resources/example/example_widget.html.erb @@ -3,29 +3,18 @@

- <%= format_measure('random') -%> <%= trend_icon(measure('random')) %> + <%= format_measure('random') -%>

-

<%= format_measure('message') -%>

-

<%= format_measure('ncloc', :suffix => ' lines', :url => url_for_drilldown('ncloc')) -%>

+

<%= message('example.help') -%>

-

- <%= message('example.jdbc_login') -%> : <%= configuration('sonar.jdbc.username') -%>
- <%= message('example.plugin_property') -%> : <%= configuration('sonar.example.myproperty') -%>
-

- -

- <%= message('example.eastwood_image') -%> :
- <%= gchart('cht=bhs&chco=FF0000,00FF00,0000FF&chs=200x125&chd=s:FOE,THE,Bar&chxt=x,y&chxl=1:|Dec|Nov|Oct|0:||20K||60K||100K|') -%> -

-

<%= message('example.widget_properties') -%>

diff --git a/plugins/sonar-example-plugin/src/main/resources/example/foolint-rules.xml b/plugins/sonar-example-plugin/src/main/resources/example/foolint-rules.xml new file mode 100644 index 00000000..1d3dbf09 --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/resources/example/foolint-rules.xml @@ -0,0 +1,37 @@ + + + ExampleRule1 + Example Rule 1 + ExampleRule1 + This is an example of rule defined thru the XML. + + BLOCKER + SINGLE + READY + example + bug + + + ExampleRule2 + Example Rule 2 + ExampleRule2 + This is a other example of rule defined thru the XML. + + MAJOR + SINGLE + BETA + example + convention + + + ExampleRule3 + Example Rule 3 + ExampleRule3 + This is a other example of rule defined thru the XML. + + CRITICAL + SINGLE + DEPRECATED + example + + diff --git a/plugins/sonar-reference-plugin/src/main/resources/org/sonar/l10n/reference.properties b/plugins/sonar-example-plugin/src/main/resources/org/sonar/l10n/example/example.properties similarity index 56% rename from plugins/sonar-reference-plugin/src/main/resources/org/sonar/l10n/reference.properties rename to plugins/sonar-example-plugin/src/main/resources/org/sonar/l10n/example/example.properties index ff1898c6..728b2f9a 100644 --- a/plugins/sonar-reference-plugin/src/main/resources/org/sonar/l10n/reference.properties +++ b/plugins/sonar-example-plugin/src/main/resources/org/sonar/l10n/example/example.properties @@ -2,7 +2,5 @@ # This bundle must be stored in the package org.sonar.l10n and its name must be _.properties # example.help=Help -example.jdbc_login=JDBC Login example.plugin_property=My Plugin Property -example.eastwood_image=Image generated by JFreeChart Eastwood -example.widget_properties=Widget properties \ No newline at end of file +example.widget_properties=Widget properties diff --git a/plugins/sonar-example-plugin/src/main/resources/org/sonar/l10n/example/example_fr.properties b/plugins/sonar-example-plugin/src/main/resources/org/sonar/l10n/example/example_fr.properties new file mode 100644 index 00000000..b8a5efcf --- /dev/null +++ b/plugins/sonar-example-plugin/src/main/resources/org/sonar/l10n/example/example_fr.properties @@ -0,0 +1,3 @@ +example.help=Aide +example.plugin_property=Ma propriété +example.widget_properties=Propriétés de ce widget diff --git a/plugins/sonar-gwt-plugin/pom.xml b/plugins/sonar-gwt-plugin/pom.xml deleted file mode 100644 index 7346ae04..00000000 --- a/plugins/sonar-gwt-plugin/pom.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - 4.0.0 - org.codehaus.sonar.examples - sonar-gwt-plugin - sonar-plugin - 0.1-SNAPSHOT - Sonar Examples :: GWT Plugin - - - 2.10 - - - - - org.codehaus.sonar - sonar-plugin-api - ${sonar.buildVersion} - provided - - - org.codehaus.sonar - sonar-gwt-api - ${sonar.buildVersion} - provided - - - com.google.gwt - gwt-user - 2.0.3 - provided - - - com.google.gwt - gwt-incubator - 2.0.1 - provided - - - - - org.codehaus.sonar - sonar-testing-harness - ${sonar.buildVersion} - test - - - junit - junit - 4.8.2 - test - - - - - - - org.codehaus.sonar - sonar-packaging-maven-plugin - 1.1 - true - - com.mycompany.sonar.gwt.GwtPlugin - - - - org.codehaus.mojo - gwt-maven-plugin - 1.2 - - - - - com.mycompany.sonar.gwt.viewer.SampleViewer - com.mycompany.sonar.gwt.page.SamplePage - - ${project.build.directory}/classes - -Xmx512m - - - compile - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - 1.5 - 1.5 - UTF-8 - - - - - diff --git a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/GwtPlugin.java b/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/GwtPlugin.java deleted file mode 100644 index 40d78ca7..00000000 --- a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/GwtPlugin.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.mycompany.sonar.gwt; - -import com.mycompany.sonar.gwt.page.SamplePage; -import com.mycompany.sonar.gwt.viewer.SampleViewer; -import org.sonar.api.SonarPlugin; - -import java.util.Arrays; -import java.util.List; - -public final class GwtPlugin extends SonarPlugin { - - public List getExtensions() { - return Arrays.asList(SampleViewer.class, SamplePage.class); - } - - public String toString() { - return getKey(); - } -} \ No newline at end of file diff --git a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/SamplePage.java b/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/SamplePage.java deleted file mode 100644 index dc2dd743..00000000 --- a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/SamplePage.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mycompany.sonar.gwt.page; - -import org.sonar.api.web.GwtPage; -import org.sonar.api.web.NavigationSection; -import org.sonar.api.web.UserRole; - -@NavigationSection(NavigationSection.RESOURCE) -@UserRole(UserRole.USER) -public class SamplePage extends GwtPage { - - public String getGwtId() { - return "com.mycompany.sonar.gwt.page.SamplePage"; - } - - public String getTitle() { - return "Sample"; - } -} diff --git a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/client/I18nConstants.java b/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/client/I18nConstants.java deleted file mode 100644 index 4dde01eb..00000000 --- a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/client/I18nConstants.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.mycompany.sonar.gwt.page.client; - -import com.google.gwt.core.client.GWT; - -public interface I18nConstants extends com.google.gwt.i18n.client.Constants { - - static I18nConstants INSTANCE = GWT.create(I18nConstants.class); - - @DefaultStringValue("This is a sample") - String sample(); -} diff --git a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/client/SamplePagePanel.java b/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/client/SamplePagePanel.java deleted file mode 100644 index c0d16edb..00000000 --- a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/page/client/SamplePagePanel.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mycompany.sonar.gwt.page.client; - -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.google.gwt.user.client.ui.Widget; -import org.sonar.gwt.ui.Page; -import org.sonar.wsclient.services.Resource; - -public class SamplePagePanel extends Page { - - @Override - protected Widget doOnResourceLoad(Resource resource) { - VerticalPanel panel = new VerticalPanel(); - panel.add(new Label(resource.getName(true))); - panel.add(new Label(I18nConstants.INSTANCE.sample())); - return panel; - } -} diff --git a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/viewer/SampleViewer.java b/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/viewer/SampleViewer.java deleted file mode 100644 index 53ca2a45..00000000 --- a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/viewer/SampleViewer.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.mycompany.sonar.gwt.viewer; - -import org.sonar.api.web.GwtPage; -import org.sonar.api.web.NavigationSection; -import org.sonar.api.web.UserRole; - -@NavigationSection(NavigationSection.RESOURCE_TAB) -@UserRole(UserRole.USER) -public class SampleViewer extends GwtPage { - public String getTitle() { - return "Sample"; - } - - public String getGwtId() { - return "com.mycompany.sonar.gwt.viewer.SampleViewer"; - } -} \ No newline at end of file diff --git a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/viewer/client/SampleViewerPanel.java b/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/viewer/client/SampleViewerPanel.java deleted file mode 100644 index 823dae78..00000000 --- a/plugins/sonar-gwt-plugin/src/main/java/com/mycompany/sonar/gwt/viewer/client/SampleViewerPanel.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.mycompany.sonar.gwt.viewer.client; - -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; -import org.sonar.gwt.ui.Page; -import org.sonar.wsclient.gwt.AbstractCallback; -import org.sonar.wsclient.gwt.Sonar; -import org.sonar.wsclient.services.Measure; -import org.sonar.wsclient.services.Resource; -import org.sonar.wsclient.services.ResourceQuery; - -public class SampleViewerPanel extends Page { - - private Label label; - - @Override - protected Widget doOnResourceLoad(Resource resource) { - label = new Label("Loading value"); - loadMeasureFromServer(resource); - return label; - } - - // Ajax call to web service - private void loadMeasureFromServer(Resource resource) { - ResourceQuery query = ResourceQuery.createForResource(resource, "random"); - Sonar.getInstance().find(query, new AbstractCallback() { - @Override - protected void doOnResponse(Resource result) { - Measure measure = result.getMeasure("random"); - if (measure==null || measure.getValue()==null) { - label.setText("No random value"); - } else { - label.setText("Random value inserted during analysis: " + measure.getValue()); - } - } - }); - } -} \ No newline at end of file diff --git a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/SamplePage.gwt.xml b/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/SamplePage.gwt.xml deleted file mode 100644 index 8f95c2e2..00000000 --- a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/SamplePage.gwt.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/client/I18nConstants_fr.properties b/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/client/I18nConstants_fr.properties deleted file mode 100644 index aa92d17b..00000000 --- a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/client/I18nConstants_fr.properties +++ /dev/null @@ -1,2 +0,0 @@ -# This file must use UTF-8 encoding -sample=Ceci est un exemple \ No newline at end of file diff --git a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/public/test.html b/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/public/test.html deleted file mode 100644 index 04371e3a..00000000 --- a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/page/public/test.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - GWT Smaple - - - - - - - - - - - - - - -
-
- - - - \ No newline at end of file diff --git a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/viewer/SampleViewer.gwt.xml b/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/viewer/SampleViewer.gwt.xml deleted file mode 100644 index af900e8d..00000000 --- a/plugins/sonar-gwt-plugin/src/main/resources/com/mycompany/sonar/gwt/viewer/SampleViewer.gwt.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/plugins/sonar-pmd-extension-plugin/pom.xml b/plugins/sonar-pmd-extension-plugin/pom.xml deleted file mode 100644 index ddedc330..00000000 --- a/plugins/sonar-pmd-extension-plugin/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - 4.0.0 - org.codehaus.sonar.examples - sonar-pmd-extension-plugin - sonar-plugin - 0.1-SNAPSHOT - Sonar Examples :: PMD Extension Plugin - - - - org.codehaus.sonar - sonar-plugin-api - 2.10 - provided - - - pmd - pmd - 4.2.5 - provided - - - - - - - org.codehaus.sonar - sonar-packaging-maven-plugin - 1.1 - true - - org.sonar.examples.pmd.PmdExtensionPlugin - - - pmd - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.5 - 1.5 - - - - - \ No newline at end of file diff --git a/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/MaximumMethodsCountCheck.java b/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/MaximumMethodsCountCheck.java deleted file mode 100644 index 5f0bc10a..00000000 --- a/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/MaximumMethodsCountCheck.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.sonar.examples.pmd; - -import net.sourceforge.pmd.AbstractRule; -import net.sourceforge.pmd.ast.ASTClassOrInterfaceBody; -import net.sourceforge.pmd.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.properties.IntegerProperty; - -import java.util.List; - -public class MaximumMethodsCountCheck extends AbstractRule { - - private static final IntegerProperty propertyDescriptor = new IntegerProperty( - "maxAuthorisedMethodsCount", "Maximum number of methods authorised", 2, 1.0f); - - public Object visit(ASTClassOrInterfaceBody node, Object data) { - List methods = node.findChildrenOfType(ASTMethodDeclaration.class); - if (methods.size() > getIntProperty(propertyDescriptor)) { - addViolation(data, node); - } - return super.visit(node, data); - } - -} diff --git a/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/PmdExtensionPlugin.java b/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/PmdExtensionPlugin.java deleted file mode 100644 index 4af72c5f..00000000 --- a/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/PmdExtensionPlugin.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sonar.examples.pmd; - -import org.sonar.api.SonarPlugin; - -import java.util.Arrays; -import java.util.List; - -public class PmdExtensionPlugin extends SonarPlugin { - - public List getExtensions() { - return Arrays.asList(PmdExtensionRepository.class); - } - -} diff --git a/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/PmdExtensionRepository.java b/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/PmdExtensionRepository.java deleted file mode 100644 index 47fc9a65..00000000 --- a/plugins/sonar-pmd-extension-plugin/src/main/java/org/sonar/examples/pmd/PmdExtensionRepository.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.sonar.examples.pmd; - -import org.apache.commons.io.IOUtils; -import org.sonar.api.resources.Java; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleRepository; -import org.sonar.api.rules.XMLRuleParser; - -import java.io.InputStream; -import java.util.List; - -public class PmdExtensionRepository extends RuleRepository { - - // Must be the same than the PMD plugin - private static final String REPOSITORY_KEY = "pmd"; - private XMLRuleParser ruleParser; - - public PmdExtensionRepository(XMLRuleParser ruleParser) { - super(REPOSITORY_KEY, Java.KEY); - this.ruleParser = ruleParser; - } - - @Override - public List createRules() { - // In this example, new rules are declared in a XML file - InputStream input = getClass().getResourceAsStream("/org/sonar/examples/pmd/extensions.xml"); - try { - return ruleParser.parse(input); - - } finally { - IOUtils.closeQuietly(input); - } - } - -} diff --git a/plugins/sonar-pmd-extension-plugin/src/main/resources/org/sonar/examples/pmd/extensions.xml b/plugins/sonar-pmd-extension-plugin/src/main/resources/org/sonar/examples/pmd/extensions.xml deleted file mode 100644 index 808974b0..00000000 --- a/plugins/sonar-pmd-extension-plugin/src/main/resources/org/sonar/examples/pmd/extensions.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - MaximumMethodsCountCheck - Maximum Methods Count Check - Maximum number of methods authorised - - - com/mycompany/sonar/pmd/rulesets.xml/MaximumMethodsCountCheck - - - - - - - - maxAuthorisedMethodsCount - Maximum number of methods authorised - - - 2 - - - - - - - AvoidIfWithoutBrace - Avoid if without using brace - com/mycompany/sonar/pmd/rulesets.xml/AvoidIfWithoutBrace - CRITICAL - - - - - - PreventUseOfEmptyClass - MAJOR - - - MINOR - - xpath - - //VariableDeclarator[../Type/ReferenceType/ClassOrInterfaceType[@Image='EmptyClass']] - - - message - - Prevent use of EmptyClass class - - - \ No newline at end of file diff --git a/plugins/sonar-pmd-extension-plugin/src/main/resources/org/sonar/examples/pmd/rulesets.xml b/plugins/sonar-pmd-extension-plugin/src/main/resources/org/sonar/examples/pmd/rulesets.xml deleted file mode 100644 index 6922cd62..00000000 --- a/plugins/sonar-pmd-extension-plugin/src/main/resources/org/sonar/examples/pmd/rulesets.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - Avoid too many methods - - 3 - - - - - - - - - - - Avoid if without using brace - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ExampleMetrics.java b/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ExampleMetrics.java deleted file mode 100644 index c6f19d38..00000000 --- a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ExampleMetrics.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.mycompany.sonar.reference; - -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.Metrics; - -import java.util.Arrays; -import java.util.List; - -public final class ExampleMetrics implements Metrics { - - public static final Metric MESSAGE = new Metric.Builder("message_key", "Message", Metric.ValueType.STRING) - .setDescription("This is a metric to store a well known message") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_GENERAL) - .create(); - - public static final Metric RANDOM = new Metric.Builder("random", "Random", Metric.ValueType.FLOAT) - .setDescription("Random value") - .setDirection(Metric.DIRECTION_BETTER) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_GENERAL) - .create(); - - // getMetrics() method is defined in the Metrics interface and is used by - // Sonar to retrieve the list of new metrics - public List getMetrics() { - return Arrays.asList(MESSAGE, RANDOM); - } -} diff --git a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ExamplePlugin.java b/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ExamplePlugin.java deleted file mode 100644 index 7f2792e3..00000000 --- a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ExamplePlugin.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.mycompany.sonar.reference; - -import com.mycompany.sonar.reference.batch.RandomDecorator; -import com.mycompany.sonar.reference.batch.ExampleSensor; -import com.mycompany.sonar.reference.ui.ExampleFooter; -import com.mycompany.sonar.reference.ui.ExampleRubyWidget; -import org.sonar.api.Properties; -import org.sonar.api.Property; -import org.sonar.api.SonarPlugin; - -import java.util.Arrays; -import java.util.List; - -/** - * This class is the entry point for all extensions - */ -@Properties({ - @Property( - key = ExamplePlugin.MY_PROPERTY, - name = "Plugin Property", - description = "A property for the plugin")}) -public final class ExamplePlugin extends SonarPlugin { - - public static final String MY_PROPERTY = "sonar.example.myproperty"; - - // This is where you're going to declare all your Sonar extensions - public List getExtensions() { - return Arrays.asList( - // Definitions - ExampleMetrics.class, - - // Batch - ExampleSensor.class, RandomDecorator.class, - - // UI - ExampleFooter.class, ExampleRubyWidget.class); - } -} \ No newline at end of file diff --git a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/batch/ExampleSensor.java b/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/batch/ExampleSensor.java deleted file mode 100644 index a8a2ec08..00000000 --- a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/batch/ExampleSensor.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.mycompany.sonar.reference.batch; - -import com.mycompany.sonar.reference.ExampleMetrics; -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.measures.Measure; -import org.sonar.api.resources.Project; - -public class ExampleSensor implements Sensor { - - public boolean shouldExecuteOnProject(Project project) { - // This sensor is executed on any type of projects - return true; - } - - public void analyse(Project project, SensorContext sensorContext) { - Measure measure = new Measure(ExampleMetrics.MESSAGE, "Hello World!"); - sensorContext.saveMeasure(measure); - } -} diff --git a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/batch/RandomDecorator.java b/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/batch/RandomDecorator.java deleted file mode 100644 index 558e6412..00000000 --- a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/batch/RandomDecorator.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.mycompany.sonar.reference.batch; - -import com.mycompany.sonar.reference.ExampleMetrics; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.math.RandomUtils; -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.resources.Java; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.Scopes; - -public class RandomDecorator implements Decorator { - - public boolean shouldExecuteOnProject(Project project) { - // Execute only on Java projects - return StringUtils.equals(project.getLanguageKey(), Java.KEY); - } - - public void decorate(Resource resource, DecoratorContext context) { - // This method is executed on the whole tree of resources. - // Bottom-up navigation : Java methods -> Java classes -> files -> packages -> modules -> project - if (Scopes.isBlockUnit(resource)) { - // Sonar API includes many libraries like commons-lang and google-collections - double value = RandomUtils.nextDouble(); - - // Add a measure to the current Java method - context.saveMeasure(ExampleMetrics.RANDOM, value); - - } else { - // we sum random values on resources different than method - context.saveMeasure(ExampleMetrics.RANDOM, MeasureUtils.sum(true, context.getChildrenMeasures(ExampleMetrics.RANDOM))); - } - } -} diff --git a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ui/ExampleRubyWidget.java b/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ui/ExampleRubyWidget.java deleted file mode 100644 index c53144ab..00000000 --- a/plugins/sonar-reference-plugin/src/main/java/com/mycompany/sonar/reference/ui/ExampleRubyWidget.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mycompany.sonar.reference.ui; - -import org.sonar.api.web.*; - -@UserRole(UserRole.USER) -@Description("Show how to use Ruby Widget API") -@WidgetCategory("Sample") -@WidgetProperties({ - @WidgetProperty(key = "param1", - description = "This is a mandatory parameter", - optional = false - ), - @WidgetProperty(key = "max", - description = "max threshold", - type = WidgetPropertyType.INTEGER, - defaultValue = "80" - ), - @WidgetProperty(key = "param2", - description = "This is an optional parameter" - ), - @WidgetProperty(key = "floatprop", - description = "test description" - ) -}) -public class ExampleRubyWidget extends AbstractRubyTemplate implements RubyRailsWidget { - - public String getId() { - return "sample"; - } - - public String getTitle() { - return "Sample"; - } - - @Override - protected String getTemplatePath() { - return "/example/example_widget.html.erb"; - } -} \ No newline at end of file diff --git a/plugins/sonar-reference-plugin/src/main/resources/org/sonar/l10n/reference_fr.properties b/plugins/sonar-reference-plugin/src/main/resources/org/sonar/l10n/reference_fr.properties deleted file mode 100644 index e38a7808..00000000 --- a/plugins/sonar-reference-plugin/src/main/resources/org/sonar/l10n/reference_fr.properties +++ /dev/null @@ -1,5 +0,0 @@ -example.help=Aide -example.jdbc_login=Compte JDBC -example.plugin_property=Ma propriété -example.eastwood_image=Image générée par JFreeChart Eastwood -example.widget_properties=Propriétés de ce widget \ No newline at end of file diff --git a/plugins/tutorial/java-custom-rules-template/.gitignore b/plugins/tutorial/java-custom-rules-template/.gitignore new file mode 100644 index 00000000..3c6daa09 --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/.gitignore @@ -0,0 +1,31 @@ +# ---- Maven +target/ +dependency-reduced-pom.xml + +# ---- IntelliJ IDEA +*.iws +*.iml +*.ipr +.idea/ + +# ---- Eclipse +.classpath +.project +.settings + +# ---- Mac OS X +.DS_Store? +Icon? +# Thumbnails +._* +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# ---- Windows +# Windows image file caches +Thumbs.db +# Folder config file +Desktop.ini + +.java-version diff --git a/plugins/tutorial/java-custom-rules-template/completed/1_MyFirstCustomCheck.zip b/plugins/tutorial/java-custom-rules-template/completed/1_MyFirstCustomCheck.zip new file mode 100644 index 00000000..17fa3814 Binary files /dev/null and b/plugins/tutorial/java-custom-rules-template/completed/1_MyFirstCustomCheck.zip differ diff --git a/plugins/tutorial/java-custom-rules-template/pom.xml b/plugins/tutorial/java-custom-rules-template/pom.xml new file mode 100644 index 00000000..1491e0f5 --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/pom.xml @@ -0,0 +1,136 @@ + + + 4.0.0 + + org.sonar.samples + java-custom-rules-template + 1.0-SNAPSHOT + sonar-plugin + + + 5.1 + 7.15.0.30507 + + + Java Custom Rules - Template + Empty template for custom rules + + + + org.codehaus.sonar + sonar-plugin-api + ${sonar.plugin.api.version} + provided + + + + org.sonarsource.java + sonar-java-plugin + sonar-plugin + ${java.plugin.version} + provided + + + + org.sonarsource.java + java-frontend + ${java.plugin.version} + + + + org.sonarsource.sslr-squid-bridge + sslr-squid-bridge + 2.7.0.377 + + + org.codehaus.sonar.sslr + sslr-core + + + + + + org.sonarsource.java + java-checks-testkit + ${java.plugin.version} + test + + + + org.codehaus.sonar.sslr + sslr-testing-harness + 1.19.2 + test + + + junit + junit + 4.11 + test + + + org.easytesting + fest-assert + 1.4 + test + + + ch.qos.logback + logback-classic + 0.9.30 + test + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + true + + org.sonar.template.java.JavaCustomRulesPlugin + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesCheckRegistrar.java b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesCheckRegistrar.java new file mode 100644 index 00000000..8c5d018a --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesCheckRegistrar.java @@ -0,0 +1,21 @@ +package org.sonar.template.java; + +import org.sonar.plugins.java.api.CheckRegistrar; + +/** + * Provide the "checks" (implementations of rules) classes that are going to be executed during + * source code analysis. + * + * This class is a batch extension by implementing the {@link org.sonar.plugins.java.api.CheckRegistrar} interface. + */ +public class JavaCustomRulesCheckRegistrar implements CheckRegistrar { + + /** + * Register the classes that will be used to instantiate checks during analysis. + */ + @Override + public void register(RegistrarContext registrarContext) { + // Call to registerClassesForRepository to associate the classes with the correct repository key + registrarContext.registerClassesForRepository(JavaCustomRulesDefinition.REPOSITORY_KEY, JavaCustomRulesList.getJavaChecks(), JavaCustomRulesList.getJavaTestChecks()); + } +} diff --git a/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesDefinition.java b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesDefinition.java new file mode 100644 index 00000000..da18ff78 --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesDefinition.java @@ -0,0 +1,29 @@ +package org.sonar.template.java; + +import com.google.common.collect.Iterables; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.api.server.rule.RulesDefinitionAnnotationLoader; +import org.sonar.plugins.java.Java; + +import java.util.List; + +/** + * Declare rule metadata in server repository of rules. + * That allows to list the rules in the page "Rules". + */ +public class JavaCustomRulesDefinition implements RulesDefinition { + + public static final String REPOSITORY_KEY = "java-custom-rules-template"; + + @Override + public void define(Context context) { + NewRepository repository = context.createRepository(REPOSITORY_KEY, Java.KEY); + repository.setName("Java Custom Rules - Template"); + + List checks = JavaCustomRulesList.getChecks(); + new RulesDefinitionAnnotationLoader().load(repository, Iterables.toArray(checks, Class.class)); + repository.done(); + } + +} diff --git a/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesList.java b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesList.java new file mode 100644 index 00000000..2dce6547 --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesList.java @@ -0,0 +1,29 @@ +package org.sonar.template.java; + +import com.google.common.collect.ImmutableList; + +import org.sonar.plugins.java.api.JavaCheck; + +import java.util.List; + +public final class JavaCustomRulesList { + + private JavaCustomRulesList() { + } + + public static List getChecks() { + return ImmutableList.builder().addAll(getJavaChecks()).addAll(getJavaTestChecks()).build(); + } + + public static List> getJavaChecks() { + return ImmutableList.>builder() + // add HERE rules targeting source files + .build(); + } + + public static List> getJavaTestChecks() { + return ImmutableList.>builder() + // add HERE rules targeting test files + .build(); + } +} diff --git a/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesPlugin.java b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesPlugin.java new file mode 100644 index 00000000..ca0d9e5a --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/JavaCustomRulesPlugin.java @@ -0,0 +1,22 @@ +package org.sonar.template.java; + +import org.sonar.api.SonarPlugin; + +import java.util.Arrays; +import java.util.List; + +/** + * Entry point of plugin + */ +public class JavaCustomRulesPlugin extends SonarPlugin { + + @Override + public List getExtensions() { + return Arrays.asList( + // server extensions -> objects are instantiated during server startup + JavaCustomRulesDefinition.class, + + // batch extensions -> objects are instantiated during code analysis + JavaCustomRulesCheckRegistrar.class); + } +} diff --git a/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/checks/package-info.java b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/checks/package-info.java new file mode 100644 index 00000000..9a01ae4b --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/src/main/java/org/sonar/template/java/checks/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +package org.sonar.template.java.checks; + +/** + * This package contains the custom rules + */ +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/plugins/tutorial/java-custom-rules-template/src/test/files/testFiles.txt b/plugins/tutorial/java-custom-rules-template/src/test/files/testFiles.txt new file mode 100644 index 00000000..f3c26f4d --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/src/test/files/testFiles.txt @@ -0,0 +1 @@ +Place your test files in this folder \ No newline at end of file diff --git a/plugins/tutorial/java-custom-rules-template/src/test/java/org/sonar/template/java/JavaCustomRulesDefinitionTest.java b/plugins/tutorial/java-custom-rules-template/src/test/java/org/sonar/template/java/JavaCustomRulesDefinitionTest.java new file mode 100644 index 00000000..09682cad --- /dev/null +++ b/plugins/tutorial/java-custom-rules-template/src/test/java/org/sonar/template/java/JavaCustomRulesDefinitionTest.java @@ -0,0 +1,22 @@ +package org.sonar.template.java; + +import org.junit.Test; +import org.sonar.api.server.rule.RulesDefinition; + +import static org.fest.assertions.Assertions.assertThat; + +public class JavaCustomRulesDefinitionTest { + + @Test + public void registration_test() { + JavaCustomRulesDefinition definition = new JavaCustomRulesDefinition(); + RulesDefinition.Context context = new RulesDefinition.Context(); + definition.define(context); + RulesDefinition.Repository repository = context.repository("java-custom-rules-template"); + + assertThat(repository.key()).isEqualTo("java-custom-rules-template"); + assertThat(repository.name()).isEqualTo("Java Custom Rules - Template"); + assertThat(repository.language()).isEqualTo("java"); + assertThat(repository.rules()).hasSize(JavaCustomRulesList.getChecks().size()); + } +} diff --git a/projects/README.md b/projects/README.md deleted file mode 100644 index d79d0756..00000000 --- a/projects/README.md +++ /dev/null @@ -1 +0,0 @@ -TO DO diff --git a/projects/ant-modules/README.md b/projects/ant-modules/README.md deleted file mode 100644 index fe0dc316..00000000 --- a/projects/ant-modules/README.md +++ /dev/null @@ -1 +0,0 @@ -This example demonstrates how to analyse project with [Ant](http://ant.apache.org/). diff --git a/projects/ant-modules/build.xml b/projects/ant-modules/build.xml deleted file mode 100644 index 93d5788c..00000000 --- a/projects/ant-modules/build.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - Root Project - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/c/README.md b/projects/c/README.md deleted file mode 100644 index be1d05f1..00000000 --- a/projects/c/README.md +++ /dev/null @@ -1,8 +0,0 @@ -This example demonstrates how to analyse C project with Sonar Runner. - -Prerequisites -============= - -* Sonar 2.6 or higher -* Sonar C Plugin -* Sonar Runner 1.1 or higher diff --git a/projects/c/sonar-project.properties b/projects/c/sonar-project.properties deleted file mode 100644 index c4baba1a..00000000 --- a/projects/c/sonar-project.properties +++ /dev/null @@ -1,13 +0,0 @@ -# Required metadata -sonar.projectKey=my:project -sonar.projectName=My project -sonar.projectVersion=1.0 - -# Description of project (optional) -sonar.projectDescription=C project inspected with Java Runner - -# Comma-separated paths to directories with sources (required) -sources=src - -# Language must be specified, because default language is Java -sonar.language=c diff --git a/projects/c/src/hello.c b/projects/c/src/hello.c deleted file mode 100644 index 97361a65..00000000 --- a/projects/c/src/hello.c +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include - -int main(void) { - printf("Hello, world."); -} diff --git a/projects/ci-workaround-pom.xml b/projects/ci-workaround-pom.xml new file mode 100644 index 00000000..8ab54387 --- /dev/null +++ b/projects/ci-workaround-pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + org.sonarqube.examples + ci-workaround + 0.1-SNAPSHOT + + CI Workaround + Temporary patch to have CI working fine with Orchestrator 3.7 + + + UTF-8 + + + + + org.sonarsource.flex + sonar-flex-plugin + 2.2.1 + + + org.sonarsource.php + sonar-php-plugin + 2.7 + + + org.sonarsource.javascript + sonar-javascript-plugin + 2.8 + + + + diff --git a/projects/gradle-modules/README.md b/projects/gradle-modules/README.md deleted file mode 100644 index 46a7fd40..00000000 --- a/projects/gradle-modules/README.md +++ /dev/null @@ -1,19 +0,0 @@ -This example demonstrates how to analyse project with [Gradle](http://www.gradle.org/). - -Prerequisites -============= - -* Sonar 2.9 or higher -* Gradle 1.0-milestone-5 or higher - -Execution -========= - -1. Build project and execute all tests: - - gradle build - -2. Analyse by Sonar: - - gradle sonar - diff --git a/projects/gradle-modules/build.gradle b/projects/gradle-modules/build.gradle deleted file mode 100644 index 21a1e006..00000000 --- a/projects/gradle-modules/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -apply plugin: "sonar" - -sonar { - server { - url = System.getProperty("sonar.host.url") ?: "http://localhost:9000/" - } - - database { - url = System.getProperty("sonar.jdbc.url") ?: "jdbc:derby://localhost:1527/sonar" - driverClassName = System.getProperty("sonar.jdbc.driver") ?: "org.apache.derby.jdbc.ClientDriver" - username = System.getProperty("sonar.jdbc.username") ?: "sonar" - password = System.getProperty("sonar.jdbc.password") ?: "sonar" - } - - project { - withProjectProperties { props -> - props["sonar.core.codeCoveragePlugin"] = "jacoco" - } - } -} - -subprojects { - apply plugin: 'java' - - buildDir = "target" - - repositories { - mavenCentral() - mavenLocal() - } -} diff --git a/projects/gradle/README.md b/projects/gradle/README.md deleted file mode 100644 index 46a7fd40..00000000 --- a/projects/gradle/README.md +++ /dev/null @@ -1,19 +0,0 @@ -This example demonstrates how to analyse project with [Gradle](http://www.gradle.org/). - -Prerequisites -============= - -* Sonar 2.9 or higher -* Gradle 1.0-milestone-5 or higher - -Execution -========= - -1. Build project and execute all tests: - - gradle build - -2. Analyse by Sonar: - - gradle sonar - diff --git a/projects/gradle/build.gradle b/projects/gradle/build.gradle deleted file mode 100644 index 65072de9..00000000 --- a/projects/gradle/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -apply plugin: "java" -apply plugin: "sonar" - -buildDir = "target" - -repositories { - mavenCentral() - mavenLocal() -} - -configurations { - jacoco -} - -dependencies { - testCompile group: "junit", name: "junit", version: "4.8.1" - - jacoco group: "org.jacoco", name: "org.jacoco.agent", version: "0.5.3.201107060350", classifier: "runtime" -} - -test { - jvmArgs "-javaagent:" + configurations.jacoco.asPath + "=destfile=" + buildDir + "/jacoco.exec,includes=example.*" -} - -sonar { - server { - url = System.getProperty("sonar.host.url") ?: "http://localhost:9000/" - } - - database { - url = System.getProperty("sonar.jdbc.url") ?: "jdbc:derby://localhost:1527/sonar" - driverClassName = System.getProperty("sonar.jdbc.driver") ?: "org.apache.derby.jdbc.ClientDriver" - username = System.getProperty("sonar.jdbc.username") ?: "sonar" - password = System.getProperty("sonar.jdbc.password") ?: "sonar" - } - - project { - withProjectProperties { props -> - props["sonar.core.codeCoveragePlugin"] = "jacoco" - } - } -} diff --git a/projects/java-runner/README.md b/projects/java-runner/README.md deleted file mode 100644 index 8b764cb1..00000000 --- a/projects/java-runner/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This example demonstrates how to analyse Java project with Sonar Runner. - -Prerequisites -============= - -* Sonar 2.6 or higher -* Sonar Runner 1.1 or higher diff --git a/projects/java-runner/build/classes/Helloworld.class b/projects/java-runner/build/classes/Helloworld.class deleted file mode 100644 index eaab8ecb..00000000 Binary files a/projects/java-runner/build/classes/Helloworld.class and /dev/null differ diff --git a/projects/java-runner/lib/deprecated.jar b/projects/java-runner/lib/deprecated.jar deleted file mode 100644 index 65e3be99..00000000 Binary files a/projects/java-runner/lib/deprecated.jar and /dev/null differ diff --git a/projects/java-runner/sonar-project.properties b/projects/java-runner/sonar-project.properties deleted file mode 100644 index c996b309..00000000 --- a/projects/java-runner/sonar-project.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Required metadata -sonar.projectKey=java-runner -sonar.projectName=Java Runner -sonar.projectVersion=1.0 - -# Description of project (optional) -sonar.projectDescription=Java project inspected with Java Runner - -# Comma-separated paths to directories with sources (required) -sources=src - -# Comma-separated paths to directories with binaries (optional), in case of Java - directories with class files -binaries=build/classes - -# Comma-separated paths to files with third-party libraries (optional), in case of Java - JAR files -libraries=lib/deprecated.jar - -# Java is the default language, so the following property can be commented -sonar.language=java diff --git a/projects/java-runner/src/Helloworld.java b/projects/java-runner/src/Helloworld.java deleted file mode 100644 index 8fd59684..00000000 --- a/projects/java-runner/src/Helloworld.java +++ /dev/null @@ -1,13 +0,0 @@ -public class Helloworld { - - private String field; - - public void use() { - new DeprecatedExample().deprecatedMethod(); - System.exit(33); // violation on findbugs rule: DM_EXIT - } - - public void useFieldForLcom4() { - System.out.println(field); - } -} diff --git a/projects/languages/abap/README.md b/projects/languages/abap/README.md new file mode 100644 index 00000000..9e42c735 --- /dev/null +++ b/projects/languages/abap/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze an SAP ABAP project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarSource ABAP Plugin](http://www.sonarsource.com/products/plugins/languages/abap/) 3.2.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/abap/sonar-project.properties b/projects/languages/abap/sonar-project.properties new file mode 100644 index 00000000..3def2c0a --- /dev/null +++ b/projects/languages/abap/sonar-project.properties @@ -0,0 +1,9 @@ +sonar.projectKey=org.sonarqube:abap-simple-sq-scanner +sonar.projectName=ABAP :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src + +sonar.language=abap + +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/abap/src/ZBCMKZ17.abap b/projects/languages/abap/src/ZBCMKZ17.abap new file mode 100644 index 00000000..936119df --- /dev/null +++ b/projects/languages/abap/src/ZBCMKZ17.abap @@ -0,0 +1,147 @@ +REPORT ZBCMKZ17. +*----------------------------------------------------------------------* +* Description: Report and Transaction Starter * +* It shows an individual list of reports/Trans. to start* +* * +* Authorization: S_PROGRAM, Reports starten * +* * +* Class: Utility * +* * +* Customizing: Needs Customer Table: ZBCMKZ1 * +* Field: Key Type Length Descr. * +* ZBCMKZ1-BNAME X CHAR C 12 User name * +* ZBCMKZ1-NAME X CHAR C 8 Report/Trans. code * +* ZBCMKZ1-NUMMER INT1 X 1 Priority level * +* * +* R/3 Release: 3.0d * +* * +* Programmer: Bence Toth * +* Date: 1997 April * +* * +*----------------------------------------------------------------------* +INCLUDE: . +TABLES: ZBCMKZ1, TRDIR, TSTCT, TSTC. +DATA: BEGIN OF BTAB OCCURS 50, "Hilfstabelle fuer Textpool + CODE(82), + END OF BTAB. +DATA: BEGIN OF T OCCURS 100, + NUMMER LIKE ZBCMKZ1-NUMMER, + NAME LIKE TRDIR-NAME, + CODE(82), +END OF T. +DATA: FI(20). +DATA BEGIN OF BDCDATA OCCURS 100. + INCLUDE STRUCTURE BDCDATA. +DATA END OF BDCDATA. + +DATA BEGIN OF MESSTAB OCCURS 10. + INCLUDE STRUCTURE BDCMSGCOLL. +DATA END OF MESSTAB. + +DATA REPORT. +AUTHORITY-CHECK OBJECT 'S_PROGRAM' + ID 'P_GROUP' FIELD '*' + ID 'P_ACTION' FIELD '*'. +IF SY-SUBRC NE 0. EXIT. ENDIF. +WRITE: /2 'Er. Modus', 12 'Name', 22 'Text'. + + +DETAIL. +SKIP. +SELECT * FROM ZBCMKZ1 WHERE BNAME EQ SY-UNAME. + CHECK ZBCMKZ1-NAME+5(1) EQ ' '. + SELECT SINGLE * FROM TSTC WHERE TCODE EQ ZBCMKZ1-NAME. + CHECK SY-SUBRC EQ 0. + CLEAR TSTCT. + SELECT SINGLE * FROM TSTCT WHERE SPRSL EQ SY-LANGU AND + TCODE EQ ZBCMKZ1-NAME. + T-CODE = TSTCT-TTEXT. + MOVE-CORRESPONDING ZBCMKZ1 TO T. + APPEND T. + CLEAR T. +ENDSELECT. +SORT T BY NUMMER CODE. +REPORT = ' '. +PERFORM LIST USING REPORT. +SELECT * FROM ZBCMKZ1 WHERE BNAME EQ SY-UNAME. + CHECK ZBCMKZ1-NAME+5(1) NE ' '. + READ TEXTPOOL ZBCMKZ1-NAME INTO BTAB LANGUAGE SY-LANGU. + CHECK SY-SUBRC EQ 0. + LOOP AT BTAB. + IF BTAB-CODE(1) EQ 'R'. + EXIT. + ENDIF. + ENDLOOP. + MOVE BTAB-CODE+9(70) TO T-CODE. + MOVE-CORRESPONDING ZBCMKZ1 TO T. + APPEND T. + CLEAR T. +ENDSELECT. +SORT T BY NUMMER CODE. +REPORT = 'X'. +PERFORM LIST USING REPORT. + +AT LINE-SELECTION. + CHECK NOT ( T-NAME IS INITIAL ). + GET CURSOR FIELD FI. + IF T-NAME+5(1) EQ ' '. + REPORT = ' '. + ELSE. + REPORT = 'X'. + ENDIF. + IF FI = 'ICON_EXECUTE_OBJECT'. + PERFORM PERO USING T-NAME REPORT. + ELSEIF REPORT EQ ' '. +* SELECT SINGLE * FROM TSTC WHERE TCODE EQ ZBCMKZ1-NAME. +* IF T+5(1) EQ ' '. + CALL TRANSACTION T-NAME. + ELSE. + SUBMIT (T-NAME) VIA SELECTION-SCREEN AND RETURN. + ENDIF. + CLEAR T-NAME. +*---------------------------------------------------------------------* +* FORM LIST * +*---------------------------------------------------------------------* +* ........ * +*---------------------------------------------------------------------* +FORM LIST USING REPORT. + LOOP AT T. + IF REPORT = ' '. + WRITE: /5 ICON_EXECUTE_OBJECT AS ICON, T-NAME UNDER 'Name', + T-CODE UNDER 'Text'. + ELSE. + WRITE: / T-NAME UNDER 'Name', T-CODE UNDER 'Text'. + ENDIF. + HIDE T. + AT END OF NUMMER. + SKIP. + ENDAT. + ENDLOOP. + SKIP. + CLEAR T. + REFRESH T. +ENDFORM. +*---------------------------------------------------------------------* +* FORM PERO * +*---------------------------------------------------------------------* +* ........ * +*---------------------------------------------------------------------* +* --> T-NAME * +*---------------------------------------------------------------------* +FORM PERO USING T-NAME REPORT. + CHECK REPORT EQ ' '. + MOVE T-NAME TO T-NAME+2(4). + MOVE '/o' TO T-NAME+0(2). + BDCDATA-PROGRAM = 'SAPMS01J'. + BDCDATA-DYNPRO = '0310'. + BDCDATA-DYNBEGIN = 'X'. + APPEND BDCDATA. + CLEAR BDCDATA. + BDCDATA-FNAM = 'BDC_OKCODE'. + BDCDATA-FVAL = T-NAME. + APPEND BDCDATA. + CALL TRANSACTION 'SU50' USING BDCDATA MODE 'N' + MESSAGES INTO MESSTAB. + CLEAR BDCDATA. + REFRESH BDCDATA. +ENDFORM. diff --git a/projects/languages/abap/src/ZZBGS106.abap b/projects/languages/abap/src/ZZBGS106.abap new file mode 100644 index 00000000..cc3e07ca --- /dev/null +++ b/projects/languages/abap/src/ZZBGS106.abap @@ -0,0 +1,194 @@ +REPORT ZZBGS106 MESSAGE-ID Z1. +*----------------------------------------------------------------------* +* Description: Utillity used for downloading abap/4 source code and * +* text elements to the desktop using ws_download. * +* Is useful as backup or for transporting to another site.* +* You must run this program in foreground/online due to * +* the use of ws_download throug the SAPGUI. * +* * +* Implementing The program is client independent. * +* * +* Authoriza. No Authorization check. * +* * +* Submitting: Run by SA38, SE38. * +* * +* Parametre: You can use generic values when filling the parameters * +* except for the Path. * +* * +* Customizing: No need for customization. * +* * +* Change of You only need to do the syntax check at releasechanges. * +* release: * +* * +* R/3 Release: Developed and tested in R/3 Release: * +* 2.2F * +* 3.0D * +* * +* Programmer: Benny G. Serensen, BGS-Consulting * +* Date: Nov 1996. * +* * +* Version 1 +*-------------------------------Corrections----------------------------* +* Date Userid Correction Text * +* 11.11.1996 BGS :::::::::::::: Start of development * +*----------------------------------------------------------------------* +*----------------------------------------------------------------------* +* Tables * +*----------------------------------------------------------------------* +TABLES: TRDIR "Application Masterdata + . +*----------------------------------------------------------------------* +* Parameters * +*----------------------------------------------------------------------* +SELECT-OPTIONS: REPO FOR TRDIR-NAME. +PARAMETERS: PATH(60) TYPE C DEFAULT 'C:\SAP\'. + +*----------------------------------------------------------------------* +* Work Variables and internal tables * +*----------------------------------------------------------------------* +DATA: BEGIN OF TABSOURCE OCCURS 10 + ,SOURCE(72) TYPE C + ,END OF TABSOURCE. + +DATA: BEGIN OF TABTEXT OCCURS 50 + ,TAB LIKE TEXTPOOL + ,END OF TABTEXT. + +DATA: BEGIN OF TABRDIR OCCURS 100 + ,RDIR LIKE TRDIR + ,END OF TABRDIR. + +DATA: FILENAME LIKE RLGRAP-FILENAME + ,MODE TYPE C VALUE ' ' + ,RDIRROWS TYPE I + ,SOURCEROWS TYPE I + ,RC TYPE I + ,LENGTH TYPE I + . +FIELD-SYMBOLS:

. + +*----------------------------------------------------------------------* +* Constants * +*----------------------------------------------------------------------* +DATA: OK TYPE I VALUE 0 + ,FAIL TYPE I VALUE 1. + +*----------------------------------------------------------------------* +* EVENT: validate users entries on the selection screen * +*----------------------------------------------------------------------* +AT SELECTION-SCREEN. +DATA: I TYPE I. + DESCRIBE TABLE REPO LINES I. + IF I <= 0. + SET CURSOR FIELD REPO. + MESSAGE E065 WITH TEXT-101. + ENDIF. + +*----------------------------------------------------------------------* +* EVENT: Start-Of-Selection * +*----------------------------------------------------------------------* +START-OF-SELECTION. +* Set slash at the end of path if not speciefied by user + CONDENSE PATH NO-GAPS. + LENGTH = STRLEN( PATH ) . + SUBTRACT 1 FROM LENGTH. + ASSIGN PATH+LENGTH(1) TO

. + IF

<> '\'. + ADD 1 TO LENGTH. + ASSIGN PATH+LENGTH TO

. +

= '\'. + ENDIF. + + SELECT * FROM TRDIR INTO TABLE TABRDIR WHERE NAME IN REPO. + DESCRIBE TABLE TABRDIR LINES RDIRROWS. + CHECK RDIRROWS > 0. + +* For every selected program: + LOOP AT TABRDIR. + MOVE TABRDIR TO TRDIR. + PERFORM DOWNLOAD_SOURCE USING RC. + CHECK RC = OK. + PERFORM DOWNLOAD_TEXTPOOL USING RC. + ENDLOOP. + +*----------------------------------------------------------------------* +* FORM: Download_Sourcecode * +*----------------------------------------------------------------------* +FORM DOWNLOAD_SOURCE USING RC. + RC = FAIL. + CLEAR: TABSOURCE, FILENAME. + REFRESH: TABSOURCE. + READ REPORT TRDIR-NAME INTO TABSOURCE. + DESCRIBE TABLE TABSOURCE LINES SOURCEROWS. + CHECK SOURCEROWS > 0. + + CALL FUNCTION 'STRING_CONCATENATE_3' "R. 2.2F + EXPORTING "R. 2.2F + STRING1 = PATH "R. 2.2F + STRING2 = TRDIR-NAME "R. 2.2F + STRING3 = '.aba' "R. 2.2F + IMPORTING "R. 2.2F + STRING = FILENAME "R. 2.2F + EXCEPTIONS "R. 2.2F + TOO_SMALL = 01. "R. 2.2F + +* CONCATENATE PATH TRDIR-NAME '.ABA' INTO FILENAME. "R. 3.0D + CONDENSE FILENAME NO-GAPS. + PERFORM DOWNLOAD TABLES TABSOURCE USING FILENAME RC. + +ENDFORM. + +*----------------------------------------------------------------------* +* FORM: Download_Textpool * +*----------------------------------------------------------------------* +FORM DOWNLOAD_TEXTPOOL USING RC. + RC = FAIL. + CLEAR: TABTEXT, FILENAME. + REFRESH: TABTEXT. + READ TEXTPOOL TRDIR-NAME INTO TABTEXT LANGUAGE SY-LANGU. + DESCRIBE TABLE TABTEXT LINES SOURCEROWS. + CHECK SOURCEROWS > 0. + + CALL FUNCTION 'STRING_CONCATENATE_3' "R. 2.2F + EXPORTING "R. 2.2F + STRING1 = PATH "R. 2.2F + STRING2 = TRDIR-NAME "R. 2.2F + STRING3 = '.TXT' "R. 2.2F + IMPORTING "R. 2.2F + STRING = FILENAME "R. 2.2F + EXCEPTIONS "R. 2.2F + TOO_SMALL = 01. "R. 2.2F + +* CONCATENATE PATH TRDIR-NAME '.TXT' INTO FILENAME. "R. 3.0x + CONDENSE FILENAME NO-GAPS. + PERFORM DOWNLOAD TABLES TABTEXT USING FILENAME RC. + +ENDFORM. + +*----------------------------------------------------------------------* +* FORM: Download * +*----------------------------------------------------------------------* +FORM DOWNLOAD TABLES TABDATA USING FILENAME RC. + + RC = FAIL. + CALL FUNCTION 'WS_DOWNLOAD' + EXPORTING + FILENAME = FILENAME + FILETYPE = 'ASC' + MODE = MODE + TABLES + DATA_TAB = TABDATA + EXCEPTIONS + FILE_OPEN_ERROR = 1 + FILE_WRITE_ERROR = 2 + INVALID_FILESIZE = 3 + INVALID_TABLE_WIDTH = 4 + INVALID_TYPE = 5 + NO_BATCH = 6 + UNKNOWN_ERROR = 7. + IF SY-SUBRC <> OK. + WRITE:/ SY-SUBRC, TEXT-100. + ENDIF. + RC = SY-SUBRC. + +ENDFORM. diff --git a/projects/languages/abap/validation.txt b/projects/languages/abap/validation.txt new file mode 100644 index 00000000..cafd8830 --- /dev/null +++ b/projects/languages/abap/validation.txt @@ -0,0 +1,8 @@ +start server + with plugin abap 3.2 +sonar-runner +verify org.sonarqube:abap-simple-sq-scanner + measure lines is 343 + measure ncloc is 218 + measure files is 2 +stop server diff --git a/projects/languages/android/android-sonarqube-gradle/README.md b/projects/languages/android/android-sonarqube-gradle/README.md new file mode 100644 index 00000000..4993fed4 --- /dev/null +++ b/projects/languages/android/android-sonarqube-gradle/README.md @@ -0,0 +1,23 @@ +This example demonstrates how to analyze a simple Android App with SonarQube Scanner for Gradle. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner for Gradle Runner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Gradle) 2.0.1+ +* [SonarQube Android Lint Plugin](http://docs.sonarqube.org/display/SONAR/Android+Lint+Plugin) 1.1+ +* [Android SDK 23](http://developer.android.com/sdk/index.html) +* [Android Build Tools 23.0.3](http://developer.android.com/tools/help/sdk-manager.html) +* Make sure that environment variable ANDROID_HOME is correctly defined + +Usage +===== +* Build the project with Gradle: + + gradle build + +* Analyze the project with SonarQube using the SonarQube Scanner for Gradle: + + gradle sonarqube + + +In order to benefit from Android Lint rules, do not forget to use a SonarQube quality profile that contains Android Lint rules for your analyses. diff --git a/projects/languages/android/android-sonarqube-gradle/app/build.gradle b/projects/languages/android/android-sonarqube-gradle/app/build.gradle new file mode 100644 index 00000000..7e0176be --- /dev/null +++ b/projects/languages/android/android-sonarqube-gradle/app/build.gradle @@ -0,0 +1,46 @@ +apply plugin: 'com.android.application' +apply plugin: "org.sonarqube" + + +sonarqube { + properties { + property "sonar.projectName", "Android Lint :: Simple Project :: SonarQube Scanner for Gradle" + property "sonar.projectKey", "org.sonarqube:android-simple-sq-scanner-gradle" + + property "sonar.sourceEncoding","UTF-8" + property "sonar.sources","." + property "sonar.exclusions","build/**,**/*.png" + + property "sonar.import_unknown_files", true + + property "sonar.android.lint.report", "./build/outputs/lint-results.xml" + } +} + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.3" + + defaultConfig { + applicationId "org.sonarqube.helloworldandroid" + minSdkVersion 16 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + lintOptions { + abortOnError false + } +} + +dependencies { + compile 'com.android.support:support-v4:23.3.0' + compile 'com.android.support:design:23.+' + testCompile 'junit:junit:4.12' +} diff --git a/projects/languages/android/android-sonarqube-gradle/app/proguard-rules.pro b/projects/languages/android/android-sonarqube-gradle/app/proguard-rules.pro new file mode 100644 index 00000000..451b28ed --- /dev/null +++ b/projects/languages/android/android-sonarqube-gradle/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/alexandregigleux/Library/Android/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/projects/languages/android/android-sonarqube-gradle/app/src/androidTest/java/org/sonarqube/helloworldandroid/ApplicationTest.java b/projects/languages/android/android-sonarqube-gradle/app/src/androidTest/java/org/sonarqube/helloworldandroid/ApplicationTest.java new file mode 100644 index 00000000..aaa8d9ea --- /dev/null +++ b/projects/languages/android/android-sonarqube-gradle/app/src/androidTest/java/org/sonarqube/helloworldandroid/ApplicationTest.java @@ -0,0 +1,13 @@ +package org.sonarqube.helloworldandroid; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/projects/languages/android/android-sonarqube-gradle/app/src/main/AndroidManifest.xml b/projects/languages/android/android-sonarqube-gradle/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..d26608c7 --- /dev/null +++ b/projects/languages/android/android-sonarqube-gradle/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/projects/languages/android/android-sonarqube-gradle/app/src/main/java/org/sonarqube/helloworldandroid/LoginActivity.java b/projects/languages/android/android-sonarqube-gradle/app/src/main/java/org/sonarqube/helloworldandroid/LoginActivity.java new file mode 100644 index 00000000..99ab5c54 --- /dev/null +++ b/projects/languages/android/android-sonarqube-gradle/app/src/main/java/org/sonarqube/helloworldandroid/LoginActivity.java @@ -0,0 +1,302 @@ +package org.sonarqube.helloworldandroid; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.annotation.TargetApi; +import android.support.v7.app.AppCompatActivity; +import android.app.LoaderManager.LoaderCallbacks; + +import android.content.CursorLoader; +import android.content.Loader; +import android.database.Cursor; +import android.net.Uri; +import android.os.AsyncTask; + +import android.os.Build; +import android.os.Bundle; +import android.provider.ContactsContract; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.EditorInfo; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + + +/** + * A login screen that offers login via email/password. + */ +public class LoginActivity extends AppCompatActivity implements LoaderCallbacks { + + /** + * A dummy authentication store containing known user names and passwords. + * TODO: remove after connecting to a real authentication system. + */ + private static final String[] DUMMY_CREDENTIALS = new String[]{ + "foo@example.com:hello", "bar@example.com:world" + }; + /** + * Keep track of the login task to ensure we can cancel it if requested. + */ + private UserLoginTask mAuthTask = null; + + // UI references. + private AutoCompleteTextView mEmailView; + private EditText mPasswordView; + private View mProgressView; + private View mLoginFormView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + // Set up the login form. + mEmailView = (AutoCompleteTextView) findViewById(R.id.email); + populateAutoComplete(); + + mPasswordView = (EditText) findViewById(R.id.password); + mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) { + if (id == R.id.login || id == EditorInfo.IME_NULL) { + attemptLogin(); + return true; + } + return false; + } + }); + + Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button); + mEmailSignInButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + attemptLogin(); + } + }); + + mLoginFormView = findViewById(R.id.login_form); + mProgressView = findViewById(R.id.login_progress); + } + + private void populateAutoComplete() { + getLoaderManager().initLoader(0, null, this); + } + + + /** + * Attempts to sign in or register the account specified by the login form. + * If there are form errors (invalid email, missing fields, etc.), the + * errors are presented and no actual login attempt is made. + */ + private void attemptLogin() { + if (mAuthTask != null) { + return; + } + + // Reset errors. + mEmailView.setError(null); + mPasswordView.setError(null); + + // Store values at the time of the login attempt. + String email = mEmailView.getText().toString(); + String password = mPasswordView.getText().toString(); + + boolean cancel = false; + View focusView = null; + + // Check for a valid password, if the user entered one. + if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) { + mPasswordView.setError(getString(R.string.error_invalid_password)); + focusView = mPasswordView; + cancel = true; + } + + // Check for a valid email address. + if (TextUtils.isEmpty(email)) { + mEmailView.setError(getString(R.string.error_field_required)); + focusView = mEmailView; + cancel = true; + } else if (!isEmailValid(email)) { + mEmailView.setError(getString(R.string.error_invalid_email)); + focusView = mEmailView; + cancel = true; + } + + if (cancel) { + // There was an error; don't attempt login and focus the first + // form field with an error. + focusView.requestFocus(); + } else { + // Show a progress spinner, and kick off a background task to + // perform the user login attempt. + showProgress(true); + mAuthTask = new UserLoginTask(email, password); + mAuthTask.execute((Void) null); + } + } + + private boolean isEmailValid(String email) { + //TODO: Replace this with your own logic + return email.contains("@"); + } + + private boolean isPasswordValid(String password) { + //TODO: Replace this with your own logic + return password.length() > 4; + } + + /** + * Shows the progress UI and hides the login form. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) + private void showProgress(final boolean show) { + // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow + // for very easy animations. If available, use these APIs to fade-in + // the progress spinner. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + + mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); + mLoginFormView.animate().setDuration(shortAnimTime).alpha( + show ? 0 : 1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); + } + }); + + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mProgressView.animate().setDuration(shortAnimTime).alpha( + show ? 1 : 0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + } + }); + } else { + // The ViewPropertyAnimator APIs are not available, so simply show + // and hide the relevant UI components. + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); + } + } + + @Override + public Loader onCreateLoader(int i, Bundle bundle) { + return new CursorLoader(this, + // Retrieve data rows for the device user's 'profile' contact. + Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI, + ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION, + + // Select only email addresses. + ContactsContract.Contacts.Data.MIMETYPE + + " = ?", new String[]{ContactsContract.CommonDataKinds.Email + .CONTENT_ITEM_TYPE}, + + // Show primary email addresses first. Note that there won't be + // a primary email address if the user hasn't specified one. + ContactsContract.Contacts.Data.IS_PRIMARY + " DESC"); + } + + @Override + public void onLoadFinished(Loader cursorLoader, Cursor cursor) { + List emails = new ArrayList<>(); + cursor.moveToFirst(); + while (!cursor.isAfterLast()) { + emails.add(cursor.getString(ProfileQuery.ADDRESS)); + cursor.moveToNext(); + } + + addEmailsToAutoComplete(emails); + } + + @Override + public void onLoaderReset(Loader cursorLoader) { + + } + + private void addEmailsToAutoComplete(List emailAddressCollection) { + //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list. + ArrayAdapter adapter = + new ArrayAdapter<>(LoginActivity.this, + android.R.layout.simple_dropdown_item_1line, emailAddressCollection); + + mEmailView.setAdapter(adapter); + } + + + private interface ProfileQuery { + String[] PROJECTION = { + ContactsContract.CommonDataKinds.Email.ADDRESS, + ContactsContract.CommonDataKinds.Email.IS_PRIMARY, + }; + + int ADDRESS = 0; + int IS_PRIMARY = 1; + } + + /** + * Represents an asynchronous login/registration task used to authenticate + * the user. + */ + public class UserLoginTask extends AsyncTask { + + private final String mEmail; + private final String mPassword; + + UserLoginTask(String email, String password) { + mEmail = email; + mPassword = password; + } + + @Override + protected Boolean doInBackground(Void... params) { + // TODO: attempt authentication against a network service. + + try { + // Simulate network access. + Thread.sleep(2000); + } catch (InterruptedException e) { + return false; + } + + for (String credential : DUMMY_CREDENTIALS) { + String[] pieces = credential.split(":"); + if (pieces[0].equals(mEmail)) { + // Account exists, return true if the password matches. + return pieces[1].equals(mPassword); + } + } + + // TODO: register the new account here. + return true; + } + + @Override + protected void onPostExecute(final Boolean success) { + mAuthTask = null; + showProgress(false); + + if (success) { + finish(); + } else { + mPasswordView.setError(getString(R.string.error_incorrect_password)); + mPasswordView.requestFocus(); + } + } + + @Override + protected void onCancelled() { + mAuthTask = null; + showProgress(false); + } + } +} + diff --git a/projects/languages/android/android-sonarqube-gradle/app/src/main/res/layout/activity_login.xml b/projects/languages/android/android-sonarqube-gradle/app/src/main/res/layout/activity_login.xml new file mode 100644 index 00000000..b5ea1e23 --- /dev/null +++ b/projects/languages/android/android-sonarqube-gradle/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + +

+ +
+ +
+ + + + + + + + + + +

+ +
+ altrow +
+ +
+
+ +
+
+
+
+
+ + + +
+ + altrow + + + Test Assembly Cleanup + Test Collection Cleanup + Test Class Cleanup + Test Method Cleanup + Test Case Cleanup + Test Cleanup + Fatal Error + + () + +
+ +
+
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/NUnitXml.xslt b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/NUnitXml.xslt new file mode 100644 index 00000000..228fbedd --- /dev/null +++ b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/NUnitXml.xslt @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + True + + + + + + + + + + + + + + + + + + False + True + + + + + + + + + + + + + + + + + False + True + + + + + + + + + + + + + + + + + + + + + + + + + False + True + + + + False + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xUnit1.xslt b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xUnit1.xslt new file mode 100644 index 00000000..a8425d36 --- /dev/null +++ b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xUnit1.xslt @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.abstractions.dll b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.abstractions.dll new file mode 100644 index 00000000..f6457097 Binary files /dev/null and b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.abstractions.dll differ diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.exe b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.exe new file mode 100644 index 00000000..4adb57f5 Binary files /dev/null and b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.exe differ diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.exe.config b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.exe.config new file mode 100644 index 00000000..6f7877d8 --- /dev/null +++ b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.exe.config @@ -0,0 +1,18 @@ + + + +
+ + + + + + + + + + + + + + diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.x86.exe b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.x86.exe new file mode 100644 index 00000000..0a9881d2 Binary files /dev/null and b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.x86.exe differ diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.x86.exe.config b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.x86.exe.config new file mode 100644 index 00000000..f68633bd --- /dev/null +++ b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.console.x86.exe.config @@ -0,0 +1,18 @@ + + + +
+ + + + + + + + + + + + + + diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.runner.reporters.desktop.dll b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.runner.reporters.desktop.dll new file mode 100644 index 00000000..8be2ed3d Binary files /dev/null and b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.runner.reporters.desktop.dll differ diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.runner.utility.desktop.dll b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.runner.utility.desktop.dll new file mode 100644 index 00000000..fc88513d Binary files /dev/null and b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/tools/xunit.runner.utility.desktop.dll differ diff --git a/projects/languages/csharp/packages/xunit.runner.console.2.1.0/xunit.runner.console.2.1.0.nupkg b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/xunit.runner.console.2.1.0.nupkg new file mode 100644 index 00000000..29efca19 Binary files /dev/null and b/projects/languages/csharp/packages/xunit.runner.console.2.1.0/xunit.runner.console.2.1.0.nupkg differ diff --git a/projects/languages/css/css-sonar-runner/README.md b/projects/languages/css/css-sonar-runner/README.md new file mode 100644 index 00000000..9f33e906 --- /dev/null +++ b/projects/languages/css/css-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a simple CSS project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube CSS Plugin](https://github.com/SonarCommunity/sonar-css) 1.8+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/css/css-sonar-runner/sonar-project.properties b/projects/languages/css/css-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..de6ebdf8 --- /dev/null +++ b/projects/languages/css/css-sonar-runner/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:css-simple-sq-scanner +sonar.projectName=CSS :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=css + +# Encoding of sources files +sonar.sourceEncoding=US-ASCII diff --git a/projects/languages/css/css-sonar-runner/src/sample.css b/projects/languages/css/css-sonar-runner/src/sample.css new file mode 100644 index 00000000..9622216a --- /dev/null +++ b/projects/languages/css/css-sonar-runner/src/sample.css @@ -0,0 +1,89 @@ +.quality-gates-navigator .navigator-side { + display: table-cell; + vertical-align: top; + width: 250px; + min-width: 0; +} +.quality-gates-navigator .navigator-header { + margin-left: 0; +} +.quality-gates-navigator .navigator-header .spinner { + margin-top: 9px; +} +.quality-gates-navigator .navigator-actions { + height: 40px; + width: 230px; + margin: 10px; + padding: 0 10px; +} +.quality-gates-navigator .navigator-actions .navigator-header-title { + color: #444; + font-size: 13px; + font-weight: 700; + text-transform: uppercase; +} +.quality-gates-navigator .navigator-results { + width: 230px; + min-width: 0; +} +.quality-gates-navigator .navigator-details { + margin-left: 0; +} +.quality-gates-nav .navigator-results-list>li { + border-color: transparent; +} +.quality-gates-nav .navigator-results-list>li:hover:not(.active):not(.empty) { + background-color: #f3f3f3; +} +.quality-gates-nav .navigator-results-list>li.active { + border-color: #4B9FD5; +} +.quality-gates-nav .navigator-results-list>li.empty { + cursor: default; +} +.quality-gates-nav .navigator-results-list>li .line { + padding-top: 2px; + padding-bottom: 2px; +} +.quality-gates-nav .navigator-results-list>li .subtitle { + text-transform: lowercase; +} +.quality-gate-section+.quality-gate-section { + margin-top: 10px; + padding-top: 20px; +} +.quality-gate-section-empty+.quality-gate-section { + border-top: 1px solid #e6e6e6; +} +.quality-gate-section-name { + margin-bottom: 10px; + font-weight: 700; + text-transform: uppercase; +} +.quality-gate-introduction { + margin-bottom: 20px; +} +.quality-gate-new-condition { + margin-bottom: 10px; +} +.quality-gate-condition-actions { + position: relative; +} +.quality-gate-default-message { + padding: 6px 5px; + border: 1px solid #ddd; + background-color: #efefef; +} +.quality-gate-conditions-wrap { + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; +} +.quality-gate-conditions .deprecated { + color: #777; + text-transform: lowercase; + font-variant: small-caps; +} +.quality-gate-conditions tbody { + border-left: none!important; + border-right: none!important; +} \ No newline at end of file diff --git a/projects/languages/css/css-sonar-runner/src/sonar.css b/projects/languages/css/css-sonar-runner/src/sonar.css new file mode 100644 index 00000000..0fac7434 --- /dev/null +++ b/projects/languages/css/css-sonar-runner/src/sonar.css @@ -0,0 +1,7168 @@ +html { + color: #000; + background: #fff; +} +body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td { + margin: 0; + padding: 0; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +fieldset, img { + border: 0; +} +address, caption, cite, code, dfn, em, strong, th, var { + font-style: normal; + font-weight: 400; +} +ol, ul { + list-style: none; +} +caption, th { + text-align: left; +} +h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-weight: 400; +} +q:before, q:after { + content: ''} +abbr, acronym { + border: 0; + font-variant: normal; +} +sup { + vertical-align: text-top; +} +sub { + vertical-align: text-bottom; +} +input, textarea, select { + font-family: inherit; + font-size: inherit; + font-weight: inherit; +} +input, textarea, select { + *font-size: 100%} +legend { + color: #000; +} +body { + font: 13px/1.231 arial, helvetica, clean, sans-serif; + *font-size: small; + *font: x-small; +} +select, input, button, textarea { + font: 99% arial, helvetica, clean, sans-serif; +} +table { + font-size: inherit; + font: 100%} +pre, code, kbd, samp, tt { + font-family: monospace; + *font-size: 108%; + line-height: 100%} +/*! jQuery UI - v1.10.3 - 2013-06-18 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.button.css, jquery.ui.dialog.css +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */.no-close .ui-dialog-titlebar-close { + display: none; +} +.ui-dialog .ui-dialog-titlebar { + display: none; +} +.ui-widget-header { + color: #fff; + font-weight: 700; +} +.ui-widget-header a { + color: #fff; +} +.ui-widget-shadow { + margin: -5px 0 0 -5px; + padding: 5px; + background: #000 50% 50% repeat-x; + opacity: .2; + -moz-border-radius: 5px; + -khtml-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} +.ui-dialog { + position: absolute; + width: 300px; + overflow: hidden; + box-shadow: 10px 10px 20px rgba(0, 0, 0, .5); + background-color: #fff; +} +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, .ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; +} +.ui-front { + z-index: 100; +} +.ui-state-disabled { + cursor: default!important; +} +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #000; + opacity: .5; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: .1px; + display: block; +} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-button { + display: inline-block; + position: relative; + padding: 0; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + overflow: visible; +} +.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { + text-decoration: none; +} +.ui-button-icon-only { + width: 2.2em; +} +button.ui-button-icon-only { + width: 2.4em; +} +.ui-button-icons-only { + width: 3.4em; +} +button.ui-button-icons-only { + width: 3.7em; +} +.ui-button .ui-button-text { + display: block; + line-height: normal; +} +.ui-button-text-only .ui-button-text { + padding: .4em 1em; +} +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { + padding: .4em; + text-indent: -9999999px; +} +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { + padding: .4em 1em .4em 2.1em; +} +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { + padding: .4em 2.1em .4em 1em; +} +.ui-button-text-icons .ui-button-text { + padding-left: 2.1em; + padding-right: 2.1em; +} +input.ui-button { + padding: .4em 1em; +} +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { + position: absolute; + top: 50%; + margin-top: -8px; +} +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; +} +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { + left: .5em; +} +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { + right: .5em; +} +.ui-buttonset { + margin-right: 7px; +} +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: -.3em; +} +input.ui-button::-moz-focus-inner, button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-dialog { + position: absolute; + top: 0; + left: 0; + outline: 0; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + background: 0 0; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-datepicker { + width: 17em; + padding: 5px 5px 0; + display: none; + background-color: #fff; + border: 1px solid #e1e1e1; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; + color: #444; +} +.ui-datepicker .ui-widget-header a { + color: #444; +} +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { + position: absolute; + top: 7px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 48px; + line-height: 1.8em; + color: #444; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month, .ui-datepicker select.ui-datepicker-year { + width: 49%} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: 700; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td span, .ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} +.ui-datepicker-today { + background-color: #eee1f8; +} +.ui-datepicker-current-day { + background-color: #4b9fd5; +} +.ui-datepicker-current-day a { + color: #fff; +} +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} +.ui-datepicker .ui-icon { + text-indent: 0; +} +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, .ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} +.select2-container { + position: relative; + display: inline-block; + zoom: 1; + *display: inline; + vertical-align: top; +} +.select2-container, .select2-drop, .select2-search, .select2-search input { + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -webkit-box-sizing: border-box; + -khtml-box-sizing: border-box; + box-sizing: border-box; +} +.select2-container .select2-choice { + background-color: #fff; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff)); + background-image: -webkit-linear-gradient(center bottom, #eee 0, #fff 50%); + background-image: -moz-linear-gradient(center bottom, #eee 0, #fff 50%); + background-image: -o-linear-gradient(bottom, #eee 0, #fff 50%); + background-image: -ms-linear-gradient(top, #eee 0, #fff 50%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); + background-image: linear-gradient(top, #eee 0, #fff 50%); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #aaa; + display: block; + overflow: hidden; + white-space: nowrap; + position: relative; + height: 26px; + line-height: 26px; + padding: 0 0 0 8px; + color: #444; + text-decoration: none; +} +.select2-container.select2-drop-above .select2-choice { + border-bottom-color: #aaa; + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff)); + background-image: -webkit-linear-gradient(center bottom, #eee 0, #fff 90%); + background-image: -moz-linear-gradient(center bottom, #eee 0, #fff 90%); + background-image: -o-linear-gradient(bottom, #eee 0, #fff 90%); + background-image: -ms-linear-gradient(top, #eee 0, #fff 90%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); + background-image: linear-gradient(top, #eee 0, #fff 90%); +} +.select2-container .select2-choice span { + margin-right: 26px; + display: block; + overflow: hidden; + white-space: nowrap; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + text-overflow: ellipsis; +} +.select2-container .select2-choice abbr { + display: block; + position: absolute; + right: 26px; + top: 8px; + width: 12px; + height: 12px; + font-size: 1px; + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") right top no-repeat; + cursor: pointer; + text-decoration: none; + border: 0; + outline: 0; +} +.select2-container .select2-choice abbr:hover { + background-position: right -11px; + cursor: pointer; +} +.select2-drop { + background: #fff; + color: #000; + border: 1px solid #aaa; + border-top: 0; + position: absolute; + top: 100%; + -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + -o-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + z-index: 9999; + width: 100%; + margin-top: -1px; + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.select2-drop.select2-drop-above { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; + margin-top: 1px; + border-top: 1px solid #aaa; + border-bottom: 0; + -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); + -moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); + -o-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); + box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); +} +.select2-container .select2-choice div { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + background: #ccc; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); + background-image: -webkit-linear-gradient(center bottom, #ccc 0, #eee 60%); + background-image: -moz-linear-gradient(center bottom, #ccc 0, #eee 60%); + background-image: -o-linear-gradient(bottom, #ccc 0, #eee 60%); + background-image: -ms-linear-gradient(top, #ccc 0, #eee 60%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#eeeeee', GradientType=0); + background-image: linear-gradient(top, #ccc 0, #eee 60%); + border-left: 1px solid #aaa; + position: absolute; + right: 0; + top: 0; + display: block; + height: 100%; + width: 18px; +} +.select2-container .select2-choice div b { + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 0 1px; + display: block; + width: 100%; + height: 100%} +.select2-search { + display: inline-block; + white-space: nowrap; + z-index: 10000; + min-height: 26px; + width: 100%; + margin: 0; + padding-left: 4px; + padding-right: 4px; +} +.select2-search-hidden { + display: block; + position: absolute; + left: -10000px; +} +.select2-search input { + background: #fff url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 100% -22px; + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 100% -22px, -o-linear-gradient(bottom, #fff 85%, #eee 99%); + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 100% -22px, -ms-linear-gradient(top, #fff 85%, #eee 99%); + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%); + padding: 4px 20px 4px 5px; + outline: 0; + border: 1px solid #aaa; + font-family: sans-serif; + font-size: 1em; + width: 100%; + margin: 0; + height: auto!important; + min-height: 26px; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + border-radius: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; +} +.select2-drop.select2-drop-above .select2-search input { + margin-top: 4px; +} +.select2-search input.select2-active { + background: #fff url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%; + background: url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); + background: url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%, -o-linear-gradient(bottom, #fff 85%, #eee 99%); + background: url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%, -ms-linear-gradient(top, #fff 85%, #eee 99%); + background: url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%); +} +.select2-container-active .select2-choice, .select2-container-active .select2-choices { + -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + -moz-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + -o-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + box-shadow: 0 0 5px rgba(0, 0, 0, .3); + border: 1px solid #5897fb; + outline: 0; +} +.select2-dropdown-open .select2-choice { + border: 1px solid #aaa; + border-bottom-color: transparent; + -webkit-box-shadow: 0 1px 0 #fff inset; + -moz-box-shadow: 0 1px 0 #fff inset; + -o-box-shadow: 0 1px 0 #fff inset; + box-shadow: 0 1px 0 #fff inset; + background-color: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee)); + background-image: -webkit-linear-gradient(center bottom, #fff 0, #eee 50%); + background-image: -moz-linear-gradient(center bottom, #fff 0, #eee 50%); + background-image: -o-linear-gradient(bottom, #fff 0, #eee 50%); + background-image: -ms-linear-gradient(top, #fff 0, #eee 50%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-image: linear-gradient(top, #fff 0, #eee 50%); + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 0; + -moz-border-radius-bottomleft: 0; + -moz-border-radius-bottomright: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.select2-dropdown-open .select2-choice div { + background: 0 0; + border-left: none; +} +.select2-dropdown-open .select2-choice div b { + background-position: -18px 1px; +} +.select2-results { + margin: 4px 4px 4px 0; + padding: 0 0 0 4px; + position: relative; + overflow-x: hidden; + overflow-y: auto; + max-height: 200px; +} +.select2-results ul.select2-result-sub { + margin: 0; +} +.select2-results ul.select2-result-sub>li .select2-result-label { + padding-left: 20px; +} +.select2-results ul.select2-result-sub ul.select2-result-sub>li .select2-result-label { + padding-left: 40px; +} +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label { + padding-left: 60px; +} +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label { + padding-left: 80px; +} +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label { + padding-left: 100px; +} +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label { + padding-left: 110px; +} +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub>li .select2-result-label { + padding-left: 120px; +} +.select2-results li { + list-style: none; + display: list-item; +} +.select2-results li.select2-result-with-children>.select2-result-label { + font-weight: 700; +} +.select2-results .select2-result-label { + padding: 3px 7px 4px; + margin: 0; + cursor: pointer; +} +.select2-results .select2-highlighted { + background: #3875d7; + color: #fff; +} +.select2-results li em { + background: #feffde; + font-style: normal; +} +.select2-results .select2-highlighted em { + background: 0 0; +} +.select2-results .select2-no-results, .select2-results .select2-searching, .select2-results .select2-selection-limit { + background: #f4f4f4; + display: list-item; +} +.select2-results .select2-disabled { + display: none; +} +.select2-more-results.select2-active { + background: #f4f4f4 url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%} +.select2-more-results { + background: #f4f4f4; + display: list-item; +} +.select2-container.select2-container-disabled .select2-choice { + background-color: #f4f4f4; + background-image: none; + border: 1px solid #ddd; + cursor: default; +} +.select2-container.select2-container-disabled .select2-choice div { + background-color: #f4f4f4; + background-image: none; + border-left: 0; +} +.select2-container-multi .select2-choices { + background-color: #fff; + background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eee), color-stop(15%, #fff)); + background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%); + background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%); + background-image: -o-linear-gradient(top, #eee 1%, #fff 15%); + background-image: -ms-linear-gradient(top, #eee 1%, #fff 15%); + background-image: linear-gradient(top, #eee 1%, #fff 15%); + border: 1px solid #aaa; + margin: 0; + padding: 0; + cursor: text; + overflow: hidden; + height: auto!important; + height: 1%; + position: relative; +} +.select2-container-multi .select2-choices { + min-height: 26px; +} +.select2-container-multi.select2-container-active .select2-choices { + -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + -moz-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + -o-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + box-shadow: 0 0 5px rgba(0, 0, 0, .3); + border: 1px solid #5897fb; + outline: 0; +} +.select2-container-multi .select2-choices li { + float: left; + list-style: none; +} +.select2-container-multi .select2-choices .select2-search-field { + white-space: nowrap; + margin: 0; + padding: 0; +} +.select2-container-multi .select2-choices .select2-search-field input { + color: #666; + background: transparent!important; + font-family: sans-serif; + font-size: 100%; + height: 15px; + padding: 5px; + margin: 1px 0; + outline: 0; + border: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; +} +.select2-container-multi .select2-choices .select2-search-field input.select2-active { + background: #fff url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e") no-repeat 100%!important; +} +.select2-default { + color: #999!important; +} +.select2-container-multi .select2-choices .select2-search-choice { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + background-color: #e4e4e4; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0); + background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee)); + background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05); + -moz-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05); + box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05); + color: #333; + border: 1px solid #aaa; + line-height: 13px; + padding: 3px 5px 3px 18px; + margin: 3px 0 3px 5px; + position: relative; + cursor: default; +} +.select2-container-multi .select2-choices .select2-search-choice span { + cursor: default; +} +.select2-container-multi .select2-choices .select2-search-choice-focus { + background: #d4d4d4; +} +.select2-search-choice-close { + display: block; + position: absolute; + right: 3px; + top: 4px; + width: 12px; + height: 13px; + font-size: 1px; + background: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619") right top no-repeat; + outline: 0; +} +.select2-container-multi .select2-search-choice-close { + left: 3px; +} +.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover { + background-position: right -11px; +} +.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close { + background-position: right -11px; +} +.select2-container-multi.select2-container-disabled .select2-choices { + background-color: #f4f4f4; + background-image: none; + border: 1px solid #ddd; + cursor: default; +} +.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice { + background-image: none; + background-color: #f4f4f4; + border: 1px solid #ddd; + padding: 3px 5px; +} +.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { + display: none; +} +.select2-result-selectable .select2-match, .select2-result-unselectable .select2-result-selectable .select2-match { + text-decoration: underline; +} +.select2-result-unselectable .select2-match { + text-decoration: none; +} +.select2-offscreen { + position: absolute; + left: -10000px; +} +@media (-webkit-min-device-pixel-ratio:2), (min-resolution:192dpi) { + .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b { + background-image: url("../images/select2x2.png?3edc3589b2afdcf04b18170ab6927ccb")!important; + background-repeat: no-repeat!important; + background-size: 60px 40px!important; +} +.select2-search input { + background-position: 100% -21px!important; +} +}.select2-container { + vertical-align: middle; +} +.select2-container .select2-choice { + height: 20px; + line-height: 20px; + border-color: #cdcdcd; + border-radius: 0; + background: #fff; + text-align: left; +} +.select2-container .select2-choice, .select2-container .select2-choices { + transition: border-color .2s ease; +} +.select2-container .select2-choice abbr { + top: 4px; +} +.select2-container .select2-choice div { + width: 19px; + border: none; + border-radius: 0; + background: #fff; +} +.select2-container .select2-choice div b { + top: 4px; + background-position: 1px -1px; +} +.select2-dropdown-open .select2-choice div b { + background-position: -17px -1px; +} +.select2-container-active .select2-choice, .select2-container-active .select2-choices { + border-color: #4b9fd5; + box-shadow: none; +} +.select2-dropdown-open .select2-choice { + box-shadow: none; +} +.select2-drop { + border-color: #cdcdcd; + border-radius: 0; +} +.select2-drop-active { + border-color: #4b9fd5; +} +.select2-dropdown-open.select2-drop-above .select2-choice, .select2-dropdown-open.select2-drop-above .select2-choices { + border-color: #4b9fd5; + border-radius: 0; + background: #fff; +} +.select2-drop.select2-drop-above.select2-drop-active { + border-color: #4b9fd5; + border-radius: 0; +} +.select2-drop.select2-drop-above .select2-search input { + margin-top: 0; +} +.select2-results { + margin: 0; + padding: 5px 0; + border-top: 1px solid #cdcdcd; +} +.select2-results .select2-result-label { + height: 20px; + line-height: 20px; + padding: 0 8px; + color: #444; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.select2-results .select2-no-results, .select2-results .select2-searching, .select2-results .select2-selection-limit, .select2-more-results.select2-active { + height: 20px; + line-height: 20px; + padding: 0 10px; +} +.select2-results .select2-highlighted { + background: 0 0; + color: #444; +} +.select2-results .select2-highlighted .select2-result-label { + background: #e2e2e2; +} +.select2-search { + padding: 4px; +} +.select2-search input { + height: 20px; + padding: 0 7px; + border-color: #cdcdcd; + background: #fff!important; +} +.select2-container-multi .select2-choices { + min-height: 19px; + padding-bottom: 1px; + border-color: #cdcdcd; + background: #fff; +} +.select2-container-multi.select2-container-active .select2-choices { + border-color: #4b9fd5; + box-shadow: none; +} +.select2-container-multi .select2-choices .select2-search-field input { + height: 16px; + padding: 0 3px; +} +.select2-container-multi .select2-choices .select2-search-choice { + margin: 1px 1px 0; + padding: 1px 5px 2px 18px; + border-radius: 0; + border-color: #cdcdcd; + background: #efefef; + box-shadow: none; +} +.select2-search-choice-close { + top: 2px; +} +.select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b { + background-image: url("../images/select2.png?829f9832d7c5fec528fe4119377a8619"); +} +.select2-search input.select2-active, .select2-more-results.select2-active, .select2-container-multi .select2-choices .select2-search-field input.select2-active { + background-image: url("../images/spinner.gif?5725ac941d218f159a383774f1e09a0e"); +} +@media (-webkit-min-device-pixel-ratio:2), (min-resolution:192dpi) { + .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b { + background-image: url("../images/select2x2.png?3edc3589b2afdcf04b18170ab6927ccb")!important; +} +}@media print { + html, body { + font-size: 8pt; +} +a, a:link, a:visited { + text-decoration: none; + border-bottom: 0; +} +.noprint { + display: none!important; +} +.print { + display: inline; + position: static; + left: 0; +} +#hd, #sidebar, #crumbs { + display: none; +} +.with_sidebar, .wo_sidebar { + padding: 0!important; + margin: 0; +} +#content { + margin-left: 0!important; +} +}@media screen { + .print { + display: none; +} +}body, a { + color: #444; +} +#container { + height: auto!important; + min-width: 940px; + min-height: 500px; +} +#hd { + color: #FFF; + background: #262626; + padding: 0 10px; + height: 30px; + line-height: 30px; + font-size: 93%; + margin: 0; + position: relative; +} +#hd #nav-left>ul>li { + height: 30px; +} +#hd a { + color: #fff; + border-bottom: none; +} +#hd a.selected, #hd a:hover, #hd a:focus { + color: #4b9fd5; +} +#nav-left { + float: left; + vertical-align: middle; +} +#nav { + float: right; + padding: 0 0 0 20px; + vertical-align: middle; +} +#nav-left img, #nav img { + vertical-align: text-bottom; +} +#nav-left>ul>li { + float: left; + padding: 0 20px 0 0; +} +#nav-left>ul>li>a, #nav>ul>li>a { + font-size: 12px; + font-weight: 300; + letter-spacing: .05em; +} +#nav>ul>li { + float: right; + height: 30px; + padding: 0 0 0 15px; +} +#searchResourcesResults { + position: absolute; + float: right; + width: 600px; + top: 30px; + right: 0; +} +#crumbs { + color: #444; + background: #EFEFEF; + height: 26px; + line-height: 26px; + font-size: 93%; + margin: 0; + padding: 0 10px; + border-bottom: 1px solid #CCC; +} +#crumbs img { + vertical-align: text-bottom; +} +#bc li { + float: left; + background: #efefef url("../images/bc-gray.png?6ec133698d492b4ad1f227aba4d6fe03") no-repeat right; + border-bottom: 1px solid #CCC; + padding: 0 20px 0 0; + margin: 0 10px 0 0; +} +#bc li img { + margin-right: -5px; +} +#bc li a { + border-bottom: none; +} +#crumbs-ops { + float: right; + padding: 0 5px 0 0; +} +#crumbs-ops li { + float: left; + padding: 0 0 0 10px; +} +#crumbs-ops li a { + border-bottom: none; +} +#hd .dropdown-menu a { + color: #000; +} +#project-settings-menu { + float: right; + right: 20px; +} +#nonav { + text-align: left; + margin: 50px 180px 0; +} +#footer { + padding: 4px 0; + clear: both; +} +#body { + position: relative; +} +.with_sidebar { + margin: 0 0 0 160px; + padding: 10px; +} +.wo_sidebar { + margin: 0 8px; +} +#sidebar { + position: absolute; + top: 0; + left: 10px; + width: 150px; +} +#sidebar.sticky { + position: fixed; +} +ul.sidebar { + text-align: left; + border-top: none; + padding: 10px 0; +} +ul.sidebar li { + list-style-type: none; + padding: 3px 10px; +} +ul.sidebar li>a { + border-bottom: none; +} +ul.sidebar li.active { + background-color: #4b9fd5; +} +ul.sidebar li.active a, ul.sidebar li.active a:hover { + color: #FFF; +} +ul.sidebar li.active [class^=icon-], ul.sidebar li.active [class*=" icon-"] { + color: #FFF; +} +li.sidebar-title { + text-transform: uppercase; + font-size: 93%; + font-weight: 700; +} +ul.sidebar li.spacer { + border: 0 none; + height: 10px; + margin: 0; + padding: 0; +} +ul.sidebar select, ul.sidebar input { + font-size: 93%} +#logo { + text-align: center; + padding: 10px 0 0; +} +#logo a { + text-decoration: none; + border-bottom-width: 0; +} +#logo img { + display: block; +} +.page { + padding: 10px; +} +.page-split-left { + min-width: 200px; + max-width: 200px; + width: 200px; + margin: 0; + display: block; + vertical-align: top; + border-top: none; + border-left: none; + float: left; +} +.page-split-right { + display: block; + margin: 0; + vertical-align: top; + padding: 0 0 0 200px; +} +.gray-sidebar { + background-color: #EFEFEF; + border: 1px solid #CCC; + color: #666; + border-top: none; +} +.blue-sidebar { + height: 100%; + border-left: 1px solid #4b9fd5; + border-right: 1px solid #4b9fd5; + border-bottom: 1px solid #4b9fd5; + background-color: #cae3f2; + color: #444; +} +.nolayout { + padding: 10px; +} +#projectSearch { + color: #444; + margin: 4px 0 0; +} +#ftlinks { + background: #fff; + color: #262626; + text-align: center; + border-top: 1px solid #fff; + font-size: 85%; + padding: 10px 0; + line-height: 1.4; +} +.ie-warn { + color: #EEE; + background: #FF5252; + padding: 0 5px; +} +.ie-warn a { + color: #EEE; + text-decoration: underline; +} +a { + cursor: pointer; +} +a.icon-favorite, a.icon-not-favorite { + border-bottom: none; +} +.loading { + background: url("../images/loading.gif?e2a9308e1360f28fb8fe7ad05eed2e38") no-repeat 4px 2px; + color: #444; + padding: 3px 25px; +} +.right { + text-align: right; +} +.left { + text-align: left; +} +.center { + text-align: center; +} +.top { + vertical-align: top; +} +.bottom { + vertical-align: bottom; +} +.middle { + vertical-align: middle; +} +.nowrap { + white-space: nowrap; +} +code { + font-size: 93%} +.hidden { + display: none; + visibility: hidden; +} +.clear { + height: 0; + clear: both; +} +.note { + color: #777; + font-size: 93%; + font-weight: 400; + line-height: 13px; +} +.note img { + vertical-align: bottom; +} +.crossout { + text-decoration: line-through; +} +.small { + font-size: 12px; +} +small { + color: #AAA; + font-size: 85%; + font-style: normal; +} +em { + font-weight: 700; +} +em.mandatory { + color: #900; + font-style: italic; +} +a.external { + background: url("../images/links/external.png?c4631db232b81958abf720e423de13b1") no-repeat 100% 0; + padding: 0 16px 0 0; +} +.fav { + display: inline-block; + background: url("../images/star.png?d9e2d314eea5020e5f8f8490e74bbd7a") no-repeat 100% 0; + width: 16px; + height: 16px; + vertical-align: text-bottom; +} +.notfav { + display: inline-block; + background: url("../images/star_off.png?ac5da9e28e8bb5b3aa06b60c69bd6029") no-repeat 100% 0; + width: 16px; + height: 16px; + vertical-align: text-bottom; +} +.red-button { + color: #900!important; +} +.red-button:hover { + color: #FFF!important; + border: solid 1px #CD504A!important; + background: #B33630!important; + background: -webkit-gradient(linear, left top, left bottom, from(#dc5f59), to(#b33630))!important; + background: -moz-linear-gradient(top, #dc5f59, #b33630)!important; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#DC5F59', endColorstr='#B33630')!important; +} +.red-button:active { + color: #FFF!important; + border: solid 1px #CD504A!important; + background: #B33630!important; + background: -webkit-gradient(linear, left top, left bottom, from(#ac2f29), to(#d35650))!important; + background: -moz-linear-gradient(top, #ac2f29, #d35650)!important; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#AC2F29', endColorstr='#D35650')!important; +} +.red-button[disabled] { + position: relative; + top: 0; + text-shadow: 1px 1px 0 #FFF; + color: #BBB; + border: solid 1px #DDD; + background: #EBEBEB; + background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e1e1e1)); + background: -moz-linear-gradient(top, #fff, #e1e1e1); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#E1E1E1'); + cursor: default; +} +h1, .h1 { + color: #444; + font-size: 16px; +} +h2, .h2 { + color: #444; + font-size: 16px; + font-weight: 400; +} +h3, .h3 { + color: #444; + font-size: 100%; + font-weight: 700; +} +h4, .h4 { + color: #444; + font-size: 85%; + color: #777; +} +h1 img, .h1 img, h2 img, .h2 img, h3 img, .h3 img, h4 img, .h4 img { + vertical-align: middle; +} +.subtitle { + color: #777; + font-size: 85%; + margin: 0; + padding: 0; +} +.notes { + color: #777; + font-size: 11px; + margin-bottom: 10px; + background-color: #EFEFEF; + border: 1px solid #cdcdcd; + line-height: 16px; + height: 16px; + padding: 2px 4px; +} +.treemap { + position: relative; + cursor: pointer; +} +.treemap a { + color: #FFF; + text-decoration: none; + font-size: 12px; + padding: 1px; +} +.treemap a:hover { + text-decoration: underline; +} +.warning, .modal-warning { + border: solid 1px #FFD324; + background-color: #FFF6BF; + color: #514721; + margin: 0 0 4px; + padding: 4px; +} +.error, .modal-error { + border: 1px solid red; + background-color: #FF5252; + color: #eee; + margin: 0 0 4px; + padding: 4px; +} +.error a, .modal-error a { + color: #eee; +} +.notice, .modal-notice { + border: 1px solid #9c9; + background-color: #e2f9e3; + color: #060; + margin: 0 0 4px; + padding: 4px; +} +.info { + background-color: #CAE3F2; + padding: 5px; + border: 1px solid #4B9FD5; +} +.migration { + background-image: url("../images/logo.png?c37a88b91098aeae04bcfdf3b4388837"); + background-repeat: no-repeat; + background-position: top right; +} +#login_form { + border: 2px solid #4b9fd5; + width: 230px; + text-align: left; + background-color: #CAE3F2; + padding: 15px 20px; +} +#login_form h4 { + text-align: left; + font-weight: 700; + color: #036; +} +#login_form p { + padding: 3px 0 10px; +} +#login_form a { + border-bottom-color: #4b9fd5; +} +#login_form .desc { + font-size: 85%; + font-weight: 400; +} +.doc h2 { + margin-top: 8px; +} +.doc p { + margin: 8px 0; +} +.doc pre, pre.code { + color: #777; + background-color: #EFEFEF; + padding: 10px; + margin: 10px 0; + border: 1px dashed #777; + font-size: 93%; + line-height: 1.5em; +} +.doc li { + list-style: disc outside; + padding: 2px; +} +.doc ul { + list-style: none outside; + padding-left: 30px; +} +.odd { + background-color: #fff; +} +.odd.selected, .even.selected, .odd.selected a, .even.selected a, .even.selected span, .odd.selected span { + background-color: #cae3f2; + color: #444; +} +table.data>thead>tr>th { + vertical-align: top; + font-size: 93%; + padding: 4px 7px 4px 3px; + line-height: 1.4; + text-transform: uppercase; +} +table.data>thead>tr>th>.small { + text-transform: none; +} +table.data>tfoot>tr>td { + font-size: 93%; + color: #777; + padding: 5px; +} +table.data>tbody>tr>td { + padding: 5px; + vertical-align: text-top; +} +table.data td.small, table.data th.small { + padding: 0; + white-space: nowrap; +} +table.data th img, table.data td img { + vertical-align: sub; +} +table.data.zebra tbody tr:nth-child(odd) { + background-color: #f5f5f5; +} +.data thead tr.total { + background-color: #EFEFEF; + font-weight: 400; + border: 1px solid #DDD; +} +.data thead tr.total th { + font-weight: 400; +} +.data thead tr.blank { + background-color: #fff; + line-height: 15px; +} +.data tr.highlight { + background-color: #cae3f2; +} +.data input, .data select, .data button { + vertical-align: baseline; +} +.data td.category { + padding-right: 15px; +} +.categoryDescription { + padding: 10px 5px; +} +.data td.category.withSubcategories { + background-image: url("../images/bullet_arrow_down.gif?1c3bb7944d54b3f1bfdb8afb824ace93"); + background-position: right center; + background-repeat: no-repeat; +} +.data td.subcategory { + padding-left: 20px; +} +.hoverable:hover { + background-color: #CAE3F2; +} +.hoverable:hover a { + color: #111; +} +table.sortable .sortcol { + cursor: pointer; + padding-left: 15px; + background-repeat: no-repeat; + background-position: right center; +} +table.sortable .sortasc { + background-image: url("../images/bullet_arrow_up.gif?09792aedf077cad45ba64d5c07ac339c"); + background-position: left center; +} +table.sortable .sortdesc { + background-image: url("../images/bullet_arrow_down.gif?1c3bb7944d54b3f1bfdb8afb824ace93"); + background-position: left center; +} +table.sortable .righticon { + padding-right: 15px; + background-position: right center; +} +table.sortable .nosort { + cursor: default; +} +table.spaced th { + font-weight: 700; + color: #333; + padding: 4px 5px; +} +table.spaced td, table.matrix tfoot td { + padding: 3px 5px; + line-height: 18px; +} +table.spaced td img { + vertical-align: text-bottom; +} +table.spacedicon th { + font-weight: 700; + color: #333; + padding: 4px 5px; +} +table.spacedicon td { + padding: 0 5px; + height: 24px; +} +.thin { + width: 1%} +td.sep { + width: 10px; +} +.spacer { + width: 5px; + display: inline-block; +} +.formError { + display: inline-block; + background-color: #FF9090; + color: #000; + padding: 0 5px; +} +table.form td { + padding: 2px 5px; + vertical-align: top; +} +table.form td.keyCell { + width: 1%; + white-space: nowrap; + text-align: right; + font-weight: 700; + vertical-align: top; +} +table.form td img { + vertical-align: bottom; +} +.admin hr { + background: 0 0; + border-left: none; + border-right: none; + border-top: none; + border-bottom: 1px dashed #FFD324; + height: 1px; +} +table#project-history tr>td { + vertical-align: top; +} +#page-operations { + display: inline-block; + width: 100%} +div.operations { + float: right; + margin: 0; +} +ul.operations { + float: right; + height: 20px; + line-height: 20px; + list-style-type: none; + margin: 0; + background-color: #EFEFEF; + border: 1px solid #cdcdcd; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} +ul.operations li { + float: left; + margin: 0; + padding: 0 8px; + font-size: 85%; + border-right: 1px solid #cdcdcd; +} +ul.operations li.selected { + background-color: #d4d4d4; +} +ul.operations li.last { + border-right-width: 0; +} +ul.operations li a { + color: #444; + outline: 0; + text-decoration: none; + transition: all .2s ease; + color: #555; +} +ul.operations li a:hover { + color: #4b9fd5; +} +ul.operations li a:active, ul.operations li a:focus { + color: #236a97; +} +ul.operations li img { + vertical-align: middle; + margin-right: 5px; +} +th.operations, td.operations { + text-align: right; +} +.resourceName h1 { + margin: 5px 0; +} +.sources2 { + width: 100%; + border: 0; + margin: 0; + background-color: #FFF; +} +.sources2 td.lid { + background-color: #EFEFEF; + border-right: 1px solid #DDD; + text-align: right; + padding: 2px .5em 0; + vertical-align: top; + font-size: 85%} +.sources2 td.lid a { + text-decoration: none; + color: #AAA; +} +.sources2 td.scm { + border-right: 1px solid #DDD; + background-color: #EFEFEF; +} +.sources2 td.revision { + border-top: 1px solid #DDD; + vertical-align: top; + padding: 0 .3em; + white-space: nowrap; +} +.sources2 tr:first-child td.revision { + border-top: none; +} +.sources2 tr.row td.plus { + background-color: #EFEFEF; + padding: 0; + width: 16px; +} +.sources2 tr.row:hover td.plus { + background: url("../images/add.png?4ea982641458a260ca3bc0575b5c687e") no-repeat scroll left 0 #efefef; +} +.sources2 td.plus a { + display: block; + cursor: pointer; + height: 16px; + width: 16px; +} +.sources2 td.gray { + background-color: #EFEFEF; + padding: 2px .5em 0; +} +.sources2 td.white { + border-left: 1px solid #DDD; + background-color: #FFF; +} +.sources2 span.date, .sources2 span.date a { + color: #AAA; + font-size: 85%; + text-decoration: none; +} +.sources2 span.author, .sources2 span.author a { + font-size: 85%} +.sources2 div.violation, #global_violations div.violation { + background-color: #FFF; + margin: 0; + border: 1px solid #DDD; + font-size: 12px; +} +.rulename, .rulename a { + color: #444; + font-weight: 700; +} +.rulename a:hover { + text-decoration: underline; +} +.sources2 td.line { + width: 100%} +.sources2 td.line pre { + font-size: 12px; + font-family: monospace; +} +.sources2 td.ind { + border-right: 1px solid #DDD; + padding: 0 .3em; + text-align: center; + vertical-align: middle; +} +.sources2 td.ind a, .sources2 td.ind span { + padding: 0 3px; +} +.sources2 td.ok { + background-color: #ACE97C; +} +.sources2 td.warn { + background-color: #FFF6BF; +} +.sources2 td.ko { + background-color: #FF9090; +} +.sources2 td.new_section { + border-width: 1px 0; + border-style: solid; + border-color: #EEE #DDD; + height: 30px; + background: url("../images/gray-stripes.png?c0affd395b7ae52801fcae4cbc50fd81"); +} +.sources2 td.violations { + background-color: #FFF; + padding: 10px; + border-left: 1px solid #DDD; +} +.source_title { + padding: 10px 5px; +} +.source_title span.h1 { + font-size: 16px; + margin-right: 10px; +} +.source_links { + font-size: 11px; +} +.global_violations { + width: 100%} +.global_violations>tbody>tr>td { + padding-bottom: 10px; +} +.global_violations td { + padding: 3px 0; +} +.global_violations td img, #source_title img { + vertical-align: text-bottom; +} +.code-issue-create-form { + padding: 10px; +} +.code-global-issues { + padding: 10px 10px 0; +} +.code-issues { + padding: 10px 10px 0; + line-height: 0; +} +.code-issue { + margin: 0; + font-size: 12px; + padding: 0 0 10px; + transition: border-color .2s ease; +} +.code-issue .error { + line-height: normal; +} +.code-issue strong { + font-weight: 700; +} +.code-issue-toggle { + cursor: pointer; +} +.code-issue-name { + position: relative; + background-color: #E4ECF3; + margin: 0; + padding: 5px 10px; + line-height: 16px; + color: #777; + border: 1px solid #DDD; + border-bottom: medium none; +} +.code-issue-msg { + line-height: 1.5; + padding: 5px 10px; + border-left: 1px solid #DDD; + border-right: 1px solid #DDD; + background-color: #EFEFEF; +} +.code-issue-name img { + vertical-align: text-bottom; +} +.code-issue-name-rule { + max-width: 90%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.code-issue-permalink { + position: absolute; + top: 4px; + right: 4px; +} +.code-issue-permalink a { + text-decoration: none; +} +.code-issue-name-extra { + margin-top: 6px; + line-height: 12px; +} +.code-issue-name-extra li { + font-size: 11px!important; +} +.code-issue-name-right { + position: absolute; + top: 5px; + right: 26px; +} +.code-issue-comment, .code-issue-msg, .code-issue-actions, .code-issue-form { + background-color: #EFEFEF; + border: 1px solid #DDD; + border-top: none; + line-height: 1.5em; + margin: 0; + padding: 5px 10px; +} +.code-issue-form input[type=submit], .code-issue-form input[type=button], .code-issue-form button, .code-issue-form .action { + vertical-align: middle; +} +.code-issue-comment h4 { + font-size: 11px; + margin-bottom: 2px; +} +.code-issue-comment h4 img { + vertical-align: sub; +} +.code-issue-comment ul li { + list-style: square inside; +} +.code-issue-comment ol li { + list-style: decimal inside; +} +.code-issue-comment pre { + padding: 10px; + border: 1px dashed #DDD; + color: #444; + font-size: 12px; +} +.code-issue-details { + padding: 0 10px 5px; + border-left: 1px solid #DDD; + border-right: 1px solid #DDD; + border-bottom: 1px solid #DDD; + background-color: #EFEFEF; + line-height: 1.3; +} +.code-issue-tabs { + margin-bottom: 5px; + font-size: 0; +} +.code-issue-tabs>li { + display: inline-block; + padding: 4px 0; + color: #777; + font-size: 12px; +} +.code-issue-tabs>li+li { + margin-left: 15px; +} +.code-issue-details-list>li { + font-size: 0; +} +.code-issue-details-term, .code-issue-details-value { + display: inline-block; + vertical-align: top; + font-size: 12px; + line-height: 20px; +} +.code-issue-details-term { + width: 90px; +} +.code-issue-details-term:after { + content: ":"} +.code-issue-list { + background-color: #E4ECF3; +} +.code-issue-bar, .code-issue-list { + font-size: 0; + white-space: nowrap; +} +.code-issue-list>li, .code-issue-bar>li { + display: inline-block; + vertical-align: middle; + height: 14px; + line-height: 14px; + padding: 0 8px; + border-left: 1px solid #fff; + border-right: 1px solid #bfbfbf; + font-size: 12px; +} +.code-issue-list>li:first-child, .code-issue-bar>li:first-child { + padding-left: 0; + border-left: none; +} +.code-issue-list>li:last-child, .code-issue-bar>li:last-child { + padding-right: 0; + border-right: none; +} +.code-issue-collapsed .code-issue-msg, .code-issue-collapsed .code-issue-details { + display: none; +} +.code-issue-errors { + margin-top: 10px; +} +.tab_header { + padding: 5px 10px; +} +.tab_header td { + padding-right: 7px; +} +.tab_header td.name { + text-align: left; + white-space: nowrap; +} +.tab_header td.value { + text-align: right; + white-space: nowrap; + font-weight: 700; +} +.extension-close { + position: absolute; + top: 5px; + right: 10px; +} +.source_options { + margin-top: 5px; + padding-top: 5px; + border-top: 1px solid #ddd; + font-size: 85%} +.source_options td { + background: url("../images/sep12.png?34e9868dc63be6f09690aa30ea1397d8") no-repeat scroll 0 50% transparent; + padding: 0 10px; +} +.source_options td.first { + background: 0 0; + padding: 0 10px 0 0; +} +.duplications { + max-width: 100%} +.duplications td.item { + text-align: right; + vertical-align: top; + padding: 0; +} +.duplications td.item p { + padding: 3px 5px; +} +.duplications td.fileItem { + text-align: left; + vertical-align: top; + padding: 0; + white-space: nowrap; +} +.duplications td.fileItem p { + padding: 3px 5px; +} +.duplications td.item p.selected, .duplications td.fileItem p.selected { + background-color: #EFEFEF; + border-top: 1px solid #DDD; + border-bottom: 1px solid #DDD; + padding: 3px 5px; +} +.duplications td.fileItem p.selected a { + text-decoration: none; +} +.duplications td.sourceItem { + padding: 0; + background-color: #EFEFEF; + border: 1px solid #DDD; + border-left: none; +} +.duplications td.sourceItem p { + padding: 3px; +} +.duplicationsMessage { + padding: 10px; +} +.discussion { + width: 100%; + border: 1px solid #DDD; +} +.discussionComment.first { + border-top: none; +} +.discussionComment { + background-color: #EFEFEF; + border-top: 1px solid #DDD; + line-height: 1.5em; + margin: 0; + padding: 5px 10px; +} +.discussionComment h4 { + font-size: 90%; + margin-bottom: 2px; +} +.discussionComment h4 img { + vertical-align: sub; +} +.discussionComment ol li { + list-style: decimal inside; +} +.discussionComment ul li { + list-style: square inside; +} +.discussionComment pre { + padding: 10px; + border: 1px dashed #DDD; + color: #444; + font-size: 12px; +} +div.comment-excerpt { + background-color: transparent; + margin-top: 5px; + margin-bottom: 5px; + color: #777; + font-size: 90%} +table.actionPlans { + margin-top: 10px; +} +table.actionPlans td.progress { + width: 300px; + padding: 0 40px; +} +table.actionPlans td.noprogress { + color: #777; + font-size: 93%; + padding-left: 43px; + padding-right: 40px; +} +table.actionPlans td.over-due { + color: #C00; + font-weight: 700; +} +div.progress { + width: 100%; + margin: 4px; +} +div.progress table { + width: 100%} +div.progress td { + height: 10px; +} +div.progress td a { + display: block; + width: 100%; + height: 100%} +div.progress td.resolved { + background-color: #078C00; +} +div.progress td.open { + background-color: #C00; +} +div.progress div.note { + color: #777; + font-size: 93%; + font-weight: 400; + white-space: nowrap; +} +div.note a { + color: #777; +} +#searchInput { + color: #444; + font-size: 13px; + padding-right: 20px; +} +#searchingResources { + position: absolute; + top: 8px; + right: 18px; +} +div.autocomplete { + position: absolute; + width: 600px; + right: 10px; + top: 10px; + background-color: #fff; + border: 1px solid #ccc; + margin: 0; + padding: 0; + color: #111; + line-height: 18px; + box-shadow: 10px 10px 20px rgba(0, 0, 0, .5); + z-index: 999999; +} +div.autocomplete ul { + list-style-type: none; + margin: 0; + padding: 0; +} +div.autocomplete ul li { + list-style-type: none; + display: block; + margin: 0; + padding: 3px 5px; + cursor: pointer; + color: #333; + line-height: 18px; + height: 18px; + vertical-align: middle; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +div.autocomplete div.q { + font-size: 93%; + color: #777; + width: 90px; + text-align: right; + margin-right: 5px; + display: inline-block; + zoom: 1; + *display: inline; +} +div.autocomplete ul li img { + vertical-align: middle; +} +div.autocomplete ul li.selected { + background-color: #cae3f2; +} +div.autocomplete strong { + font-weight: 700; +} +div.autocompleteNote { + color: #777; + font-size: 85%; + background-color: #EFEFEF; + border-top: 1px solid #CCC; + padding: 1px 10px; +} +#gwtpage { + width: 100%} +.gwt-SourcePanel { + font-size: 12px; + background-color: #fff; + border-top: 1px solid silver; + border-bottom: 1px solid silver; + width: 100%} +.gwt-SourcePanel .ln { + background-color: #EFEFEF; + white-space: nowrap; + text-align: right; + font-size: 85%; + color: #AAA; + border-right: 1px solid #DDD; + padding: 0 3px; + height: 14px; +} +.gwt-SourcePanel .src { + padding: 0 5px; + height: 14px; +} +.gwt-SourcePanel .val { + background-color: #EFEFEF; + border-right: 1px solid #DDD; + text-align: right; + color: #777; + padding: 0 3px; + height: 14px; + white-space: nowrap; +} +.gwt-SourcePanel .red { + background-color: #F0C8C8; +} +.gwt-SourcePanel .orange { + background-color: #FFF6BF; + color: #514721; +} +.gwt-SourcePanel .green { + background-color: #ACE97C; +} +.gwt-SourcePanel .msg { + font-family: sans-serif; + vertical-align: top; + padding: 3px 0; + height: 1.3em; + background-position: 5px 1px; + background-repeat: no-repeat; +} +.gwt-SourcePanel .bigln { + font-family: sans-serif; + vertical-align: top; + padding: 3px 0; + height: 1.6em; + background-position: 5px 1px; + background-repeat: no-repeat; + background-color: #EFEFEF; +} +.gwt-SourcePanel .warn { + font-family: sans-serif; + vertical-align: top; + background-color: #FFFFC9; + border: 1px solid #DCDCDC; + border-top: none; + color: #000; + line-height: 1.6em; + margin: 0; + padding: 0 0 2px 5px; +} +.gwt-SourcePanel .msg.error { + background-image: url("../images/exclamation.png?ce271080701989135bfe2211fc44bb52"); +} +.gwt-SourcePanel .msg.warning { + background-image: url("../images/warning.png?afd11ba47b28942073cdc83be5f9a585"); +} +.gwt-SourcePanel .msg.BLOCKER { + padding: 1px 5px 1px 25px; + background-image: url("../images/priority/BLOCKER.gif?c949e4e4fcd27032b9293b5e10f42712"); + background-color: #FF5252; + color: #eee; + border: 1px solid red; + margin: 1px 0 1px 5px; + height: 100%} +.gwt-SourcePanel .msg.CRITICAL { + padding: 1px 5px 1px 25px; + background-image: url("../images/priority/CRITICAL.gif?f206a6d8f76787e9a2fee6b20d1b08ab"); + background-color: #FF5252; + color: #eee; + border: 1px solid red; + margin: 1px 0 1px 5px; + height: 100%} +.gwt-SourcePanel .msg.MAJOR { + padding: 1px 5px 1px 25px; + background-image: url("../images/priority/MAJOR.gif?03a144017ac15577a0689992f310e5d3"); + background-color: #FF5252; + color: #eee; + border: 1px solid red; + margin: 1px 0 1px 5px; + height: 100%} +.gwt-SourcePanel .msg.MINOR { + padding: 1px 5px 1px 25px; + background-image: url("../images/priority/MINOR.gif?7c6095fa30e19e007c8e6d77dddfddbc"); + background-color: #FFF6BF; + border: 1px solid #FFD324; + margin: 1px 0 1px 5px; + height: 100%} +.gwt-SourcePanel .msg.INFO { + padding: 1px 5px 1px 25px; + background-image: url("../images/priority/INFO.gif?5ea2d33455a15853170a173ab42ac437"); + background-color: #FFF6BF; + border: 1px solid #FFD324; + margin: 1px 0 1px 5px; + height: 100%} +.gwt-ViewerHeader { + background-color: #EFEFEF; + border: 1px solid #DDD; + border-top: none; + margin-bottom: 8px; + color: #333; + vertical-align: bottom; +} +.gwt-ViewerHeader .metric { + padding: 8px 2px 5px 10px; + font-size: 93%; + text-align: right; + font-weight: 700; +} +.gwt-ViewerHeader .value { + padding: 8px 15px 5px 2px; + font-size: 93%; + text-align: left; + font-weight: 400; +} +.gwt-ViewerHeader .cell { + padding: 3px 10px; +} +.gwt-ViewerHeader .big { + padding: 4px 10px 2px; + font-size: 152%; + font-weight: 700; +} +.page_title { + margin: 0 0 7px; +} +.color_OK { + border: 2px solid #85bb43!important; + color: #85bb43!important; +} +.color_WARN { + border: 2px solid #f90!important; + color: #f90!important; +} +.color_ERROR { + border: 2px solid #d4333f!important; + color: #d4333f!important; +} +#alerts_widget { + margin-bottom: 10px; + padding: 5px 5px 5px 10px; +} +#alerts_widget img { + vertical-align: bottom; +} +span.empty_widget { + color: #777; + font-size: 93%} +.dashbox { + float: left; + vertical-align: top; + text-align: left; + padding: 0 10px 7px 0; +} +.dashbox h3 { + line-height: 1.2; + font-size: 16px; + font-weight: 300; +} +.dashbox a { + color: #236a97; + outline: 0; + text-decoration: none; + transition: all .2s ease; + border-bottom: 1px solid #cae3f2; +} +.dashbox a:hover { + color: #4b9fd5; +} +.dashbox a:active, .dashbox a:focus { + color: #236a97; +} +.dashbox a .rating { + color: #fff; +} +.big { + font-size: 152%; + font-weight: 700; +} +.adminportlet { + border: 2px dashed #ccc; + margin-bottom: 10px; + padding: 10px; +} +table.header1 { + background-color: #EFEFEF; + color: #444; + border: 1px solid #DDD; + margin: 0 0 10px; + width: 100%} +table.header1 td { + padding: 10px 0 10px 10px; + text-align: left; + vertical-align: top; +} +.headerLine { + background-color: #EFEFEF; + color: #444; + border: 1px solid #DDD; + margin: 0 0 10px; + line-height: 28px; + height: 28px; +} +ul.headerLine li { + float: left; + display: block; + padding: 0 10px; + height: 28px; + vertical-align: middle; +} +ul.headerLine li.sep { + background: url("../images/sep12.png?34e9868dc63be6f09690aa30ea1397d8") no-repeat scroll 50% 50% transparent; + padding: 0 5px; +} +ul.headerLine select, ul.headerLine input, ul.headerLine button, ul.headerLine textarea, ul.headerLine span { + vertical-align: middle; +} +select.withIcons option, span.withIcons { + background-repeat: no-repeat; + background-position: 2px 0; + padding: 0 2px 0 22px; + vertical-align: middle; +} +option.status_open { + background-image: url("../images/status/OPEN.png?93470244b51797cb5c435a34167b05b6"); +} +option.status_reopened { + background-image: url("../images/status/REOPENED.png?510859cfbda0d26c7cab6e9f1cc79ebc"); +} +option.status_resolved { + background-image: url("../images/status/RESOLVED.png?869f86bf2642e99417689f4a5a94670b"); +} +option.status_closed { + background-image: url("../images/status/CLOSED.png?60be2fa5dd39904af6532bf57a6c0a60"); +} +option.sev_INFO, span.sev_INFO { + background-image: url("../images/priority/INFO.png?092726fdd9e95ac273b6d7f54d0eddbe"); +} +option.sev_MINOR, span.sev_MINOR { + background-image: url("../images/priority/MINOR.png?e0c036e9432170fe7e3f298fcec2eef6"); +} +option.sev_MAJOR, span.sev_MAJOR { + background-image: url("../images/priority/MAJOR.png?bc3cfc6c0a0dc1a51a19feb96afd837e"); +} +option.sev_CRITICAL, span.sev_CRITICAL { + background-image: url("../images/priority/CRITICAL.png?ed0c398b4ff5e18fbeee90f7d81c5741"); +} +option.sev_BLOCKER, span.sev_BLOCKER { + background-image: url("../images/priority/BLOCKER.png?9fb61c8155cd5dbcf54afa837cc33269"); +} +.var { + color: #444!important; +} +.varb { + color: #85bb43!important; +} +.varw { + color: #d4333f!important; +} +.help { + border: 1px solid #DDD; + background-color: #EFEFEF; + color: #444; + padding: 5px; +} +.help h2 { + padding-left: 23px; + color: #444; + vertical-align: bottom; + font-weight: 700; + background: url("../images/information.png?441b7712b4c687fd869663595f2d2841") no-repeat left center; +} +.help p { + padding: 5px 0; +} +.inline-help { + padding: 5px; + margin: 5px; + background-color: #FFF6BF; + border: 1px solid #FFD324; +} +.admintable { + border: solid 1px #FFD324; + background-color: #FFF6BF; + color: #111; +} +.admintable td { + padding: 5px 10px; +} +.admintable span.desc { + font-size: 85%; + font-weight: 400; +} +.box { + border: 1px solid #ccc; + background-color: #EFEFEF; + margin-bottom: 5px; + color: #444; + padding: 10px; +} +.box a, .box a:visited { + color: #555; +} +.admin { + border: solid 1px #FFD324; + background-color: #FFF6BF; + color: #514721; + margin-bottom: 5px; + padding: 5px; +} +.admin h3 { + font-size: 100%; + text-align: left; + font-weight: 700; + color: #333; +} +.column { + vertical-align: top; + text-align: left; + padding: 0 0 0 10px; +} +.column.first { + padding: 0; +} +.column h3 { + padding: 3px 0; +} +.scrollable { + height: 144px; + overflow: auto; + border: 1px solid #e6e6e6; +} +.scroll-ie { + overflow-x: hidden; + padding-right: 17px; +} +.red { + color: #8B0000; +} +.green { + color: #050; +} +ul.bullet { + margin: 3px 0 3px 25px; +} +ul.bullet li { + padding: 2px 0; + list-style-image: url("../images/bullet.png?da7c8093227679496892e74f2dfd8d58"); +} +.rule_title { + font-size: 110%} +.tablinks { + float: right; + padding: 0 5px 0 10px; + text-align: right; +} +.tablinks li { + float: left; + text-align: right; + margin-left: 5px; + padding: 0 0 0 5px; +} +.tablinks li.first { + background: 0 0; +} +.tablinks a { + text-decoration: underline; + color: #777; + font-size: 85%} +.tabs-panel { + border-right: 1px solid #DDD; + border-bottom: 1px solid #DDD; + border-left: 1px solid #DDD; + border-top-width: 0; + padding: 10px; +} +.tabs2, .tabs { + height: 20px; + border-bottom: 1px solid #DDD; + margin: 0; + padding: 0; + font-size: 93%} +.tabs2 li, .tabs li { + display: inline; + list-style-type: none; + font-weight: 400; + color: #777; + vertical-align: baseline; + white-space: nowrap; + margin: 0; + border: 0; + padding: 0; +} +.tabs2 li a, .tabs li a { + float: left; + color: #777; + vertical-align: bottom; + height: 17px; + margin: 0 1px 0 0; + padding: 1px 5px; + border-bottom: none; +} +.tabs2 li a.selected, .tabs li a.selected, .tabs .ui-tabs-active a { + text-decoration: none; + color: #555!important; + font-weight: 700; + margin: 0 1px 0 0; +} +.tabbed { + border: 1px solid silver; + border-top: 0; + padding: 5px; +} +.comments { + color: #777; + font-size: 12px; + margin-bottom: 10px; + padding: 4px; +} +.little { + font-size: 80%} +.tooltip { + position: absolute; + background-color: #CAE3F2; + border: 1px solid #4b9fd5; + max-width: 480px; + text-align: left; + color: #262626; +} +.tooltip .content { + color: #111; + padding: 4px; +} +.tooltip .title { + color: #111; + font-weight: 700; + font-size: 100%; + padding: 2px 4px; +} +.tooltip td { + margin: 0; + padding: 2px; +} +.tooltip p { + margin: 0; + padding: 0; +} +.alert_WARN { + background-color: #f90; + color: #fff; + margin: 0; + padding: 0 3px; +} +a>.alert_WARN { + margin-bottom: -1px; + border-bottom: 1px solid #f90; + transition: all .2s ease; +} +a>.alert_WARN:hover { + opacity: .8; +} +.alert_ERROR { + background-color: #d4333f; + color: #fff; + margin: 0; + padding: 0 3px; +} +a>.alert_ERROR { + margin-bottom: -1px; + border-bottom: 1px solid #d4333f; + transition: all .2s ease; +} +a>.alert_ERROR:hover { + opacity: .8; +} +#comparison span.best { + font-size: 108%; + font-weight: 700; +} +.gwt-TabBar { + font-size: 93%; + width: 100%; + border-bottom: 1px solid #cdcdcd; +} +.gwt-TabBarFirst { + width: 0; +} +.gwt-TabBar .gwt-TabBarItem { + cursor: pointer; + font-weight: 400; + text-decoration: underline; + color: #555; + background-color: #EFEFEF; + vertical-align: middle; + white-space: nowrap; + padding: .3em .6em; + border: 1px solid #cdcdcd; + border-bottom: none; + border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + -webkit-border-radius: 4px 4px 0 0; +} +.gwt-TabBar .gwt-TabBarItem-wrapper { + padding: 0 0 0 1px; +} +.gwt-TabBar .gwt-TabBarItem-selected { + cursor: default; + font-weight: 700; + text-decoration: underline; + color: #efefef; + background-color: #4B9FD5; + border-bottom: none; + vertical-align: middle; + white-space: nowrap; + padding: .3em .6em; +} +.gwt-TabPanelBottom { + width: 100%} +.markdown-tips { + font-size: 12px; + color: #777; +} +.rule-desc h2 { + margin-top: 16px; + font-size: 16px; + line-height: 1.5; + color: #444; +} +.rule-desc h3 { + margin-top: 16px; + font-size: 12px; + line-height: 1.5; + color: #444; + font-weight: 700; +} +.rule-desc p, .property p { + margin-top: 10px; +} +.rule-desc pre, .property pre, .bubble-popup pre, .coding-rules-detail-parameter pre { + margin: 10px 0!important; + padding: 10px!important; + border: 1px dashed #aaa; + font-size: 12px; + font-family: monospace; +} +.rule-desc blockquote, .property blockquote, .bubble-popup blockquote, .coding-rules-detail-parameter blockquote { + margin-top: 10px; + padding: 10px; +} +.rule-desc ul, .property ul { + list-style-type: disc; + list-style-position: inside; + margin: 10px; +} +.rule-desc ol, .property ol { + list-style-type: decimal; + list-style-position: inside; + margin: 10px; +} +.rule-table { + margin-top: 10px; + overflow-x: auto; + border-collapse: collapse; +} +.rule-table th { + background: none no-repeat scroll right center #efefef; + border: 1px solid #DDD; + padding: 5px 10px; + font-weight: 700; +} +.rule-table td { + background: none no-repeat scroll right center transparent; + border: 1px solid #DDD; + padding: 5px 10px; +} +.tip:hover { + background: #FFF; + position: relative; + z-index: 100; +} +.tip span { + display: none; + margin-left: -20px; + padding: 4px 5px; +} +.tip:hover span { + display: inline; + position: absolute; + background: #CAE3F2; + border: 1px solid #4b9fd5; + color: #262626; + white-space: nowrap; + text-decoration: none; +} +.hbar { + float: left; + border: none; + clear: both; + width: 4em; + margin: 0; + padding: 2px 0 0; +} +.hbar li { + background-color: #777; + color: #FFF; + font-family: Verdana, Tahoma, Arial, sans-serif; + font-size: xx-small; + letter-spacing: -.075em; + list-style: none; + line-height: 1.1em; + text-align: right; + vertical-align: middle; + padding: .1em; +} +div.barchart { + border: 0; + margin: 0; + padding: 0; + float: left; +} +div.barchart>div { + background-color: #236a97; + height: .9em; +} +table.matrix thead { + background-color: #CAE3F2; + border: 1px solid #4b9fd5; +} +table.matrix thead th { + text-align: right; + border-right: 1px solid #4b9fd5; + padding: 4px 5px; +} +table.matrix tbody td { + border: 1px solid #ddd; + margin: 0; + padding: 4px 5px; +} +table.matrix tbody td.title { + border: none; + font-weight: 700; + margin: 0; + padding: 5px 0 0 5px; +} +a.nolink { + border-bottom: none; +} +h1 strong, .dashbox .title, .gwt-SourcePanel .sources .msg li strong { + font-weight: 700; +} +h4 a, h4 a:visited, .gray { + color: #777; +} +.even, table.sortable tr.rowodd { + background-color: #f5f5f5; +} +.bordered { + border-bottom: 1px solid #ddd; +} +table.data, table.spaced, .gwt-SourcePanel .sources { + width: 100%} +table.data td.barchart { + width: 100px; +} +table.without-header { + border-top: 1px solid #ddd; +} +.hoverable.selected a { + color: #fff; +} +.gwt-SourcePanel .sources td { + vertical-align: top; +} +.line-block { + display: block; + width: 100%; + height: 24px; + line-height: 22px; + margin-bottom: 5px; +} +.line-info { + background: url("../images/information.png?441b7712b4c687fd869663595f2d2841") no-repeat scroll left 50% transparent; + padding-left: 18px; +} +div.break10 { + height: 10px; +} +div.break30 { + height: 30px; +} +.marginbottom10 { + margin-bottom: 10px; +} +.marginbottom5 { + margin-bottom: 5px; +} +.marginright10 { + margin-right: 10px; +} +.marginleft10 { + margin-left: 10px; +} +.width100 { + width: 100%} +ul.horizontal { + list-style-type: none; +} +ul.horizontal li { + float: left; + position: relative; +} +table.nowrap td, td.nowrap, th.nowrap { + white-space: nowrap; +} +table.nowrap td.small, td.nowrap.small, th.nowrap.small { + line-height: 16px; +} +.background-gray { + background-color: #EFEFEF; + color: #444; +} +.bulk-edit { + display: block; + padding: 2px 0 2px 2px; +} +.csv { + display: block; + background: url("../images/csv.png?275d8839c05801c18013f3ec706d30bc") no-repeat scroll left 50% transparent; + padding: 2px 0 2px 20px; +} +.add { + display: block; + background: url("../images/add.png?4ea982641458a260ca3bc0575b5c687e") no-repeat scroll left 50% transparent; + padding: 2px 0 2px 20px; +} +.restore { + display: block; + background: url("../images/restore.gif?cbdc69992987d3ee037585b955cff796") no-repeat scroll left 50% transparent; + padding: 2px 0 2px 20px; +} +.compare { + display: block; + background: url("../images/compare.png?36ad68e78b5c90f3a75e1017d60618d0") no-repeat scroll left 50% transparent; + padding: 2px 0 2px 20px; +} +.diffParam { + font-family: 'Bitstream Vera Sans Mono', Courier, monospace; +} +.yellowHighlight { + background: #FFFBCC; +} +.link-action { + color: #236a97; + outline: 0; + text-decoration: none; + transition: all .2s ease; + border-bottom: 1px solid #cae3f2; +} +.link-action:hover { + color: #4b9fd5; +} +.link-action:active, .link-action:focus { + color: #236a97; +} +.link-action.link-red { + color: #d4333f; + border-bottom-color: #d49f98; +} +.link-action.link-red:hover, .link-action.link-red:active, .link-action.link-red:focus { + color: #d4333f; + border-bottom-color: #d4333f; +} +.link-red { + color: #d4333f!important; +} +.link-more { + background-image: url("../images/bullet_arrow_down.png?66181fb292ee9928a30e1777a8e6ad28"); + background-repeat: no-repeat; + padding-right: 20px; + background-position: right center; + cursor: pointer; +} +.dropdown { + cursor: pointer; + display: inline-block; + text-decoration: none!important; + zoom: 1; + *display: inline; +} +.dropdown-menu { + background-clip: padding-box; + background-color: #FFF; + border: 1px solid #DDD; + box-shadow: 10px 10px 20px rgba(0, 0, 0, .5); + float: left; + margin: 0; + max-width: 220px; + min-width: 160px; + padding: 0; + position: absolute; + z-index: 1000; +} +.dropdown-menu h2 { + padding: 0 8px; + font-size: 100%; + font-weight: 700; +} +.dropdown-menu li { + list-style-type: none!important; + line-height: 24px; + height: 24px; + padding: 0 8px; + cursor: pointer!important; + float: none!important; +} +.dropdown-menu li:hover { + background-color: #cae3f2!important; +} +.dropdown-menu a { + text-decoration: none!important; + border-bottom: none!important; + color: #444!important; +} +.form-key-cell { + padding: 2px 8px 4px 10px; + text-align: right; + width: 1%; + white-space: nowrap; + vertical-align: top; +} +.form-val-cell { + padding: 2px 8px 4px 0; + text-align: left; + white-space: normal; +} +.form-val-cell li { + margin-bottom: 5px; +} +.form-val-note { + color: #999; +} +blockquote { + border-left: 3px solid #E5E5E5; + padding: 0 8px; + line-height: 16px; +} +blockquote cite { + line-height: 16px; + background-image: url("../images/reviews/comment.png?dbcb8faed1d503559cdfc5ab6cee060e"); + background-repeat: no-repeat; + padding-left: 20px; + background-position: left center; + font-size: 12px; + color: #888; +} +.spacer-left { + margin-left: 8px; +} +.spacer-right { + margin-right: 8px; +} +.spacer-bottom { + margin-bottom: 8px; +} +.spacer-top { + margin-top: 8px; +} +td.spacer-left { + padding-left: 8px; +} +td.spacer-right { + padding-right: 8px; +} +td.spacer-bottom { + padding-bottom: 8px; +} +td.spacer-top { + padding-top: 8px; +} +.bordered { + border: 1px solid #DDD; +} +.bordered-left { + border-left: 1px solid #DDD; +} +.bordered-right { + border-right: 1px solid #DDD; +} +.bordered-bottom { + border-bottom: 1px solid #DDD; +} +.bordered-top { + border-top: 1px solid #DDD; +} +.table>thead>tr>th { + border-top: 0 none; + font-weight: 700; + line-height: 16px; + padding: 4px 5px; + vertical-align: bottom; +} +.table>tbody>tr>td { + line-height: 16px; + padding: 4px 5px; + vertical-align: top; +} +.table>tfoot>tr>td { + font-size: 93%; + color: #777; + padding: 4px 5px; +} +.table>tfoot>tr>td a { + color: #777; +} +.table-bordered>tbody { + border-left: 1px solid #DDD; + border-right: 1px solid #DDD; + border-bottom: 1px solid #DDD; +} +.table-bordered>tbody>tr>td { + border-top: 1px solid #DDD; +} +select.small-width { + max-width: 120px; +} +select.medium-width { + max-width: 175px; + width: 175px; +} +.modal-head { + padding: 0 10px; + background-color: #EFEFEF; + border-bottom: 1px solid #DDD; +} +.modal-head h1, .modal-head h2 { + line-height: 30px; + min-height: 30px; +} +ul.modal-head-metadata { + overflow: hidden; + padding: 0 0 5px; +} +ul.modal-head-metadata li { + float: left; + position: relative; + font-size: 85%; + color: #777; +} +.modal-body { + padding: 10px; +} +.modal-body-select2 { + margin-bottom: 10px; +} +.modal-body .notes { + height: auto; +} +.modal-field { + clear: both; + display: block; + padding: 5px 0 5px 130px; +} +.modal-field label { + display: block; + float: left; + text-align: right; + width: 130px; + left: -140px; + margin-right: -130px; + line-height: 1; + word-wrap: break-word; + position: relative; + padding-top: 5px; +} +.modal-field label.simple-label { + display: inline-block; + vertical-align: middle; + float: none; + position: static; + margin: 0 0 0 -5px; + padding: 0; + text-align: left; +} +.readonly-field { + padding-top: 5px; + margin-left: -5px; + line-height: 1; +} +.modal-field input { + margin-right: 5px; + margin-bottom: 10px; +} +.modal-field input[type=text], .modal-field input[type=password], .modal-field textarea { + width: 250px; +} +.modal-field .text { + line-height: 20px; +} +.modal-foot { + text-align: right; + padding: 2px 10px; + border-top: 1px solid #CCC; + line-height: 30px; + height: 30px; + background-color: #EFEFEF; +} +.modal-foot input { + margin-right: 10px; +} +.modal-field-description { + clear: both; + font-size: 93%; + color: #777; +} +.modal-error, .modal-warning, .modal-notice { + display: none; +} +textarea.width100 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.property { + margin-bottom: 10px; +} +.property h3 { + float: none; + max-width: 20em; +} +.property>th, .property>td { + vertical-align: top; + padding: 10px; +} +.property>th { + text-align: right; +} +.property table.data { + width: 480px; +} +.property textarea { + vertical-align: text-top; +} +.property .note { + margin-top: 5px; +} +.accordion-item { + border: 1px solid #e6e6e6; + margin-bottom: 20px; +} +.accordion-item table.data { + border-collapse: separate; +} +.accordion-item-body-medium { + max-height: 200px; + overflow: auto; +} +.rule-search { + display: inline-block; + line-height: 16px; +} +div.rule-title { + display: inline-block; + float: left; + clear: right; +} +#result_table .rule-desc { + width: 100%; + float: left; + clear: right; +} +.rule-status, .rule-tags { + display: inline-block; + margin-left: 10px; + float: right; + padding: 3px 5px 0 0; + font-size: 85%; + color: #777; +} +.rule-tags a { + color: inherit; + text-decoration: none; +} +.rule-status span { + text-transform: uppercase; +} +.rule-tags span { + background-color: #eee; + padding: 3px 4px; + margin: 4px 2px; + border-radius: 2px; + box-shadow: 0 -1px 0 rgba(0, 0, 0, .12)inset; +} +.project-search { + display: inline-block; + line-height: 16px; + padding: 4px 2px; +} +.sonar-d3 .axis path { + fill: none; + stroke: #444; +} +.sonar-d3 .tick line { + stroke: #444; +} +.sonar-d3 .tick text { + fill: #444; +} +.sonar-d3 .plot { + transition: all .2s ease; +} +.sonar-d3 .plot:hover .arc, .sonar-d3 .plot.hover .arc { + opacity: .4; +} +.sonar-d3 .plot .arc:hover, .sonar-d3 .plot .arc.hover { + opacity: 1; +} +.sonar-d3 .plot .line { + fill: none; + stroke: #000; + stroke-width: 2; +} +.sonar-d3 .plot .line-marker { + fill: #fff; + stroke: #000; + stroke-width: 2; + opacity: 0; +} +.sonar-d3 .plot .scanner { + stroke: #000; + opacity: .25; +} +.sonar-d3 .arc, .sonar-d3 .bar rect { + cursor: pointer; + stroke: #fff; + stroke-width: 1px; + transition: all .2s ease; +} +.sonar-d3 .bar, .sonar-d3 .bar .legend-text, .sonar-d3 .pie-legend, .sonar-d3 .pie-legend .legend-text { + cursor: pointer; +} +.sonar-d3 .legend-bullet { + transition: all .2s ease; +} +.sonar-d3 .legend-text { + font-size: 12px; + cursor: default; +} +.sonar-d3 .legend-active .legend-bullet { + -webkit-transform: scale(1.4); + -webkit-transform-origin: center; +} +.sonar-d3 .legend-html { + margin-bottom: 10px; + color: #777; +} +.sonar-d3 .legend-html .legend-text+.legend-text { + margin-left: 15px; +} +.sonar-d3 .legend-html .legend-text-main { + font-weight: 500; +} +.sonar-d3 .details-color-indicator { + fill: #fff; + transition: fill .2s ease; +} +.sonar-d3 .details-metric { + font-size: 12px; +} +.sonar-d3 .details-metric-main { + font-weight: 700; +} +.sonar-d3 .info-text { + font-size: 13px; +} +.sonar-d3 .info-text-bold { + font-weight: 700; +} +.sonar-d3 .info-text-small { + font-size: 12px; +} +.sonar-d3 .event-tick { + fill: none; + stroke: #000; + stroke-width: 1px; + transition: all .3s ease; +} +.sonar-d3.cloud-widget { + text-align: center; +} +.sonar-d3 .cloud-word { + display: inline-block; + vertical-align: baseline; + white-space: nowrap; + margin-right: 14px; + text-decoration: none; + border-bottom: 1px solid transparent; +} +.sonar-d3 .cloud-word:hover { + border-bottom: 1px solid; +} +.sonar-d3 .max-results-reached-message { + font-size: 12px; +} +.sonar-d3 div.max-results-reached-message { + margin-top: 10px; + color: #777; + text-align: center; +} +.sonar-d3 text.max-results-reached-message { + fill: #777; +} +.sonar-d3 .treemap-container { + position: relative; +} +.sonar-d3 .treemap-cell { + position: absolute; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + -moz-box-sizing: border-box; + box-sizing: border-box; + text-align: center; +} +.sonar-d3 .treemap-cell-drilldown { + cursor: pointer; + transition: opacity .2s ease; +} +.sonar-d3 .treemap-cell-drilldown:hover { + opacity: .8; +} +.sonar-d3 .treemap-inner { + display: inline-block; + vertical-align: middle; + line-height: 1.2; + padding: 5px; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #fff; + font-weight: 300; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.sonar-d3 .treemap-link { + position: absolute; + z-index: 2; + top: 5px; + right: 5px; + line-height: 14px; + color: #fff; + opacity: .5; + border-bottom: none; +} +.sonar-d3 .treemap-link:hover { + opacity: 1; +} +.sonar-d3 .treemap-link i, .sonar-d3 .treemap-link i:before { + vertical-align: top; + font-size: inherit; + line-height: inherit; +} +.sonar-d3 .treemap-cell-small .treemap-inner { + display: none; +} +.sonar-d3 .treemap-cell-very-small .treemap-inner { + display: none; +} +.sonar-d3 .treemap-cell-very-small .treemap-link { + display: none; +} +.sonar-d3 .treemap-breadcrumbs { + margin-top: 10px; + padding-top: 7px; + border-top: 1px solid #E6E6E6; +} +.sonar-d3 .treemap-breadcrumbs-item { + color: #777; +} +.sonar-d3 .treemap-breadcrumbs-item>[class^=icon-qualifier-] { + margin-right: 4px; +} +.sonar-d3 .treemap-breadcrumbs-item+.treemap-breadcrumbs-item { + margin-left: 10px; +} +.sonar-d3 .treemap-breadcrumbs-item+.treemap-breadcrumbs-item>.icon-chevron-right { + margin-right: 10px; +} +.admin-page-title { + margin-bottom: 0; +} +.admin-page-description { + font-size: 85%; + font-weight: 400; + margin-bottom: 25px; +} +.bubble-popup { + position: absolute; + z-index: 100; + margin-top: -16px; + margin-left: 8px; + padding: 10px; + border: 1px solid #e6e6e6; + border-radius: 3px; + -moz-box-sizing: border-box; + box-sizing: border-box; + background-color: #fff; + box-shadow: 10px 10px 20px rgba(0, 0, 0, .5); +} +.bubble-popup-arrow, .bubble-popup-arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border: 8px solid transparent; +} +.bubble-popup-arrow { + top: 15px; + left: -8px; + border-left-width: 0; + border-right-color: #e6e6e6; +} +.bubble-popup-arrow:after { + content: " "; + left: 1px; + bottom: -8px; + border-left-width: 0; + border-right-color: #fff; +} +.bubble-popup-bottom { + margin-top: 8px; + margin-left: -16px; +} +.bubble-popup-bottom .bubble-popup-arrow { + top: -8px; + left: 15px; + border-left-width: 8px; + border-top-width: 0; + border-right-color: transparent; + border-bottom-color: #e6e6e6; +} +.bubble-popup-bottom .bubble-popup-arrow:after { + left: -8px; + bottom: -9px; + border-left-width: 8px; + border-top-width: 0; + border-right-color: transparent; + border-bottom-color: #fff; +} +.bubble-popup-bottom-right { + margin-top: 8px; + margin-left: -16px; + margin-left: 0; + margin-right: -8px; +} +.bubble-popup-bottom-right .bubble-popup-arrow { + top: -8px; + left: 15px; + border-left-width: 8px; + border-top-width: 0; + border-right-color: transparent; + border-bottom-color: #e6e6e6; +} +.bubble-popup-bottom-right .bubble-popup-arrow:after { + left: -8px; + bottom: -9px; + border-left-width: 8px; + border-top-width: 0; + border-right-color: transparent; + border-bottom-color: #fff; +} +.bubble-popup-bottom-right .bubble-popup-arrow { + left: auto; + right: 15px; +} +.bubble-popup-container { + max-width: 560px; + max-height: 300px; + overflow: auto; +} +.bubble-popup-title { + margin-bottom: 5px; + font-weight: 600; +} +.bubble-popup-section { + width: 450px; + padding-bottom: 2px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.bubble-popup-section.fluid { + width: auto; + max-width: 450px; +} +.bubble-popup-section+.bubble-popup-section, .bubble-popup-section+.bubble-popup-title { + margin-top: 10px; +} +.bubble-popup-list { + margin-top: 5px; +} +.bubble-popup-list>li { + padding: 2px 0; +} +@font-face { + font-family: sonar; + src: url("../fonts/sonar.eot??528bf402310afebac23d469d3ca3329a"); + src: url("../fonts/sonar.eot?#iefix?528bf402310afebac23d469d3ca3329a") format('embedded-opentype'), url("../fonts/sonar.woff??092aa12b52e10b720f58185b9a0a4979") format('woff'), url("../fonts/sonar.ttf??403688ec2ef4aa8a613b29d3ced24d75") format('truetype'), url("../fonts/sonar.svg?#sonar?1e882586786bb43a2d60d232dabb3a1f") format('svg'); + font-weight: 400; + font-style: normal; +} +[class^=icon-], [class*=" icon-"] { + font-family: sonar; + speak: none; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: middle; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +a[class^=icon-], a[class*=" icon-"] { + border-bottom: none; +} +.icon-black { + color: #444; +} +.icon-red { + color: #d4333f; +} +.icon-green { + color: #85bb43; +} +[class^=icon-severity-], [class*=" icon-severity"] { + position: relative; + top: -1px; +} +.icon-severity-blocker:before, .icon-severity-4:before { + content: "\f000"; + color: #d4333f; + font-size: 14px; +} +.icon-severity-critical:before, .icon-severity-3:before { + content: "\f001"; + color: #d4333f; + font-size: 14px; +} +.icon-severity-major:before, .icon-severity-2:before { + content: "\f003"; + color: #d4333f; + font-size: 14px; +} +.icon-severity-minor:before, .icon-severity-1:before { + content: "\f006"; + color: #85bb43; + font-size: 14px; +} +.icon-severity-info:before, .icon-severity-0:before { + content: "\f004"; + color: #85bb43; + font-size: 14px; +} +[class^=icon-status-], [class*=" icon-status"] { + position: relative; + top: -1px; +} +.icon-status-open:before { + content: "\f010"; + color: #4b9fd5; + font-size: 14px; + line-height: 12px; +} +.icon-status-confirmed:before { + content: "\f011"; + color: #4b9fd5; + font-size: 14px; + line-height: 12px; +} +.icon-status-reopened:before { + content: "\f012"; + color: #4b9fd5; + font-size: 14px; + line-height: 12px; +} +.icon-status-resolved:before { + content: "\f013"; + color: #444; + font-size: 14px; + line-height: 12px; +} +.icon-status-closed:before { + content: "\f014"; + color: #444; + font-size: 14px; + line-height: 12px; +} +.icon-test-status-ok:before { + content: "\f013"; + color: #85bb43; + font-size: 16px; +} +.icon-test-status-failure:before { + content: "\f000"; + color: #f90; + font-size: 16px; +} +.icon-test-status-error:before { + content: "\f057"; + color: #d4333f; + font-size: 16px; +} +.icon-test-status-skipped:before { + content: "\f056"; + color: #b4b4b4; + font-size: 16px; +} +.icon-alert-ok:before { + content: "\f013"; + color: #85bb43; + font-size: 16px; +} +.icon-alert-warn:before { + content: "\f000"; + color: #f90; + font-size: 16px; +} +.icon-alert-error:before { + content: "\f057"; + color: #d4333f; + font-size: 16px; +} +.icon-alert-none:before { + content: "\f056"; + color: #b4b4b4; + font-size: 16px; +} +[class^=icon-qualifier-], [class*=" icon-qualifier-"] { + position: relative; + top: -1px; + color: #444; + font-size: 16px; + text-shadow: 0 1px 0 #fff; +} +.icon-qualifier-dir:before, .icon-qualifier-pac:before { + content: "\f114"} +.icon-qualifier-trk:before, .icon-qualifier-brc:before, .icon-qualifier-dev_prj:before { + content: "\e600"} +.icon-qualifier-cla:before, .icon-qualifier-fil:before { + content: "\f0f6"} +.icon-qualifier-uts:before { + content: "\e602"} +.icon-qualifier-lib:before { + content: "\e604"} +.icon-qualifier-vw:before, .icon-qualifier-svw:before { + content: "\e608"} +.icon-qualifier-dev:before { + content: "\e60a"} +.icon-qualifier-dir:before, .icon-qualifier-pac:before { + color: #f90; +} +.icon-qualifier-cla:before, .icon-qualifier-fil:before, .icon-qualifier-trk:before, .icon-qualifier-brc:before, .icon-qualifier-uts:before, .icon-qualifier-lib:before, .icon-qualifier-vw:before, .icon-qualifier-svw:before, .icon-qualifier-dev:before, .icon-qualifier-dev_prj:before { + color: #2d87c0; +} +[class^=icon-trend-], [class*=" icon-trend-"] { + position: relative; + top: -1px; + font-size: 14px; +} +.icon-trend-big { + font-size: 16px; +} +.icon-trend-0:before { + content: "\e607"} +.icon-trend-1:before { + content: "\e605"} +.icon-trend--1:before { + content: "\e601"} +.icon-trend-2:before { + content: "\e606"} +.icon-trend--2:before { + content: "\e603"} +.icon-checkbox { + position: relative; + top: -1px; + color: #777; + font-size: 16px; +} +.icon-checkbox:before { + content: "\e60c"} +.icon-checkbox-checked:after { + color: #4b9fd5; +} +.icon-checkbox-checked:after { + content: "\e60d"; + position: absolute; + top: 0; + left: 0; +} +.icon-checkbox-checked.icon-checkbox-single:after { + content: "\e60e"} +.icon-checkbox-invisible { + visibility: hidden; +} +.icon-list:before { + content: "\f039"} +.icon-bullet-list:before { + content: "\f03a"} +.icon-settings:before { + content: "\f015"} +.icon-bulk-change:before { + content: "\f085"; + font-size: 16px; +} +.icon-arrow-down:before { + content: "\f0d7"; + position: relative; + top: -2px; +} +.icon-arrow-up:before { + content: "\f0d8"; + position: relative; + top: -2px; +} +.icon-arrow-left:before { + content: "\f0d9"} +.icon-arrow-right:before { + content: "\f0da"} +.icon-dropdown:before { + content: "\f0d7"; + position: relative; + top: -1px; +} +.icon-sort-desc:before { + content: "\f0d7"; + position: relative; + top: -1px; +} +.icon-sort-asc:before { + content: "\f0d8"; + position: relative; + top: -1px; +} +.icon-emoticon-smiley:before { + content: "\f118"} +.icon-emoticon-sad:before { + content: "\f119"} +.icon-emoticon-speechless:before { + content: "\f11a"} +.icon-rect-check:before { + content: "\f046"} +.icon-check:before { + content: "\f00c"; + color: #85bb43; + font-size: 16px; +} +.icon-default:before { + position: relative; + top: -.1em; + content: "\f00c"} +.icon-lang:before { + content: "\f024"; + font-size: 14px; +} +.icon-quality-profile:before { + content: "\f022"; + font-size: 14px; +} +.icon-tags:before { + content: "\f02c"; + font-size: 14px; +} +.icon-calendar:before { + content: "\f073"; + font-size: 16px; +} +.icon-favorite { + font-size: 16px; +} +.icon-favorite:before { + content: "\f005"; + color: #f90; + font-size: 16px; +} +.icon-not-favorite { + font-size: 16px; +} +.icon-not-favorite:before { + content: "\f005"; + color: #cdcdcd; + font-size: 16px; +} +.icon-help:before { + content: "\f059"; + color: #4b9fd5; + font-size: 16px; +} +.icon-info:before { + content: "\f05a"; + color: #4b9fd5; + font-size: 16px; +} +.icon-uniF060:before { + content: "\f060"} +.icon-uniF061:before { + content: "\f061"} +.icon-uniF062:before { + content: "\f062"} +.icon-uniF063:before { + content: "\f063"} +.icon-comment:before { + content: "\f075"; + font-size: 14px; +} +.icon-delete:before { + content: "\f00d"; + color: #d4333f; + font-size: 16px; +} +.icon-compare:before { + content: "\f0c5"; + font-size: 14px; +} +.icon-restore:before { + content: "\f122"; + font-size: 14px; +} +.icon-inheritance:before { + content: "\f126"} +.icon-plus:before { + content: "\f067"; + font-size: 16px; +} +.icon-link:before { + content: "\f127"; + font-size: 14px; +} +.icon-move-down:before { + content: "\f063"; + color: #236a97; + font-size: 16px; +} +.icon-move-up:before { + content: "\f062"; + color: #236a97; + font-size: 16px; +} +.icon-move-left:before { + content: "\f060"; + color: #236a97; + font-size: 16px; +} +.icon-move-right:before { + content: "\f061"; + color: #236a97; + font-size: 16px; +} +.icon-scm:before { + content: "\f017"; + font-size: 14px; +} +.icon-scm_dev:before { + content: "\f015"; + font-size: 14px; +} +.icon-ci:before { + content: "\f021"; + font-size: 14px; +} +.icon-issue:before { + content: "\f188"; + font-size: 14px; +} +.icon-homepage:before { + content: "\f016"; + font-size: 14px; +} +.icon-resizer:before { + content: "\f142"; + color: #cdcdcd; + font-size: 16px; +} +.icon-expand:before { + content: "\e60b"; + font-size: 16px; +} +.icon-period:before { + content: "\f018"; + font-size: 16px; +} +.icon-filter:before { + content: "\f03a"; + font-size: 16px; +} +.icon-detach:before { + content: "\f08e"; + font-size: 14px; +} +.icon-chevron-left:before { + content: "\f104"; + font-size: 14px; +} +.icon-chevron-right:before { + content: "\f105"; + font-size: 14px; +} +.icon-double-chevron-left:before { + content: "\f100"; + font-size: 14px; +} +.icon-double-chevron-right:before { + content: "\f101"; + font-size: 14px; +} +.icon-extension:before { + content: "\f069"; + font-size: 16px; +} +.icon-home:before { + content: "\f016"; + font-size: 16px; +} +.spinner { + position: relative; + vertical-align: middle; + width: 16px; + height: 16px; + border: 2px solid #0cf; + border-radius: 50%; + -webkit-animation: spin .75s infinite linear; + animation: spin .75s infinite linear; +} +.ie9 .spinner { + background-image: url("../images/loading.gif?e2a9308e1360f28fb8fe7ad05eed2e38"); + background-repeat: no-repeat; + background-position: 0 0; + border: none; +} +.spinner:before, .spinner:after { + left: -2px; + top: -2px; + display: none; + position: absolute; + content: ''; + width: inherit; + height: inherit; + border: inherit; + border-radius: inherit; +} +.spinner, .spinner:before, .spinner:after { + display: inline-block; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-color: transparent; + border-top-color: #4b9fd5; + -webkit-animation-duration: 1.2s; + animation-duration: 1.2s; +} +.spinner:before { + -webkit-transform: rotate(120deg); + -ms-transform: rotate(120deg); + transform: rotate(120deg); +} +.spinner:after { + -webkit-transform: rotate(240deg); + -ms-transform: rotate(240deg); + transform: rotate(240deg); +} +.spinner-margin { + margin: 10px; +} +@-webkit-keyframes spin { + from { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); +} +to { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); +} +}@keyframes spin { + from { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); +} +to { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); +} +}@font-face { + font-family: Roboto; + src: url("../fonts/Roboto-Light-webfont.eot?efd91b453f819684984ca83fd8db381a"); + src: url("../fonts/Roboto-Light-webfont.eot?#iefix?efd91b453f819684984ca83fd8db381a") format('embedded-opentype'), url("../fonts/Roboto-Light-webfont.woff?e2a80e99a7a0f73f9d5eb0a76c3291a2") format('woff'), url("../fonts/Roboto-Light-webfont.ttf?469c9049e5e80133a02a56c86a8b1e03") format('truetype'), url("../fonts/Roboto-Light-webfont.svg#robotolight?344300b18a23acb2504fbade4caceb01") format('svg'); + font-weight: 300; + font-style: normal; +} +@font-face { + font-family: Roboto; + src: url("../fonts/Roboto-Regular-webfont.eot?b9c2d82a0eaf54330a07c7b29e7fa0f5"); + src: url("../fonts/Roboto-Regular-webfont.eot?#iefix?b9c2d82a0eaf54330a07c7b29e7fa0f5") format('embedded-opentype'), url("../fonts/Roboto-Regular-webfont.woff?5e4fa07b945a148d5e5789709cae4210") format('woff'), url("../fonts/Roboto-Regular-webfont.ttf?76a334ee91f49c94df0f3676b6ed84cd") format('truetype'), url("../fonts/Roboto-Regular-webfont.svg#robotoregular?f9ede3e38f01dfdbf4902cdf626eaffb") format('svg'); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: Roboto; + src: url("../fonts/Roboto-Medium-webfont.eot?6f2aff0dfddc7a7a5deff19f5d4197d5"); + src: url("../fonts/Roboto-Medium-webfont.eot?#iefix?6f2aff0dfddc7a7a5deff19f5d4197d5") format('embedded-opentype'), url("../fonts/Roboto-Medium-webfont.woff?b1bf937b4340988b2886a8407d978ba4") format('woff'), url("../fonts/Roboto-Medium-webfont.ttf?5713ededcd04f2d4fb2e5c63f2a7b2c6") format('truetype'), url("../fonts/Roboto-Medium-webfont.svg#robotomedium?72f6bae64658cd141ce8c1cafd12791e") format('svg'); + font-weight: 500; + font-style: normal; +} +@font-face { + font-family: Roboto; + src: url("../fonts/Roboto-Bold-webfont.eot?6813d1b15f40ce5c9897625c3e49d874"); + src: url("../fonts/Roboto-Bold-webfont.eot?#iefix?6813d1b15f40ce5c9897625c3e49d874") format('embedded-opentype'), url("../fonts/Roboto-Bold-webfont.woff?c691a29cc74d0e4e35797a73dec6361c") format('woff'), url("../fonts/Roboto-Bold-webfont.ttf?efde55770658360bdc459dfc334ac845") format('truetype'), url("../fonts/Roboto-Bold-webfont.svg#robotobold?1dc03cd3af72747bc130840b97611d44") format('svg'); + font-weight: 700; + font-style: normal; +} +body { + font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif; +} +select, input, button, textarea { + font-size: 99%; + font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif; +} +select::-moz-focus-inner, input::-moz-focus-inner, button::-moz-focus-inner { + border: 0; + padding: 0; +} +.nowrap { + white-space: nowrap; +} +.text-ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.justify { + margin-bottom: -1em; + text-align: justify; +} +.justify>.ib { + display: inline-block; +} +.justify:after { + display: inline-block; + width: 100%; + content: " "} +.no-transform { + text-transform: none; +} +.base-link { + color: #444; + outline: 0; + text-decoration: none; + transition: all .2s ease; +} +.base-link:hover { + color: #4b9fd5; +} +.base-link:active, .base-link:focus { + color: #236a97; +} +.icon-with-link { + outline: 0; + text-decoration: none; +} +.widget-link { + color: #236a97; + outline: 0; + text-decoration: none; + transition: all .2s ease; + border-bottom: 1px solid #cae3f2; +} +.widget-link:hover { + color: #4b9fd5; +} +.widget-link:active, .widget-link:focus { + color: #236a97; +} +.widget-link-red { + color: #d4333f; + border-bottom-color: #d49f98; +} +.widget-link-red:hover, .widget-link-red:active, .widget-link-red:focus { + color: #d4333f; + border-bottom-color: #d4333f; +} +.link-no-underline { + border-bottom: none; +} +a { + cursor: pointer; + color: #236a97; + outline: 0; + text-decoration: none; + transition: all .2s ease; + border-bottom: 1px solid #cae3f2; +} +a:hover { + color: #4b9fd5; +} +a:active, a:focus { + color: #236a97; +} +a.link-red { + color: #d4333f; + border-bottom-color: #d49f98; +} +a.link-red:hover, a.link-red:active, a.link-red:focus { + color: #d4333f; + border-bottom-color: #d4333f; +} +a.active-link { + border-bottom: none; + font-weight: 500; +} +input[type=text], input[type=password], input[type=email], textarea { + border: 1px solid #cdcdcd; + -moz-box-sizing: border-box; + box-sizing: border-box; + background: #fff; + color: #444; + transition: border-color .2s ease; +} +input[type=text]:active, input[type=password]:active, input[type=email]:active, textarea:active, input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, textarea:focus { + border-color: #4b9fd5; + box-shadow: none; + outline: 0; +} +input[type=text].invalid, input[type=password].invalid, input[type=email].invalid, textarea.invalid { + border-color: #d4333f; +} +input[type=text], input[type=password], input[type=email] { + height: 22px; + padding: 0 3px; +} +textarea { + padding: 3px; +} +button, .button, input[type=submit], input[type=button] { + display: inline-block; + vertical-align: baseline; + height: 22px; + margin: 0 1px; + padding: 0 10px; + border: 1px solid #cdcdcd; + -moz-box-sizing: border-box; + box-sizing: border-box; + background: #f4f4f4; + color: #444; + font-weight: 700; + font-size: 13px; + text-align: center; + text-decoration: none; + cursor: pointer; + outline: 0; + transition: border-color .2s ease; +} +button:hover, .button:hover, input[type=submit]:hover, input[type=button]:hover, button.active, .button.active, input[type=submit].active, input[type=button].active { + border-color: #5281a0; + background: #4b9fd5; + color: #fff; +} +button:active, .button:active, input[type=submit]:active, input[type=button]:active { + border-color: #2790c0; + background: #78bdea; + color: #fff; +} +button:focus, .button:focus, input[type=submit]:focus, input[type=button]:focus { + border-color: #4b9fd5; +} +button[disabled], .button[disabled], input[type=submit][disabled], input[type=button][disabled], button[disabled]:hover, .button[disabled]:hover, input[type=submit][disabled]:hover, input[type=button][disabled]:hover, button[disabled]:active, .button[disabled]:active, input[type=submit][disabled]:active, input[type=button][disabled]:active, button[disabled]:focus, .button[disabled]:focus, input[type=submit][disabled]:focus, input[type=button][disabled]:focus { + color: #bbb; + border-color: #ddd; + background: #ebebeb; + cursor: default; +} +.button { + line-height: 22px; +} +.button-red:hover, .button-red:focus { + border-color: #900; + background: #c00; + color: #fff; +} +.button-red:active { + border-color: #900; + background: red; +} +.button-clean, .button-clean:hover, .button-clean:focus { + margin: 0; + padding: 0; + border: none; + background: 0 0; + color: #444; +} +.button-group { + display: inline-block; + vertical-align: middle; + font-size: 0; + white-space: nowrap; +} +.button-group>button, .button-group>.button { + position: relative; + z-index: 2; + display: inline-block; + vertical-align: middle; + margin: 0; + padding: 2px 8px; + font-size: 12px; + font-weight: 400; + cursor: pointer; +} +.button-group>button:hover, .button-group>.button:hover, .button-group>button:focus, .button-group>.button:focus, .button-group>button:active, .button-group>.button:active, .button-group>button.active, .button-group>.button.active { + z-index: 3; +} +.button-group>.button { + line-height: 16px; +} +.button-group>button+button, .button-group>button+.button, .button-group>.button+button, .button-group>.button+.button { + margin-left: -1px; +} +.button-group>a:not(.button) { + vertical-align: middle; + margin: 0 8px; + font-size: 12px; +} +.message-alert { + display: block; + padding: 5px 8px; + border: 2px solid #f90; +} +.message-error { + display: block; + padding: 5px 8px; + background-color: #d4333f; + color: #fff; +} +.markdown a { + color: #236a97; + outline: 0; + text-decoration: none; + transition: all .2s ease; + border-bottom: 1px solid #cae3f2; +} +.markdown a:hover { + color: #4b9fd5; +} +.markdown a:active, .markdown a:focus { + color: #236a97; +} +.markdown a.link-red { + color: #d4333f; + border-bottom-color: #d49f98; +} +.markdown a.link-red:hover, .markdown a.link-red:active, .markdown a.link-red:focus { + color: #d4333f; + border-bottom-color: #d4333f; +} +.rating { + display: inline-block; + width: 1em; + height: 1.3em; + line-height: 1.3; + color: #fff; + font-weight: 300; + text-align: center; +} +a>.rating { + margin-bottom: -1px; + border-bottom: 1px solid; + transition: all .2s ease; +} +a>.rating:hover { + opacity: .8; +} +.rating-A { + background-color: #0A0; +} +a .rating-A { + border-bottom-color: #0A0; +} +.rating-B { + background-color: #80CC00; +} +a .rating-B { + border-bottom-color: #80CC00; +} +.rating-C { + background-color: #FE0; + color: #444; +} +a .rating-C { + border-bottom-color: #FE0; +} +.rating-D { + background-color: #F77700; +} +a .rating-D { + border-bottom-color: #F77700; +} +.rating-E { + background-color: #E00; +} +a .rating-E { + border-bottom-color: #E00; +} +.code { + font-size: 12px; +} +.code pre { + font-family: Monospace; + padding: 0 5px; + color: #111; + margin: 0; +} +.code .a { + color: olive; +} +.code .c { + color: #660E80; + font-style: italic; + font-weight: 700; +} +.code .j { + color: #666; + font-style: normal; +} +.code .cd { + color: #666; + font-style: italic; +} +.code .cppd { + color: #666; + font-style: italic; +} +.code .k { + color: navy; + font-weight: 700; +} +.code .s { + color: green; + font-weight: 700; +} +.code .h { + color: navy; + font-weight: 400; +} +.code .p { + color: #347235; + font-weight: 400; +} +.sym { + cursor: hand; + cursor: pointer; +} +.highlighted { + background-color: #B3D4FF; +} +.dashboard-page { + background-color: #f3f3f3; +} +.dashboard-page #ftlinks { + border-top-color: #e6e6e6; + background-color: #f3f3f3; +} +#dashboard { + position: relative; + width: 100%} +#dashboard .transparent { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + background: url("../images/transparent.gif?e3a98b896a81dbc5b02ca14b5646e2ac") repeat; + z-index: 1000; +} +#dashboard .widget { + position: relative; + overflow-x: auto; + overflow-y: hidden; + padding: 10px; + margin: 0; +} +#dashboard .widget .big { + line-height: 1.5; + font-size: 24px; + font-weight: 300; +} +#dashboard .block { + margin: 0 0 10px; + border: 1px solid #e6e6e6; + background-color: #fff; +} +#dashboard .configure_widget { + display: block; + position: relative; +} +#dashboard .widget_props { + background-color: #FFFBE2; + border: 1px solid #FCE174; + margin: 5px; + padding: 5px; +} +#dashboard .widget-title { + padding: 10px; + line-height: 1; + border-bottom: 1px solid #e6e6e6; + color: #444; + font-size: 14px; + font-weight: 400; + text-transform: uppercase; +} +#dashboard .widget-title a { + border-bottom: none; +} +#dashboard #configure { + position: relative; + height: 260px; + margin: 5px 0 10px; +} +#dashboard #widget_defs, #dashboard #edit-layout { + background-color: #FFFBE2; + border: 1px solid #FCE174; + padding: 5px; + overflow-x: hidden; +} +#dashboard #widget_defs { + margin-right: 104px; + overflow-y: auto; + height: 250px; +} +#dashboard #edit-layout { + width: 86px; + height: 248px; + position: absolute; + right: 0; + top: 0; + padding-top: 5px; +} +#dashboard #edit-layout p { + margin-bottom: 5px; +} +#dashboard .widget_def { + display: inline-block; + vertical-align: top; + border: 1px solid #FCE174; + padding: 5px; + margin: 5px; + white-space: normal; + width: 250px; + min-height: 100px; +} +#dashboard ul.widget_categs li { + padding-right: 5px; +} +#dashboard ul.widget_categs li.selected a { + font-weight: 700; + text-decoration: none; +} +#dashboard .select-layout { + float: left; +} +#dashboard .select-layout img { + border: 3px solid #FFF6BF; +} +#dashboard .select-layout.selected img { + border: 3px solid #4B9FD5; +} +.admin_page { + position: relative; +} +.admin_page table { + margin-top: 10px; + margin-bottom: 50px; +} +.admin_page .empty { + font-style: italic; +} +.admin_page .operations { + width: 260px; + text-align: right; +} +.admin_page .operations .link-action { + margin-left: 4px; +} +.admin_page .owner { + width: 140px; + text-align: center; +} +.admin_page .shared { + width: 40px; + text-align: center; +} +.admin_page .order, .admin_page .global { + width: 45px; + text-align: center; +} +#dashboard #dashboard-operations { + position: relative; + display: inline-block; + width: 100%} +#dashboard #dashboard-operations ul.operations { + float: left; + list-style-type: none; + border: 1px solid #cdcdcd; + padding: 0; + margin: 0; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} +#dashboard #dashboard-operations ul.operations li { + float: left; + margin: 0; + padding: 2px 10px; + position: relative; + background-color: #f4f4f4; + font-size: 85%; + border-right: 1px solid #cdcdcd; +} +#dashboard #dashboard-operations ul.operations li.last { + border-right-width: 0; +} +#dashboard #dashboard-operations ul.operations li.selected { + background-color: #d4d4d4; +} +#dashboard #dashboard-operations ul.operations li a { + color: #555; +} +#dashboard .dashboard-column { + margin: 0; + padding: 0; + overflow: visible; +} +#dashboard .dashboard-column-wrapper { + float: left; + margin: 0; + padding: 0; +} +#dashboard .column-handle { + height: 30px; + width: 100%; + margin: 0; + padding: 0; + display: inline-block; + line-height: 100px; + text-align: center; + font-size: x-large; + vertical-align: middle; + background-color: #eee; +} +#dashboard .block { + position: relative; + width: 100%} +#dashboard .widget-header { + line-height: 16px; + padding: 3px 5px 5px; + background-color: #efefef; + border: 1px solid #ddd; + border-bottom: 0; +} +#dashboard .widget-handle { + cursor: move; + margin: 0; + background-image: url("../images/move.png?c9696f1a9ec509ca83a5300f6fa0e99f"); + background-position: left center; + background-repeat: no-repeat; + padding-left: 20px; +} +#dashboard .widget-actions { + float: right; +} +#dashboard .widget-actions a { + cursor: pointer; +} +#dashboard .block-hover { + outline: 2px dashed #ddd; +} +#dashboard .shadow-block { + box-shadow: 8px 8px 8px #ddd; + -moz-box-shadow: 8px 8px 8px #ddd; + -webkit-box-shadow: 8px 8px 8px #ddd; +} +.widget-row { + font-size: 0; + margin: 0 -10px -20px; +} +.widget-span { + display: inline-block; + vertical-align: top; + padding: 0 10px 20px; + -moz-box-sizing: border-box; + box-sizing: border-box; + font-size: 13px; +} +.widget-span-1 { + width: 8.33333333333333%} +.widget-span-2 { + width: 16.66666666666667%} +.widget-span-3 { + width: 25%} +.widget-span-3-5 { + width: 29.16666666666667%} +.widget-span-4 { + width: 33.33333333333333%} +.widget-span-5 { + width: 41.66666666666667%} +.widget-span-6 { + width: 50%} +.widget-span-7 { + width: 58.33333333333333%} +.widget-span-8 { + width: 66.666666666667%} +.widget-span-9 { + width: 75%} +.widget-span-10 { + width: 83.333333333333%} +.widget-span-11 { + width: 91.666666666667%} +.widget-span-12 { + width: 100%} +@media (max-width:1279px) { + .widget-span-1 { + width: 50%} +.widget-span-2 { + width: 50%} +.widget-span-3 { + width: 50%} +.widget-span-3-5 { + width: 50%} +.widget-span-4 { + width: 50%} +.widget-span-5 { + width: 50%} +.widget-span-6 { + width: 50%} +.widget-span-7 { + width: 100%} +.widget-span-8 { + width: 100%} +.widget-span-9 { + width: 100%} +.widget-span-10 { + width: 100%} +.widget-span-11 { + width: 100%} +.widget-span-12 { + width: 100%} +}.widget-label { + display: block; + font-size: 13px; + line-height: 1.2; + font-weight: 300; +} +.widget-number { + color: #236a97; +} +.widget-big { + line-height: 1.5; + font-size: 24px; + font-weight: 300; +} +.widget-medium { + line-height: 1.5; + font-size: 18px; + font-weight: 300; +} +.widget-measure { + display: inline-block; + vertical-align: top; + margin: 0 15px 10px 0; +} +.widget-measure .widget-link, .widget-measure .widget-number { + line-height: 1.5; + font-size: 18px; + font-weight: 300; +} +.widget-measure .widget-label { + text-transform: capitalize; +} +.widget-measure-main { + display: block; + margin-top: 10px; +} +.widget-measure-main .widget-link, .widget-measure-main .widget-number { + line-height: 1.5; + font-size: 24px; + font-weight: 300; +} +.widget-measure-main .widget-label { + font-size: 16px; +} +.widget-measure-container { + margin: -10px 0; +} +.widget-measure-delta { + margin-top: -5px; + margin-bottom: 10px; + line-height: 1.5; +} +.widget-barchar { + line-height: 1; +} +.widget-barchar td { + vertical-align: middle!important; +} +.widget-barchar div.barchart div { + height: 1em; +} +.widget-measure-container .widget-barchar { + margin-bottom: 10px; +} +.widget-measure-container .widget-barchart-more { + margin-top: -5px; + margin-bottom: 10px; + padding-left: 5px; +} +.description-widget-project { + display: inline-block; + line-height: 1.5; + margin-right: 10px; + font-size: 16px; + font-weight: 300; + white-space: nowrap; +} +.description-widget-description { + margin: 7px 0; + line-height: 1.5; +} +.description-widget-key { + color: #777; + font-size: 12px; + font-weight: 300; + white-space: nowrap; +} +.description-widget-links>li { + display: inline-block; + vertical-align: top; + padding: 5px 25px 5px 0; +} +.description-widget-links>li>a { + font-size: 13px; +} +.description-widget-links>li>a>i, .description-widget-links>li>a>i:before { + vertical-align: top; + font-size: 16px; +} +.description-widget-link-data { + margin-top: 7px; +} +.select-list-container { + min-width: 500px; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.select-list-control { + margin-bottom: 10px; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.select-list-list-container { + border: 1px solid #bfbfbf; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.select-list-list-container.loading .select-list-list { + display: none; +} +.select-list-list-container-readonly { + border: none; +} +.select-list-list-container-readonly .select-list-list { + overflow: visible; +} +.select-list-list-container-readonly .select-list-list>li { + border: none; +} +.select-list-list { + overflow-x: hidden; +} +.select-list-list>li { + position: relative; + display: block; + margin-top: -1px; + padding: 5px 10px; + border-top: 1px solid #e0e0e0; + color: #404040; + transition: -webkit-transform .3s ease; + transition: -ms-transform .3s ease; + transition: transform .3s ease; +} +.select-list-list>li.removed { + -webkit-transform: translateX(100%); + -moz-transform: translateX(100%); + -ms-transform: translateX(100%); + -o-transform: translateX(100%); + transform: translateX(100%); +} +.select-list-list>li.added { + -webkit-transform: translateX(-100%); + -moz-transform: translateX(-100%); + -ms-transform: translateX(-100%); + -o-transform: translateX(-100%); + transform: translateX(-100%); +} +.select-list-list>li.progress { + background: url("../images/loading.gif?e2a9308e1360f28fb8fe7ad05eed2e38") no-repeat 10px 5px; +} +.select-list-list>li.progress .select-list-list-checkbox { + visibility: hidden; +} +.select-list-list>li.empty-message { + padding: 6px 5px; + border: 1px solid #ddd; + background-color: #efefef; +} +.select-list-list-checkbox { + display: inline-block; + vertical-align: middle; + margin-right: 10px; +} +.select-list-list-item { + display: inline-block; + vertical-align: middle; +} +.select-list-control { + height: 27px; +} +.select-list-check-control { + float: left; +} +.select-list-check-control.disabled { + filter: alpha(opacity=60); + opacity: .6; +} +.select-list-check-control.disabled .select-list-control-button { + background-color: #fff!important; +} +.select-list-control-button { + position: relative; + z-index: 1; + display: inline-block; + vertical-align: middle; + width: 110px; + height: 27px; + line-height: 25px; + -moz-box-sizing: border-box; + box-sizing: border-box; + border: 1px solid #bfbfbf; + color: #444; + text-align: center; + cursor: pointer; + transition: background-color .2s ease; +} +.select-list-control-button:hover { + background-color: #f6f6f6; + color: #444; +} +.select-list-control-button:active, .select-list-control-button.active { + z-index: 2; + background-color: #efefef; + color: #444; +} +.select-list-control-button+.select-list-control-button { + margin-left: -1px; +} +.select-list-search-control { + position: relative; + float: right; + height: 27px; +} +.select-list-search-control input { + width: 170px; + height: 100%; + line-height: 27px\9; + padding: 0 40px 0 10px; + border: 1px solid #bfbfbf; + -moz-box-sizing: border-box; + box-sizing: border-box; + transition: all .3s ease; +} +.select-list-search-control input:focus { + outline: 0; + box-shadow: none; +} +.select-list-search-control input::-ms-clear { + display: none; +} +.select-list-search-control-clear { + position: absolute; + top: 2px; + right: 2px; + width: 23px; + height: 23px; + line-height: 24px; + background-color: #e0e0e0; + color: #fff; + cursor: pointer; + font-size: 18px; + text-align: center; + transition: all .3s ease; +} +.select-list-search-control.disabled .select-list-search-control-clear { + filter: alpha(opacity=0); + opacity: 0; +} +.select-list-search-control-clear:hover { + background-color: #d6d6d6; +} +.navigator-header { + height: 40px; + margin: 10px; + border: 1px solid #e6e6e6; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.navigator-filters { + position: relative; + margin: 10px; + border: 1px solid #e6e6e6; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.navigator-content { + display: table; + width: 100%} +.navigator-side { + position: relative; + display: table-cell; + vertical-align: top; + width: 340px; + min-width: 295px; + max-width: 620px; +} +.navigator-main { + display: table-cell; + vertical-align: top; +} +.navigator-facets { + margin: 10px; + border: 1px solid #e6e6e6; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.navigator-results { + position: relative; + z-index: 2; + width: 320px; + min-width: 275px; + max-width: 600px; + margin: 10px 10px 0; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.navigator-actions { + position: relative; + z-index: 4; + margin: 0 10px 10px; + border: 1px solid #e6e6e6; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.navigator-actions:before, .navigator-actions:after { + display: table; + content: ""; + line-height: 0; +} +.navigator-actions:after { + clear: both; +} +.navigator-details { + position: relative; + margin: 0 10px 10px; +} +.navigator-resizer { + position: absolute; + top: 50%; + right: -1px; + cursor: col-resize; +} +.navigator-notes { + display: none; +} +.navigator-with-notes .navigator-notes { + display: block; +} +.measures-page .navigator-details { + overflow: visible; +} +.measures-page .page { + padding: 0 0 0 10px; +} +.navigator-fetching:before { + content: " "; + position: absolute; + z-index: 3; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: #fff url("../images/loading.gif?e2a9308e1360f28fb8fe7ad05eed2e38") no-repeat 4px 4px; +} +.navigator-fetching#tab-issue-rule { + position: relative; +} +.navigator-fetching#tab-issue-rule:before { + z-index: 3; + background-color: #EFEFEF; +} +.navigator-fetching.code-issue-actions { + position: relative; +} +.navigator-fetching.code-issue-actions:before { + z-index: 3; + background-color: #E4ECF3; +} +.navigator-page-loader { + padding: 10px 0 0 10px; +} +.navigator-header { + padding: 0 10px; + background-color: #f3f3f3; + font-size: 0; +} +.navigator-header-favorite { + padding-left: 58px; +} +.navigator-header-title { + display: inline-block; + vertical-align: middle; + color: #444; + font-size: 20px; + line-height: 37px; +} +.navigator-header-title-note { + vertical-align: middle; + color: #777; + font-size: 12px; +} +.navigator-header-description { + display: inline-block; + vertical-align: middle; + margin-left: 16px; + font-size: 12px; + font-style: italic; +} +.navigator-header-actions { + margin-left: 20px; +} +.navigator-header-actions>a { + vertical-align: middle; + margin: 0 8px; + font-size: 12px; +} +.navigator-header-menu-toggle { + display: inline-block; + vertical-align: top; + height: 36px; + margin-right: 10px; + margin-left: -10px; + padding: 10px; + border-right: 1px solid transparent; + -moz-box-sizing: border-box; + box-sizing: border-box; + cursor: pointer; + transition: all .2s ease; +} +.navigator-header-menu-toggle:hover { + background-color: #e6e6e6; +} +.navigator-header-menu-toggle.active { + border-color: #cdcdcd; + background-color: #fff; +} +.navigator-header-menu-toggle [class^=icon-], .navigator-header-menu-toggle [class*=" icon-"] { + font-size: 16px; +} +.navigator-notes { + margin: 0 10px 10px; + padding: 0 10px; + border: 1px solid #e6e6e6; + background-color: #f3f3f3; + color: #777; + font-size: 12px; + line-height: 20px; +} +.navigator-facets { + padding: 10px; + border-bottom: 1px solid #e6e6e6; + background-color: #f3f3f3; +} +.navigator-facets-list-item { + font-size: 0; + margin-bottom: -6px; +} +.navigator-facets-list-item+.navigator-facets-list-item { + margin-top: 10px; +} +.navigator-facets-list-item-name { + float: left; + line-height: 22px; + min-width: 120px; + margin-right: 10px; + font-size: 12px; + font-weight: 400; + text-transform: uppercase; +} +.navigator-facets-list-item-options { + overflow: hidden; +} +.navigator-facets-list-item-option { + display: inline-block; + vertical-align: middle; + line-height: 1; + margin: 0 6px 6px; + padding: 4px 5px; + border: 1px solid #e6e6e6; + border-radius: 2px; + background-color: #f8f8f8; + font-size: 0; + font-weight: 300; + cursor: pointer; + transition: all .2s ease; +} +.navigator-facets-list-item-option:hover { + border: 1px solid #4b9fd5; + text-decoration: none; +} +.navigator-facets-list-item-option.active { + border: 1px solid #4b9fd5; + background-color: #cae3f2; + text-decoration: none; +} +.navigator-facets-list-item-option.active .navigator-facets-list-item-option-stat { + border-color: #4b9fd5; +} +.navigator-facets-list-item-option-name { + font-size: 12px; +} +.navigator-facets-list-item-option-stat { + margin-left: 5px; + padding-left: 5px; + border-left: 1px solid #e6e6e6; + color: #777; + font-size: 12px; + transition: all .2s ease; +} +.navigator-results { + background-color: #fff; + overflow-x: hidden; + overflow-y: auto; +} +.navigator-results.fetching .navigator-results-list { + visibility: hidden; +} +.navigator-results.fetching .navigator-results-loader { + display: block; +} +.navigator-results-loader { + position: fixed; + z-index: 10; + display: none; + background-color: #fff; +} +.navigator-results-list>li { + position: relative; + z-index: 1; + padding: 5px 0; + border: 1px solid; + border-color: #e6e6e6 transparent; + cursor: pointer; + transition: all .2s ease; +} +.navigator-results-list>li .line { + padding: 5px 10px; + line-height: 1.2; +} +.navigator-results-list>li .line-small { + font-size: 11px; + line-height: 14px; +} +.navigator-results-list>li .line-right { + float: right; +} +.navigator-results-list>li .line-nowrap { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.navigator-results-list>li:hover { + background-color: #f3f3f3; +} +.navigator-results-list>li.active { + z-index: 2; + background-color: #CAE3F2; + border-color: #4B9FD5; +} +.navigator-results-list>li+li { + margin-top: -1px; +} +.navigator-results-no-results { + padding-top: 20%!important; + background: #fff!important; + border-color: transparent!important; + color: #999; + cursor: default!important; + text-align: center; +} +.navigator-details { + background-color: #fff; + overflow: auto; +} +.navigator-details.loading { + background: #fff url("../images/loading.gif?e2a9308e1360f28fb8fe7ad05eed2e38") no-repeat 4px 2px; +} +.navigator-details .code-issue-name { + border-bottom: none; +} +.navigator-details .code-issue-actions { + background-color: #E4ECF3; +} +.navigator-details .source_title { + z-index: 3; + top: 160px; + left: 320px; + right: 0; + padding: 0 0 10px; + background-color: #fff; +} +.navigator-details .source>table { + border: 1px solid #DDD; +} +.navigator-details .scm .author { + display: inline-block; + vertical-align: middle; + max-width: 100px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.navigator-actions { + padding: 0 10px 0 0; + border-right: 1px solid #e6e6e6; + border-bottom: 1px solid #e6e6e6; + background-color: #f3f3f3; + font-size: 12px; +} +.navigator-actions strong { + font-weight: 700; +} +.navigator-actions-order { + float: left; + padding: 0 10px; + line-height: 30px; + cursor: pointer; + transition: all .2s ease; +} +.navigator-actions-order:hover { + background-color: #e6e6e6; +} +.navigator-actions-order-choices { + position: absolute; + top: 100%; + left: -1px; + min-width: 160px; + background-color: #fff; + border: 1px solid #e6e6e6; + box-shadow: 10px 10px 20px rgba(0, 0, 0, .5); + overflow: hidden; + display: none; +} +.navigator-actions-order-choices>li { + height: 30px; + line-height: 30px; + padding: 0 10px; + cursor: pointer; + transition: all .2s ease; +} +.navigator-actions-order-choices>li:hover { + background-color: #f3f3f3; +} +.navigator-actions-order-choices.open { + display: block; +} +.navigator-actions-total { + float: right; + height: 30px; + line-height: 30px; +} +.navigator-actions-bulk { + position: relative; + top: -1px; + margin-left: 8px; + font-size: 16px; + text-decoration: none; +} +.navigator-page #footer { + margin: 0; + border-top: 1px solid #e6e6e6; +} +.navigator-page #ftlinks { + margin-top: 0; +} +.navigator-filters { + padding-right: 85px; + background-color: #f3f3f3; + font-size: 0; +} +.navigator-filters-list { + display: inline-block; + vertical-align: middle; + font-size: 0; + margin-bottom: -1px; +} +.navigator-filter-submit, .navigator-filter-new-search { + vertical-align: middle; + margin-left: 15px; + font-size: 13px; +} +.navigator-filter-submit { + position: absolute; + bottom: 0; + right: 0; + width: 85px; + height: 40px; + margin: -1px -1px -1px 0; + padding: 0; + border: 1px solid #2d87c0; + background: #4b9fd5; + color: #fff; + font-weight: 400; + transition: all .2s ease; +} +.navigator-filter-submit::-moz-focus-inner { + border: 0; +} +.navigator-filter-submit:hover, .navigator-filter-submit:focus { + border-color: #4b9fd5; + background-color: #74b5df; +} +.navigator-filter-list-favorite { + position: relative; + padding-left: 36px; + overflow: hidden; +} +.navigator-filters-actions { + display: inline-block; + vertical-align: middle; + margin-left: 20px; + font-size: 13px; +} +.navigator-filter { + position: relative; + z-index: 1; + display: inline-block; + vertical-align: top; + height: 40px; + line-height: 37px; + margin: -1px 0 0 -1px; + padding: 0 15px; + border: 1px solid #e6e6e6; + -moz-box-sizing: border-box; + box-sizing: border-box; + white-space: nowrap; + cursor: pointer; + transition: all .2s ease; +} +.navigator-filter:hover { + z-index: 2; + border-color: #e6e6e6; + background-color: #e6e6e6; +} +.navigator-filter.active { + border-color: #cdcdcd; + background: #fff; +} +.navigator-filter-disabled { + display: none; +} +.navigator-filter-optional { + padding-right: 0; +} +.navigator-filter-inline, .navigator-filter-read-only, .navigator-filter-inactive { + cursor: default; +} +.navigator-filter-inline:hover, .navigator-filter-read-only:hover, .navigator-filter-inactive:hover, .navigator-filter-inline.active, .navigator-filter-read-only.active, .navigator-filter-inactive.active { + border-color: transparent; + background: 0 0; +} +.navigator-filter-inline .navigator-filter-label:after { + content: ""} +.navigator-filter-inactive { + opacity: .5; +} +.navigator-filter-context { + z-index: 3; + background-color: #eee1f8; + border-color: #d7b7ef; +} +.navigator-filter-label { + display: inline-block; + vertical-align: middle; + margin-right: 5px; + color: #333; + font-size: 13px; +} +.navigator-filter-label:after { + content: ":"} +.navigator-filter-value { + display: inline-block; + vertical-align: middle; + max-width: 120px; + color: #333; + font-size: 13px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.navigator-filter-value.default { + color: #666; +} +.navigator-filter-disable { + display: inline-block; + vertical-align: middle; + width: 20px; + height: 20px; + line-height: 20px; + margin: 0 0 0 5px; + font-size: 18px; + text-align: center; + transition: background .3s ease; +} +.navigator-filter-disable:hover { + background-color: #d4d4d4; +} +.navigator-filter-range-input { + width: 120px; +} +.navigator-filter-details { + display: none; + position: absolute; + z-index: 1200; + min-width: 100px; + border: 1px solid #cdcdcd; + background: #fff; + box-shadow: 10px 10px 20px rgba(0, 0, 0, .5); + font-size: 13px; + transition: opacity .3s ease; +} +.navigator-filter-details.active { + display: block; +} +@media screen and (-ms-high-contrast:active), (-ms-high-contrast:none) { + .navigator-filter-details { + width: 250px; +} +}.navigator-filter-details-inner { + max-width: 300px; + padding: 5px 10px; +} +.navigator-filter-details-inner .select2-container, .navigator-filter-details-inner input { + margin: 5px 0; + vertical-align: middle; +} +.navigator-filter-select-list { + min-width: 150px; + max-width: 300px; + max-height: 182px; + padding: 5px 0; + overflow-y: auto; + -ms-overflow-style: scrollbar; +} +.navigator-filter-select-list::-webkit-scrollbar { + width: 11px; + background-color: transparent; + background-clip: content-box; +} +.navigator-filter-select-list::-webkit-scrollbar-button { + background-color: transparent; +} +.navigator-filter-select-list::-webkit-scrollbar-corner { + background-color: transparent; +} +.navigator-filter-select-list::-webkit-scrollbar-thumb { + border: solid transparent; + border-width: 1px 1px 1px 2px; + background-color: #c5c5c5; + background-clip: content-box; +} +.navigator-filter-select-list::-webkit-scrollbar-track { + border: solid #fff; + border-width: 1px 1px 1px 2px; + background-color: #fff; + background-clip: content-box; +} +.navigator-filter-select-list::-webkit-scrollbar-track-piece { + border-left: 1px solid #ccc; + background-color: transparent; +} +.navigator-filter-select-list label { + display: block; + padding: 5px 10px; + cursor: pointer; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: background .2s ease; +} +.navigator-filter-select-list label:hover, .navigator-filter-select-list label.current { + background-color: #ededed; +} +.navigator-filter-select-list label>input[type=checkbox] { + vertical-align: baseline; + cursor: pointer; +} +.navigator-filter-select-list label>img { + vertical-align: text-bottom; +} +.navigator-filter-select-list label.special { + font-style: italic; +} +.navigator-filter-select-list label.special>span { + text-decoration: underline; +} +.navigator-filter-select-list label.inactive { + cursor: default; + opacity: .5; +} +.navigator-filter-select-list label.inactive:hover { + background-color: transparent; +} +.navigator-filter-select-list .single { + padding: 5px 10px; +} +.navigator-filter-select-list .line { + height: 1px; + margin: 5px 0; + background: #cdcdcd; +} +.navigator-filter-select-list:not(.hidden)+.navigator-filter-select-list { + margin-top: 5px; + border-top: 1px solid #cdcdcd; +} +.navigator-filter-search { + position: relative; + margin: 10px 26px 10px 10px; +} +.navigator-filter-search input { + width: 100%; + height: 26px; + padding: 0 7px; + border: 1px solid #cdcdcd; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.fetching .navigator-filter-search:after { + content: ' '; + position: absolute; + top: 6px; + right: -21px; + display: block; + width: 16px; + height: 16px; + background: #fff url("../images/loading.gif?e2a9308e1360f28fb8fe7ad05eed2e38") no-repeat center center; +} +.navigator-filter-search.fetching-error input { + border: 2px solid #d4333f; +} +.navigator-filter-load-more { + display: none; + height: 26px; + line-height: 26px; + background-color: #efefef; + text-align: center; + cursor: pointer; + transition: background .3s ease; +} +.navigator-filter-load-more:hover { + background-color: #ddd; +} +.navigator-filter-favorite { + position: absolute; + top: -50px; + left: 0; +} +.navigator-filter-favorite-toggle { + width: 16px; + height: 40px; + background: url("../images/navigator/favorite-filters.png?b417118b9e88b0379652f50519aa0e72") no-repeat center center; +} +@media (-webkit-min-device-pixel-ratio:2), (min-resolution:192dpi) { + .navigator-filter-favorite-toggle { + background-image: url("../images/navigator/favorite-filters@2x.png?10d370e67289463f8791f86812b89e4b"); + background-size: 16px 14px; +} +}.navigator-filter-more-criteria { + font-size: 13px; +} +.api-documentation-navigator .navigator-side { + display: table-cell; + vertical-align: top; + width: 250px; + min-width: 0; +} +.api-documentation-navigator .navigator-header { + margin-left: 0; +} +.api-documentation-navigator .navigator-header .spinner { + margin-top: 9px; +} +.api-documentation-navigator .navigator-actions { + height: 40px; + width: 230px; + margin: 10px; + padding: 0 10px; +} +.api-documentation-navigator .navigator-actions .navigator-header-title { + color: #444; + font-size: 13px; + font-weight: 700; + text-transform: uppercase; +} +.api-documentation-navigator .api-documentation-show-internals { + margin: 10px; + padding: 0 10px; +} +.api-documentation-navigator .navigator-results { + width: 230px; + min-width: 0; +} +.api-documentation-navigator .navigator-details { + margin-left: 0; +} +.api-documentation-navigator .internal { + color: #f3f3f3; + background-color: #7f7f7f; + border-radius: 2px; + padding: 1px 5px; +} +.api-documentation-nav .navigator-results-list>li { + border-color: transparent; +} +.api-documentation-nav .navigator-results-list>li:hover:not(.active):not(.empty) { + background-color: #f3f3f3; +} +.api-documentation-nav .navigator-results-list>li.active { + border-color: #4B9FD5; +} +.api-documentation-nav .navigator-results-list>li.empty { + cursor: default; +} +.api-documentation-nav .navigator-results-list>li .line { + padding-top: 2px; + padding-bottom: 2px; +} +.api-documentation-actions { + margin-top: 10px; + margin-left: 5px; +} +.api-documentation-actions ol li { + list-style: decimal; + margin-left: 2em; +} +.api-documentation-actions .api-documentation-action { + margin-top: 30px; +} +.api-documentation-actions .api-documentation-action>p, .api-documentation-actions .api-documentation-action>h3 { + margin-top: 5px; +} +.api-documentation-actions .api-documentation-action table { + width: 100%} +.api-documentation-actions .api-documentation-action table tr { + border-top: 1px solid #e6e6e6; +} +.api-documentation-actions .api-documentation-action table tr td { + padding: 10px 0 10px 5px; + margin: 5px; + vertical-align: top; +} +.api-documentation-actions .api-documentation-action table tr td ul li { + list-style: square; + margin-left: 2em; +} +.api-documentation-actions .api-documentation-action table tr td ul.possible-values { + display: inline; +} +.api-documentation-actions .api-documentation-action table tr td ul.possible-values li { + display: inline; + margin: 0; +} +.api-documentation-actions .api-documentation-action table tr td ul.possible-values li:before { + content: ', '} +.api-documentation-actions .api-documentation-action table tr td ul.possible-values li:first-child:before { + content: ''} +.api-documentation-actions .api-documentation-action .example-response { + text-decoration: underline; +} +.api-documentation-actions .api-documentation-action .example-response-content { + margin: 10px 0; + padding: 5px; + background-color: #f3f3f3; + border: 1px solid #e6e6e6; +} +.api-documentation-actions .api-documentation-action .example-response-content code { + white-space: pre-wrap; +} +.coding-rules-page .navigator-results .spinner { + margin: 10px; +} +.coding-rules-page .navigator-results .line-right { + margin-top: -14px; + float: none; + text-align: right; +} +.coding-rules-page .navigator-results-list .line { + padding-top: 3px; + padding-bottom: 3px; +} +.coding-rules-page .navigator-results-list .line+.line { + padding-top: 0; +} +.coding-rules-page .navigator-results-list .line-small { + color: #777; +} +.navigator-filter-query { + min-width: 40em; + padding: 0 5px; +} +.navigator-filter-query input { + height: 80%; + width: 100%; + font-size: 13px; + vertical-align: middle; + vertical-align: -webkit-baseline-middle; +} +.coding-rules-detail-header, .coding-rules-detail-title { + position: relative; + margin-bottom: 10px; + line-height: 1.5; + font-weight: 700; +} +.coding-rules-detail-header { + margin-bottom: 0; + padding-right: 100px; + font-size: 18px; +} +.coding-rules-detail-title { + display: inline-block; + margin-top: 30px; + text-transform: uppercase; +} +.coding-rules-detail-permalink { + position: absolute; + top: 0; + right: 0; + font-size: 13px; + font-weight: 400; + text-decoration: none; + transition: all .2s ease; +} +.coding-rules-detail-permalink:hover { + color: #4b9fd5; +} +.coding-rules-detail-context { + margin-bottom: 10px; + padding: 5px; + border: 1px solid #d7b7ef; + background-color: #eee1f8; +} +.coding-rules-detail-context .coding-rules-detail-quality-profile { + margin-left: 0; +} +.coding-rules-detail-context .coding-rules-detail-quality-profile-name, .coding-rules-detail-context .coding-rules-detail-quality-profile-severity, .coding-rules-detail-context .coding-rules-detail-quality-profile-parameters, .coding-rules-detail-context .coding-rules-detail-quality-profile-actions { + vertical-align: top; +} +.coding-rules-detail-context .coding-rules-detail-quality-profile-name, .coding-rules-detail-context .coding-rules-detail-quality-profile-severity { + width: 1px; + padding-right: 10px; + white-space: nowrap; +} +.coding-rules-detail-context .coding-rules-detail-quality-profile-parameter { + display: table-cell; +} +.coding-rules-detail-quality-profile-parameter { + display: block; + height: 100%; + padding-top: 0; + padding-right: 10px; +} +.coding-rules-detail-quality-profile-parameter .key, .coding-rules-detail-quality-profile-parameter .value, .coding-rules-detail-quality-profile-parameter .sep { + display: inline; + vertical-align: top; +} +.coding-rules-detail-quality-profile-parameter .value { + display: inline-block; + max-width: 300px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-family: monospace; + vertical-align: baseline; +} +.coding-rules-detail-quality-profile-parameter+.coding-rules-detail-quality-profile-parameter { + margin-top: 0; +} +.coding-rules-detail-context-actions { + padding: 5px; + background-color: #eee1f8; + border: 1px solid #d7b7ef; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.coding-rules-detail-context-actions-quality-profile { + vertical-align: middle; + margin-right: 10px; + font-weight: 700; +} +.coding-rules-detail-context-actions-item { + display: inline-block; + vertical-align: middle; + margin-right: 10px; +} +.coding-rules-detail-context-actions-item .limited { + display: inline-block; + vertical-align: middle; + max-width: 180px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.coding-rules-detail-context-actions-item .limited-big { + max-width: 480px; +} +.coding-rules-detail-properties { + margin: 10px 0; + font-size: 0; +} +.coding-rules-detail-property { + display: inline-block; + vertical-align: middle; + margin-right: 20px; + font-size: 12px; + height: 22px; + line-height: 22px; +} +.coding-rules-detail-property .select2-search-field { + line-height: 1; +} +.coding-rules-subcharacteristic { + cursor: pointer; +} +.coding-rules-debt-popup h3 { + display: inline; +} +.coding-rules-detail-tag+.coding-rules-detail-tag { + margin-left: 10px; +} +.coding-rules-detail-tags-change { + cursor: pointer; +} +.coding-rules-detail-tags-change:hover span { + text-decoration: underline; +} +.coding-rules-detail-tag-edit { + line-height: 1; +} +.coding-rules-detail-description { + margin: 20px 0; +} +.coding-rules-detail-description-extra { + margin-top: -10px; +} +.coding-rules-detail-extend-description-form { + margin: 10px 0; +} +.coding-rules-detail-parameters { + margin: 10px 0 20px; +} +.coding-rules-detail-parameter { + margin: 10px 0; +} +.coding-rules-detail-parameter-name { + display: block; + margin-left: 20px; + font-weight: 700; + cursor: pointer; +} +.coding-rules-detail-parameter-description { + display: inline-block; + text-overflow: ellipsis; + vertical-align: top; + max-width: 75%; + margin-left: 20px; + padding: 10px; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.coding-rules-detail-parameter-description .subtitle { + margin-top: 10px; + font-size: 13px; +} +.coding-rules-detail-parameter-details { + display: inline-block; + font-size: 13px; + padding-left: 5px; +} +.coding-rules-detail-parameter-original { + margin-left: 10px; + font-size: 12px; +} +.coding-rules-detail-quality-profiles-header { + margin-top: 30px; +} +.coding-rules-detail-quality-profiles { + font-size: 0; +} +.coding-rules-detail-quality-profile { + margin-left: 20px; +} +.coding-rules-detail-quality-profile+.coding-rules-detail-quality-profile { + margin-top: 10px; + padding-top: 10px; + border-top: 1px solid #e6e6e6; +} +.coding-rules-detail-quality-profile-name { + vertical-align: top; + width: 15%; + font-weight: 700; + white-space: nowrap; + padding-right: 5px; +} +.coding-rules-detail-quality-profile-severity { + vertical-align: top; + width: 10%} +.coding-rules-detail-quality-profile-parameters { + vertical-align: top; +} +.coding-rules-detail-quality-profile-parameter+.coding-rules-detail-quality-profile-parameter { + margin-top: 8px; +} +.coding-rules-detail-quality-profile-actions { + vertical-align: top; + width: 25%; + text-align: right; +} +.coding-rules-detail-quality-profile-inheritance { + margin-top: 4px; + font-size: 12px; + font-weight: 400; +} +.coding-rules-detail-quality-profile-inheritance i { + position: relative; + top: -1px; + font-size: 14px; +} +.coding-rules-detail-quality-profiles-activation { + margin-top: -3px; + margin-left: 10px; +} +.coding-rules-detail-quality-profiles-template-caption { + margin-bottom: 10px; +} +.coding-rules-bulk-change-dropdown { + position: absolute; + z-index: 10; + width: 200px; + border: 1px solid #e6e6e6; + -moz-box-sizing: border-box; + box-sizing: border-box; + box-shadow: 10px 10px 20px rgba(0, 0, 0, .5); + background-color: #fff; +} +.coding-rules-bulk-change-dropdown-link { + display: block; + max-width: 190px; + height: 30px; + line-height: 30px; + padding: 0 10px; + font-size: 12px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + border-bottom: none; + transition: all .2s ease; +} +.coding-rules-bulk-change-dropdown-link:hover { + background-color: #f3f3f3; +} +.coding-rules-bulk-change-dropdown-link strong { + font-weight: 700; +} +input.coding-rules-name-key { + width: 30em; +} +[id=coding-rules-detail-custom-rules] { + padding-left: 20px; +} +textarea.coding-rules-markdown-description { + width: 100%; + margin-bottom: 4px; +} +.coding-rules-detail-custom-rule+.coding-rules-detail-custom-rule { + margin-top: 10px; + padding-top: 10px; + border-top: 1px solid #e6e6e6; +} +.coding-rules-detail-custom-rule td { + padding: 10px; +} +.coding-rules-detail-custom-rule-name { + font-weight: 700; +} +.coding-rules-subcharacteristic-more { + display: none; +} +.coding-rules-list-tags { + display: inline-block; + vertical-align: top; + max-width: 50%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.coding-rules-list-tags .icon-tags:before { + font-size: 12px; +} +.component-viewer-source .code pre { + padding: 0; + font-family: 'Source Code Pro', monospace; + font-size: 12px; + line-height: 16px; +} +.component-viewer-source .code .c { + font-style: normal; +} +.component-viewer-source .code .j { + font-style: normal; +} +.component-viewer-source .code .k { + color: #0071ba; + font-weight: 600; +} +.component-viewer-source .code .s { + color: #d4333f; + font-weight: 400; +} +.component-viewer-source .code .p { + font-weight: 400; +} +.component-viewer-source .sym { + color: #5e8c26; +} +.component-viewer { + width: 100%; + min-width: 600px; + border-left-width: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.component-viewer:before, .component-viewer:after { + display: table; + content: ""; + line-height: 0; +} +.component-viewer:after { + clear: both; +} +.component-viewer-workspace-enabled .component-viewer-workspace .component-viewer-workspace-list, .component-viewer-workspace-enabled .component-viewer-workspace .component-viewer-workspace-title { + display: block; +} +.component-viewer-title { + color: #444; + font-size: 13px; + font-weight: 700; +} +.component-viewer-title-separator { + padding: 0 4px; +} +.component-viewer-workspace { + position: relative; + float: left; + min-width: 30px; + margin-right: 10px; + border: 1px solid #e6e6e6; + background-color: #f3f3f3; +} +.component-viewer-workspace.overflow { + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.component-viewer-workspace-header { + position: relative; + height: 30px; + border-bottom: 1px solid #e6e6e6; +} +.component-viewer-workspace-title { + display: none; + padding: 0 30px 0 10px; + line-height: 30px; + text-transform: uppercase; +} +.component-viewer-workspace-list { + display: none; + width: 250px; + padding: 8px 0; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.component-viewer-workspace-item { + padding: 0 10px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.component-viewer-workspace-item.active>a { + font-weight: 700; +} +.component-viewer-workspace-item .subtitle { + line-height: 16px; +} +.component-viewer-workspace-item+.component-viewer-workspace-item { + margin-top: 10px; +} +.component-viewer-workspace-transition { + margin-top: 7px; + margin-left: 7px; + font-size: 12px; +} +.component-viewer-workspace-options { + margin-top: 5px; + margin-left: 7px; + padding-left: 10px; + border-left: 3px solid #cdcdcd; +} +.component-viewer-workspace-option { + line-height: 16px; + padding: 3px 0; +} +.component-viewer-workspace-option.active>a { + font-weight: 700; +} +.component-viewer-workspace-toggle { + position: absolute; + top: 0; + right: 0; + width: 30px; + height: 30px; + transition: all .2s ease; +} +.component-viewer-workspace-toggle:hover { + background-color: #e6e6e6; +} +.component-viewer-source { + position: relative; + float: left; +} +.component-viewer-source.overflow { + -moz-box-sizing: border-box; + box-sizing: border-box; + overflow: auto; +} +.component-viewer-source .code { + width: 100%; + border: 1px solid #e6e6e6; +} +.component-viewer-source .code th { + height: 30px; + -moz-box-sizing: border-box; + box-sizing: border-box; + background-color: #f3f3f3; +} +.component-viewer-source .code th.stat { + padding-top: 4px; + padding-bottom: 4px; + border-left: none; + border-right: none; + border-bottom: 1px solid #e6e6e6; +} +.component-viewer-source .code th.lid { + border-right: 1px solid #e6e6e6; +} +.component-viewer-source .code th.settings { + line-height: 22px; + text-align: left; +} +.component-viewer-source .code th.settings .icon-not-favorite, .component-viewer-source .code th.settings .icon-favorite { + float: right; + padding-top: 2px; +} +.component-viewer-source .code th.settings-toggle { + vertical-align: top; + border-right: 1px solid #e6e6e6; + text-align: center; + white-space: nowrap; +} +.component-viewer-source .code th.settings-toggle .icon-settings { + font-size: 14px; +} +.component-viewer-source .code .row:hover td.stat { + background-color: #e6e6e6; +} +.component-viewer-source .code .row:hover td.line { + background-color: #f3f3f3; +} +.component-viewer-source .code .row-highlighted td.stat, .component-viewer-source .code .row-highlighted:hover td.stat { + background-color: #fdf190; +} +.component-viewer-source .code .row-highlighted td.line, .component-viewer-source .code .row-highlighted:hover td.line, .component-viewer-source .code .row-highlighted .code-issues, .component-viewer-source .code .row-highlighted:hover .code-issues, .component-viewer-source .code .row-highlighted .code-issue, .component-viewer-source .code .row-highlighted:hover .code-issue { + background-color: #fff8c2; +} +.component-viewer-source .code td.line { + width: 100%; + padding: 1px 5px; +} +.component-viewer-source .code .stat { + vertical-align: top; + min-width: 12px; + padding: 1px 5px; + background-color: #f3f3f3; + color: #888; + font-size: 11px; + line-height: 16px; + text-align: right; + cursor: default; + white-space: nowrap; +} +.component-viewer-source .code .lid { + min-width: 18px; + padding-left: 10px; + padding-right: 10px; + cursor: pointer; +} +.component-viewer-source .code .coverage-tests { + cursor: pointer; +} +.component-viewer-source .code .duplications { + padding-top: 0; + padding-bottom: 0; + font-size: 0; +} +.component-viewer-source .code .duplications .duplication { + display: inline-block; + vertical-align: top; + width: 5px; + height: 19px; +} +.component-viewer-source .code .duplications .duplication+.duplication { + margin-left: 2px; +} +.component-viewer-source .code .duplications .duplication-exists { + background-color: #f3ca8e; + cursor: pointer; + transition: all .2s ease; +} +.component-viewer-source .code .duplications .duplication-hover { + background-color: #eeb460; +} +.component-viewer-source .code .measures { + padding: 4px 5px; + border-left: 1px solid #e6e6e6; + border-bottom: 1px solid #e6e6e6; + background-color: #f3f3f3; +} +.component-viewer-source .code .issue>pre { + display: inline-block; + background-image: url("data:image/png; base64, iVBORw0KGgoAAAANSUhEUgAAAAcAAAAGCAYAAAAPDoR2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1M0M2Rjk4M0M3QUYxMUUzODkzRUREMUM5OTNDMjY4QSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1M0M2Rjk4NEM3QUYxMUUzODkzRUREMUM5OTNDMjY4QSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjUzQzZGOTgxQzdBRjExRTM4OTNFREQxQzk5M0MyNjhBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjUzQzZGOTgyQzdBRjExRTM4OTNFREQxQzk5M0MyNjhBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+bcqJtQAAAEhJREFUeNpi+G+swwDGDAwgbAWlwZiJAQFCgfgwEIfDRaC67ID4NRDnQ2kQnwFZwgFqnANMAQOUYY9sF0wBiCGH5CBkrAgQYACuWi4sSGW8yAAAAABJRU5ErkJggg=="); + background-repeat: repeat-x; + background-size: 4px; + background-position: bottom; +} +.component-viewer-source .code .scm { + line-height: 16px; + padding-top: 0; + padding-bottom: 0; + text-align: left; +} +.component-viewer-source .code .scm .scm-date { + display: inline-block; + vertical-align: middle; + padding: 2px 4px; + line-height: 1; + background-color: #e6e6e6; +} +.component-viewer-source .code .scm .scm-author { + display: inline-block; + vertical-align: middle; + max-width: 120px; + padding: 2px 0; + line-height: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.component-viewer-source .code .stat.coverage-green { + background-color: #a9d07b!important; + color: #444; +} +.component-viewer-source .code .stat.coverage-orange { + background-color: #ffb84d!important; + color: #444; +} +.component-viewer-source .code .stat.coverage-red { + background-color: #e1727a!important; + color: #444; +} +.component-viewer-source .code .row-expand .stat, .component-viewer-source .code .row-expand .line { + border-left: none; + border-right: none; + background: url("../images/gray-stripes.png?c0affd395b7ae52801fcae4cbc50fd81") repeat; +} +.component-viewer-source .code .row-expand .line { + text-align: right; +} +.component-viewer-source .code .row-hidden { + display: none; +} +.component-viewer-source-settings { + display: none; +} +.component-viewer-source-settings.open { + display: inline-block; +} +.component-viewer-source-settings>li { + display: inline; + margin-right: 10px; +} +.component-viewer-header { + position: relative; + margin-bottom: 10px; +} +.component-viewer-header-bar { + border: 1px solid #e6e6e6; + background-color: #f3f3f3; +} +.component-viewer-header-bar:before, .component-viewer-header-bar:after { + display: table; + content: ""; + line-height: 0; +} +.component-viewer-header-bar:after { + clear: both; +} +.component-viewer-header-bar+.component-viewer-header-bar { + border-top: 1px solid #e6e6e6; +} +.component-viewer-header-component { + float: left; + line-height: 24px; + padding: 6px 10px; +} +.component-viewer-header-component-project { + color: #777; + font-size: 12px; +} +.component-viewer-header-component-name { + font-weight: 600; +} +.component-viewer-header-favorite { + position: relative; + top: -2px; + margin-left: 4px; + border-bottom: none; +} +.component-viewer-header-measures { + float: right; +} +.component-viewer-header-measures-scope { + position: relative; + float: left; + height: 60px; +} +.component-viewer-header-measures-toggle-scope { + position: absolute; + top: 0; + display: block; + width: 100%; + height: 6px; + margin-bottom: -1px; + border-left: 1px solid #f3f3f3; + -moz-box-sizing: border-box; + box-sizing: border-box; + background-color: #c7e1f2; + border-bottom: none; + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + transition: all .2s ease; +} +.component-viewer-header-measures-toggle-scope:after { + content: " "; + position: absolute; + top: 100%; + width: 100%; + height: 4px; + background-color: transparent; +} +.component-viewer-header-measures-toggle-scope:hover { + background-color: #89c0e3; + -webkit-transform: scale(1, 2); + -ms-transform: scale(1, 2); + transform: scale(1, 2); +} +.component-viewer-header-measures-toggle-scope.active { + background-color: #4b9fd5; +} +.component-viewer-header-measures-toggle-scope.inactive { + background-color: transparent; +} +.component-viewer-header-measures-expand { + display: block; + padding: 11px 20px; + white-space: nowrap; + border-bottom: none; +} +a.component-viewer-header-measures-expand { + transition: background .2s ease; +} +a.component-viewer-header-measures-expand:hover { + background-color: #e6e6e6; +} +a.component-viewer-header-measures-expand:active, a.component-viewer-header-measures-expand.active { + margin-bottom: -1px; + border-bottom: 1px solid #fff; + border-left-color: #e6e6e6; + background-color: #fff; +} +.component-viewer-header-measures-scope+.component-viewer-header-measures-scope { + border-left-color: #e6e6e6; +} +.component-viewer-header-measures-expand .icon-dropdown { + margin-left: 6px; + margin-right: -10px; + color: #444; +} +.component-viewer-header-measure { + display: inline-block; + vertical-align: middle; + font-size: 13px; +} +.component-viewer-header-measure .rating { + font-size: 18px; +} +.component-viewer-header-measure+.component-viewer-header-measure { + margin-left: 15px; +} +.component-viewer-header-measure-label { + display: block; + margin-top: 2px; + color: #777; + font-size: 12px; +} +.component-viewer-header-measure-value { + display: block; + color: #444; + font-size: 18px; + font-weight: 300; +} +.component-viewer-header-measure-value i { + position: relative; + top: -2px; +} +.component-viewer-header-measure-issues { + width: 45px; +} +.component-viewer-header-measure-issue { + min-width: 1px; + height: 6px; +} +.component-viewer-header-measure-issue.s-blocker { + background-color: #d4333f; +} +.component-viewer-header-measure-issue.s-critical { + background-color: #d4333f; +} +.component-viewer-header-measure-issue.s-major { + background-color: #d4333f; +} +.component-viewer-header-measure-issue.s-minor { + background-color: #85bb43; +} +.component-viewer-header-measure-issue.s-info { + background-color: #85bb43; +} +.component-viewer-header-measure-issue+.component-viewer-header-measure-issue { + margin-top: 1px; +} +.component-viewer-header-actions { + float: right; + display: block; + padding: 20px 10px; + font-size: 16px; + border-bottom: none; +} +.component-viewer-header-more-actions { + position: absolute; + z-index: 100; + right: 0; + top: 60px; + padding: 10px; + border: 1px solid #e6e6e6; + background-color: #fff; + line-height: 1.8; +} +.component-viewer-header-expanded-bar { + display: none; + position: relative; + margin-top: -1px; + border: 1px solid #e6e6e6; + border-top: none; + background-color: #fff; +} +.component-viewer-header-expanded-bar:before, .component-viewer-header-expanded-bar:after { + display: table; + content: ""; + line-height: 0; +} +.component-viewer-header-expanded-bar:after { + clear: both; +} +.component-viewer-header-expanded-bar.active { + display: block; +} +.component-viewer-header-expanded-bar-section { + display: inline-block; + vertical-align: top; + width: 250px; +} +.component-viewer-header-expanded-bar-section.large { + width: 350px; +} +.component-viewer-header-expanded-bar-section-actions { + margin-left: 15px; +} +.component-viewer-header-expanded-bar-section-actions .component-viewer-header-expanded-bar-section-list>li { + padding: 4px 0; + line-height: 1.5; +} +.component-viewer-header-expanded-bar-section-title { + padding: 10px 10px 6px; + color: #777; + font-size: 12px; +} +.component-viewer-header-expanded-bar-section-list { + max-height: 120px; + overflow: auto; +} +.component-viewer-header-expanded-bar-section-list::-webkit-scrollbar { + width: 11px; + background-color: transparent; + background-clip: content-box; +} +.component-viewer-header-expanded-bar-section-list::-webkit-scrollbar-button { + background-color: transparent; +} +.component-viewer-header-expanded-bar-section-list::-webkit-scrollbar-corner { + background-color: transparent; +} +.component-viewer-header-expanded-bar-section-list::-webkit-scrollbar-thumb { + border: solid transparent; + border-width: 1px 1px 1px 2px; + background-color: #c5c5c5; + background-clip: content-box; +} +.component-viewer-header-expanded-bar-section-list::-webkit-scrollbar-track { + border: solid #fff; + border-width: 1px 1px 1px 2px; + background-color: #fff; + background-clip: content-box; +} +.component-viewer-header-expanded-bar-section-list::-webkit-scrollbar-track-piece { + border-left: 1px solid #ccc; + background-color: transparent; +} +.component-viewer-header-expanded-bar-section-list>li>.item { + position: relative; + display: block; + padding: 4px 60px 4px 10px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.component-viewer-header-expanded-bar-section-list>li>.item>.number { + position: absolute; + right: 25px; + top: 50%; + margin-top: -8px; +} +.component-viewer-header-expanded-bar-section-list>li>.item>i { + position: absolute; + top: 50%; + right: 10px; + margin-top: -7px; +} +.component-viewer-header-expanded-bar-section-list>li>.item .duration { + display: inline-block; + min-width: 40px; +} +.component-viewer-header-expanded-bar-section-list>li>a.item { + color: #444; + border-bottom: none; + transition: all .2s ease; +} +.component-viewer-header-expanded-bar-section-list>li>a.item:hover { + background-color: #f3f3f3; +} +.component-viewer-header-expanded-bar-section-list>li>a.item:active, .component-viewer-header-expanded-bar-section-list>li>a.item.active { + background-color: #cae3f2; +} +.component-viewer-header-expanded-bar-bulk-change { + position: absolute; + right: 0; + bottom: 0; + padding: 4px 10px; + font-size: 12px; + transition: all .2s ease; +} +.component-viewer-header-expanded-bar-bulk-change:hover { + background-color: #f3f3f3; +} +.component-viewer-header-decoration { + margin-top: 10px; +} +.component-viewer-header-time-changes { + padding: 10px; +} +.component-viewer-header-sqale-rating { + float: left; + font-size: 20px; +} +.component-viewer-popup-test { + position: relative; + display: block; + height: 16px; + line-height: 16px; +} +.component-viewer-popup-test-name { + display: block; + border-left: 20px solid transparent; + border-right: 44px solid transparent; + -moz-box-sizing: border-box; + box-sizing: border-box; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.component-viewer-popup-test-status { + position: absolute; + left: 0; + top: 50%; + margin-top: -8px; +} +.component-viewer-popup-test-duration { + position: absolute; + top: 0; + right: 0; + color: #777; + font-size: 12px; +} +.component-viewer-popup-duplications { + padding: 4px 0; + white-space: normal; +} +.component-viewer-popup-label { + padding-right: 6px; + font-weight: 500; +} +@font-face { + font-family: 'Source Code Pro'; + src: url("../fonts/sourcecodepro-regular.woff?00afed99b3447c000639744c33c850fb") format('woff'); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: 'Source Code Pro'; + src: url("../fonts/sourcecodepro-semibold.woff?55455c9c3f3f6090aed1b37a1c19cbf9") format('woff'); + font-weight: 600; + font-style: normal; +} +.dsm-legend { + margin: 10px 0; +} +.dsm-legend>li { + display: inline-block; +} +.dsm-legend>li+li { + margin-left: 20px; +} +.dsm-legend-square { + display: inline-block; + vertical-align: middle; + width: 14px; + height: 14px; +} +.dsm-legend-square.gray { + background-color: #efefef; +} +.dsm-legend-square.red { + background-color: #d4333f; +} +.dsm-legend-square.green { + background-color: #e2ffbe; +} +.dsm-legend-square.blue { + background-color: #4b9fd5; +} +.dsm-legend-square.yellow { + background-color: #fde9cc; +} +.dsm-legend-label { + display: inline-block; + vertical-align: middle; + font-size: 13px; +} +.dsm-body td { + border: 1px solid #e6e6e6; +} +.dsm-body-title { + position: relative; + vertical-align: middle; + padding: 2px 15px 2px 4px; + border-right: 2px solid #d2d2d2!important; + color: #444; + cursor: pointer; + border-bottom: none; + transition: background-color .2s ease; +} +.dsm-body-title:hover { + background-color: #f3f3f3; +} +.dsm-body-cell { + min-width: 23px; + padding: 2px 4px; + -moz-box-sizing: border-box; + box-sizing: border-box; + text-align: center; + cursor: pointer; + transition: background-color .2s ease; +} +.dsm-body-cell-dependency { + background-color: #efefef; +} +.dsm-body-cell-cycle { + background-color: #d4333f!important; + color: #fff!important; +} +.dsm-body-highlighted { + background-color: #dff2fd; +} +.dsm-body-highlighted:hover { + background-color: #dff2fd; +} +.dsm-body-usage, .dsm-body-usage:hover { + background-color: #e2ffbe; +} +.dsm-body-dependency, .dsm-body-dependency:hover { + background-color: #fde9cc; +} +.dsm-info { + margin-top: 25px; +} +.dsm-info th { + padding: 2px 5px 7px; + font-weight: 500; +} +.dsm-info td { + padding: 2px 5px; +} +.dsm-info td.changed { + padding-top: 7px; +} +.libraries-header { + margin-bottom: 20px; + font-size: 0; +} +.libraries-header-filter, .libraries-header-test, .libraries-header-actions { + display: inline-block; + vertical-align: middle; + font-size: 13px; +} +.libraries-header-test, .libraries-header-actions { + margin-left: 30px; +} +.libraries-header-actions { + margin-right: -10px; +} +.libraries-header-actions a { + margin-right: 10px; +} +.libraries-tree>ul ul { + padding-left: 24px; +} +.libraries-tree>ul ul ul { + margin: 4px 0 4px 8px; + padding-left: 16px; + border-left: 1px dashed #ddd; +} +.libraries-tree>ul>li+li { + margin-top: 15px; +} +.libraries-tree>ul>li>.libraries-tree-name { + font-weight: 500; +} +.libraries-tree li { + padding: 3px 0; +} +.libraries-tree li:last-child { + padding-bottom: 0; +} +.libraries-tree .icon-dropdown { + display: inline-block; + width: 10px; + visibility: hidden; +} +.libraries-tree-subtree-hidden { + display: none; +} +.libraries-tree-with-subtree>.libraries-tree-name { + border-bottom: 1px solid transparent; + cursor: pointer; + transition: all .2s ease; +} +.libraries-tree-with-subtree>.libraries-tree-name:hover { + border-color: #ddd; +} +.libraries-tree-with-subtree>a>.icon-dropdown { + visibility: visible; +} +.libraries-tree-subtree-collapsed>ul { + display: none; +} +.libraries-tree-subtree-collapsed>a>.icon-dropdown:before { + content: "\f0da"} +.libraries-tree-test { + display: none; +} +.libraries-tree-show-tests .libraries-tree-test { + display: list-item; +} +.libraries-tree-version { + margin: 0 3px; + padding: 0 4px; + background: #f3f3f3; +} +.quality-gates-navigator .navigator-side { + display: table-cell; + vertical-align: top; + width: 250px; + min-width: 0; +} +.quality-gates-navigator .navigator-header { + margin-left: 0; +} +.quality-gates-navigator .navigator-header .spinner { + margin-top: 9px; +} +.quality-gates-navigator .navigator-actions { + height: 40px; + width: 230px; + margin: 10px; + padding: 0 10px; +} +.quality-gates-navigator .navigator-actions .navigator-header-title { + color: #444; + font-size: 13px; + font-weight: 700; + text-transform: uppercase; +} +.quality-gates-navigator .navigator-results { + width: 230px; + min-width: 0; +} +.quality-gates-navigator .navigator-details { + margin-left: 0; +} +.quality-gates-nav .navigator-results-list>li { + border-color: transparent; +} +.quality-gates-nav .navigator-results-list>li:hover:not(.active):not(.empty) { + background-color: #f3f3f3; +} +.quality-gates-nav .navigator-results-list>li.active { + border-color: #4B9FD5; +} +.quality-gates-nav .navigator-results-list>li.empty { + cursor: default; +} +.quality-gates-nav .navigator-results-list>li .line { + padding-top: 2px; + padding-bottom: 2px; +} +.quality-gates-nav .navigator-results-list>li .subtitle { + text-transform: lowercase; +} +.quality-gate-section+.quality-gate-section { + margin-top: 10px; + padding-top: 20px; +} +.quality-gate-section-empty+.quality-gate-section { + border-top: 1px solid #e6e6e6; +} +.quality-gate-section-name { + margin-bottom: 10px; + font-weight: 700; + text-transform: uppercase; +} +.quality-gate-introduction { + margin-bottom: 20px; +} +.quality-gate-new-condition { + margin-bottom: 10px; +} +.quality-gate-condition-actions { + position: relative; +} +.quality-gate-default-message { + padding: 6px 5px; + border: 1px solid #ddd; + background-color: #efefef; +} +.quality-gate-conditions-wrap { + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; +} +.quality-gate-conditions .deprecated { + color: #777; + text-transform: lowercase; + font-variant: small-caps; +} +.quality-gate-conditions tbody { + border-left: none!important; + border-right: none!important; +} diff --git a/projects/languages/css/css-sonar-runner/validation.txt b/projects/languages/css/css-sonar-runner/validation.txt new file mode 100644 index 00000000..1a250122 --- /dev/null +++ b/projects/languages/css/css-sonar-runner/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin css 1.5 +sonar-runner +verify org.sonarqube:css-simple-sq-scanner + measure lines is 7258 + measure ncloc is 7254 + measure files is 2 +verify org.sonarqube:css-simple-sq-scanner:src/sonar.css + measure lines is 7169 + measure ncloc is 7165 +stop server diff --git a/projects/languages/erlang/README.md b/projects/languages/erlang/README.md new file mode 100644 index 00000000..b424549f --- /dev/null +++ b/projects/languages/erlang/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a simple Erlang project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Erlang Plugin](https://github.com/SonarCommunity/sonar-erlang) 1.2+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/erlang/sonar-project.properties b/projects/languages/erlang/sonar-project.properties new file mode 100644 index 00000000..7bb015c5 --- /dev/null +++ b/projects/languages/erlang/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:erlang-simple-sq-scanner +sonar.projectName=Erlang :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=erlang + +# Encoding of sources files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/erlang/src/hello.erl b/projects/languages/erlang/src/hello.erl new file mode 100644 index 00000000..cabba3b9 --- /dev/null +++ b/projects/languages/erlang/src/hello.erl @@ -0,0 +1,4 @@ +-module(hello). +-export([hello_world/0]). + +hello_world() -> io:fwrite("hello, world\n"). diff --git a/projects/languages/flex/flex-sonar-runner-coverage/README.md b/projects/languages/flex/flex-sonar-runner-coverage/README.md new file mode 100644 index 00000000..2c58ac18 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner-coverage/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a Flex project with the SonarQube Scanner and retrieving code coverage data from a Cobertura report. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Flex Plugin](http://docs.sonarqube.org/display/PLUG/Flex+Plugin) 2.2.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/flex/flex-sonar-runner-coverage/report/coverage.xml b/projects/languages/flex/flex-sonar-runner-coverage/report/coverage.xml new file mode 100644 index 00000000..ddee7657 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner-coverage/report/coverage.xml @@ -0,0 +1,32 @@ + + + + + + src + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/languages/flex/flex-sonar-runner-coverage/sonar-project.properties b/projects/languages/flex/flex-sonar-runner-coverage/sonar-project.properties new file mode 100644 index 00000000..608514f9 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner-coverage/sonar-project.properties @@ -0,0 +1,16 @@ +# Required metadata +sonar.projectKey=org.sonarqube:flex-coverage-sq-scanner +sonar.projectName=Flex :: Coverage :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=flex + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 + +# Retrieve code coverage data from the Cobertura report +sonar.flex.cobertura.reportPath=report/coverage.xml diff --git a/projects/languages/flex/flex-sonar-runner-coverage/src/Circle.as b/projects/languages/flex/flex-sonar-runner-coverage/src/Circle.as new file mode 100644 index 00000000..b371db1a --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner-coverage/src/Circle.as @@ -0,0 +1,10 @@ +package { + + public class Circle { + public var diameter:int = 0; + + function Circle (d:int) { + this.diameter = d; + } + } +} diff --git a/projects/languages/flex/flex-sonar-runner-coverage/src/UncoveredCircle.as b/projects/languages/flex/flex-sonar-runner-coverage/src/UncoveredCircle.as new file mode 100644 index 00000000..e0a66503 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner-coverage/src/UncoveredCircle.as @@ -0,0 +1,10 @@ +package { + + public class UncoveredCircle { + public var diameter:int = 0; + + function UncoveredCircle (d:int) { + this.diameter = d; + } + } +} diff --git a/projects/languages/flex/flex-sonar-runner-coverage/validation.txt b/projects/languages/flex/flex-sonar-runner-coverage/validation.txt new file mode 100644 index 00000000..9e64d6a9 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner-coverage/validation.txt @@ -0,0 +1,18 @@ +start server + with plugin flex 2.2.1 +sonar-runner +verify org.sonarqube:flex-coverage-sq-scanner + measure lines is 22 + measure ncloc is 16 + measure files is 2 + measure classes is 2 + measure coverage is 50 +verify org.sonarqube:flex-coverage-sq-scanner:src/Circle.as + measure lines is 11 + measure ncloc is 8 + measure coverage is 100 +verify org.sonarqube:flex-coverage-sq-scanner:src/UncoveredCircle.as + measure lines is 11 + measure ncloc is 8 + measure coverage is 0 +stop server diff --git a/projects/languages/flex/flex-sonar-runner/README.md b/projects/languages/flex/flex-sonar-runner/README.md new file mode 100644 index 00000000..ac49377f --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a Flex project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Flex Plugin](http://docs.sonarqube.org/display/PLUG/Flex+Plugin) 2.2.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/flex/flex-sonar-runner/sonar-project.properties b/projects/languages/flex/flex-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..722104e5 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:flex-simple-sq-scanner +sonar.projectName=Flex :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=flex + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/flex/flex-sonar-runner/src/Greeter.as b/projects/languages/flex/flex-sonar-runner/src/Greeter.as new file mode 100644 index 00000000..2471a186 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner/src/Greeter.as @@ -0,0 +1,13 @@ +package +{ + public class Greeter + { + public function sayHello():String + { + var greeting:String; + greeting = "Hello World!"; + if (1 == 1) {} + return greeting; + } + } +} diff --git a/projects/languages/flex/flex-sonar-runner/validation.txt b/projects/languages/flex/flex-sonar-runner/validation.txt new file mode 100644 index 00000000..28e249b7 --- /dev/null +++ b/projects/languages/flex/flex-sonar-runner/validation.txt @@ -0,0 +1,12 @@ +start server + with plugin flex 2.2.1 +sonar-runner +verify org.sonarqube:flex-simple-sq-scanner + measure lines is 14 + measure ncloc is 13 + measure files is 1 + measure classes is 1 +verify org.sonarqube:flex-simple-sq-scanner:src/Greeter.as + measure lines is 14 + measure ncloc is 13 +stop server diff --git a/projects/languages/generic-coverage/sonar-runner/README.md b/projects/languages/generic-coverage/sonar-runner/README.md new file mode 100644 index 00000000..f576c7b2 --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/README.md @@ -0,0 +1,14 @@ +This example demonstrates how to use the generic coverage plugin with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Generic Coverage Plugin](http://docs.sonarqube.org/display/PLUG/Generic+Test+Coverage) 1.2+ +* [SonarQube Javascript Plugin](http://docs.sonarqube.org/display/PLUG/JavaScript+Plugin) 2.12 + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/generic-coverage/sonar-runner/report/coverage.xml b/projects/languages/generic-coverage/sonar-runner/report/coverage.xml new file mode 100644 index 00000000..ac460327 --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/report/coverage.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/projects/languages/generic-coverage/sonar-runner/report/itcoverage.xml b/projects/languages/generic-coverage/sonar-runner/report/itcoverage.xml new file mode 100644 index 00000000..ac460327 --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/report/itcoverage.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/projects/languages/generic-coverage/sonar-runner/report/unittest.xml b/projects/languages/generic-coverage/sonar-runner/report/unittest.xml new file mode 100644 index 00000000..6e4bc9cb --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/report/unittest.xml @@ -0,0 +1,16 @@ + + + + + + message + + + + + + long long stacktrace + + + + diff --git a/projects/languages/generic-coverage/sonar-runner/sonar-project.properties b/projects/languages/generic-coverage/sonar-runner/sonar-project.properties new file mode 100644 index 00000000..bf3d1516 --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/sonar-project.properties @@ -0,0 +1,17 @@ +# Required metadata +sonar.projectKey=org.sonarqube:example-generic-coverage-sonar-scanner +sonar.projectName=Example of Generic Test Coverage Reports Import :: SonarQube Scanner +sonar.projectDescription=Example of Import of UT Execution Results Report and UT/IT Coverage Report Import +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src/main/java,src/main/js +sonar.tests=src/test/java,src/test/js + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 + +sonar.genericcoverage.reportPaths=report/coverage.xml +sonar.genericcoverage.itReportPaths=report/itcoverage.xml +sonar.genericcoverage.unitTestReportPaths=report/unittest.xml + diff --git a/projects/languages/generic-coverage/sonar-runner/src/main/java/FooBar.java b/projects/languages/generic-coverage/sonar-runner/src/main/java/FooBar.java new file mode 100644 index 00000000..e5b8cd77 --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/src/main/java/FooBar.java @@ -0,0 +1,10 @@ +public class FooBar { + + public int process(int a) { + if (a > 1 && a < 10) { + return a; + } + return 0; + } + +} diff --git a/projects/languages/generic-coverage/sonar-runner/src/main/js/foo.js b/projects/languages/generic-coverage/sonar-runner/src/main/js/foo.js new file mode 100644 index 00000000..6ddcc7ac --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/src/main/js/foo.js @@ -0,0 +1,6 @@ +function process() { + if (i > 3) { + return i; + } + return 0; +} diff --git a/projects/languages/generic-coverage/sonar-runner/src/test/java/FooBarTest.java b/projects/languages/generic-coverage/sonar-runner/src/test/java/FooBarTest.java new file mode 100644 index 00000000..9c49f63f --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/src/test/java/FooBarTest.java @@ -0,0 +1,10 @@ +public class FooBar { + + public int test(int a) { + if (a > 1 && a < 10) { + return a; + } + return 0; + } + +} diff --git a/projects/languages/generic-coverage/sonar-runner/src/test/js/test_foo.js b/projects/languages/generic-coverage/sonar-runner/src/test/js/test_foo.js new file mode 100644 index 00000000..6ddcc7ac --- /dev/null +++ b/projects/languages/generic-coverage/sonar-runner/src/test/js/test_foo.js @@ -0,0 +1,6 @@ +function process() { + if (i > 3) { + return i; + } + return 0; +} diff --git a/projects/languages/groovy/groovy-maven/README.md b/projects/languages/groovy/groovy-maven/README.md new file mode 100644 index 00000000..d270c817 --- /dev/null +++ b/projects/languages/groovy/groovy-maven/README.md @@ -0,0 +1,17 @@ +This example demonstrates how to analyze a Groovy project with Maven. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Groovy Plugin](http://docs.sonarqube.org/display/PLUG/Groovy+Plugin) 1.3.1+ +* Maven 3.0+ + +Usage +===== +* Compile the project: + + mvn clean install + +* Analyze it with SonarQube using Maven: + + mvn sonar:sonar diff --git a/projects/languages/groovy/groovy-maven/pom.xml b/projects/languages/groovy/groovy-maven/pom.xml new file mode 100644 index 00000000..639dca67 --- /dev/null +++ b/projects/languages/groovy/groovy-maven/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + org.sonarqube + example-groovy-maven + 1.0-SNAPSHOT + + Simple Groovy Project Analyzed with Maven + + + UTF-8 + grvy + + + + + org.codehaus.groovy + groovy-all + 2.4.7 + + + junit + junit + 3.8.2 + test + + + + + src/main/groovy + + + org.codehaus.gmaven + gmaven-plugin + 1.4 + + 1.8 + + + + + generateStubs + compile + generateTestStubs + testCompile + + + + + + + + diff --git a/projects/languages/groovy/groovy-maven/src/main/groovy/example/Greeting.groovy b/projects/languages/groovy/groovy-maven/src/main/groovy/example/Greeting.groovy new file mode 100644 index 00000000..ef635498 --- /dev/null +++ b/projects/languages/groovy/groovy-maven/src/main/groovy/example/Greeting.groovy @@ -0,0 +1,7 @@ +package example + +class Greeting { + def say() { + println 'Hello World' + } +} diff --git a/projects/languages/groovy/groovy-maven/src/main/groovy/innerclass/InnerClassExample.groovy b/projects/languages/groovy/groovy-maven/src/main/groovy/innerclass/InnerClassExample.groovy new file mode 100644 index 00000000..caf298d2 --- /dev/null +++ b/projects/languages/groovy/groovy-maven/src/main/groovy/innerclass/InnerClassExample.groovy @@ -0,0 +1,14 @@ +package innerclass + +class InnerClassExample +{ + def show() { + println 'Hello World' + new ExampleInnerClass().show() + } + + class ExampleInnerClass { + def show() { println "Hello Inner"} + } + +} diff --git a/projects/languages/groovy/groovy-maven/src/test/groovy/example/GreetingTest.groovy b/projects/languages/groovy/groovy-maven/src/test/groovy/example/GreetingTest.groovy new file mode 100644 index 00000000..a66eb686 --- /dev/null +++ b/projects/languages/groovy/groovy-maven/src/test/groovy/example/GreetingTest.groovy @@ -0,0 +1,7 @@ +package example + +class GreetingTest extends GroovyTestCase { + void testSay() { + new Greeting().say() + } +} diff --git a/projects/languages/groovy/groovy-sonar-runner-cobertura/README.md b/projects/languages/groovy/groovy-sonar-runner-cobertura/README.md new file mode 100644 index 00000000..fb538049 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-cobertura/README.md @@ -0,0 +1,14 @@ +This example demonstrates how to analyze a Groovy project with the SonarQube Scanner. +It reuses existing Cobertura report. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Groovy Plugin](http://docs.sonarqube.org/display/PLUG/Groovy+Plugin) 1.3.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/groovy/groovy-sonar-runner-cobertura/reports/cobertura.xml b/projects/languages/groovy/groovy-sonar-runner-cobertura/reports/cobertura.xml new file mode 100644 index 00000000..4c1a3d29 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-cobertura/reports/cobertura.xml @@ -0,0 +1,58 @@ + + + + + + C:/git/sonar-examples/projects/languages/groovy/groovy-maven/target/generated-sources/groovy-stubs/main + --source + C:/git/sonar-examples/projects/languages/groovy/groovy-maven/src/main/groovy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/languages/groovy/groovy-sonar-runner-cobertura/sonar-project.properties b/projects/languages/groovy/groovy-sonar-runner-cobertura/sonar-project.properties new file mode 100644 index 00000000..644b9527 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-cobertura/sonar-project.properties @@ -0,0 +1,12 @@ +# Required metadata +sonar.projectKey=org.sonarqube:groovy-cobertura-sq-scanner +sonar.projectName=Groovy :: Cobertura :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src +sonar.language=grvy +sonar.sourceEncoding=UTF-8 + +# Path to the Cobertura XML report +sonar.groovy.cobertura.reportPath=reports/cobertura.xml + diff --git a/projects/languages/groovy/groovy-sonar-runner-cobertura/src/example/Greeting.groovy b/projects/languages/groovy/groovy-sonar-runner-cobertura/src/example/Greeting.groovy new file mode 100644 index 00000000..ef635498 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-cobertura/src/example/Greeting.groovy @@ -0,0 +1,7 @@ +package example + +class Greeting { + def say() { + println 'Hello World' + } +} diff --git a/projects/languages/groovy/groovy-sonar-runner-cobertura/src/innerclass/InnerClassExample.groovy b/projects/languages/groovy/groovy-sonar-runner-cobertura/src/innerclass/InnerClassExample.groovy new file mode 100644 index 00000000..caf298d2 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-cobertura/src/innerclass/InnerClassExample.groovy @@ -0,0 +1,14 @@ +package innerclass + +class InnerClassExample +{ + def show() { + println 'Hello World' + new ExampleInnerClass().show() + } + + class ExampleInnerClass { + def show() { println "Hello Inner"} + } + +} diff --git a/projects/languages/groovy/groovy-sonar-runner-cobertura/val.deactivated b/projects/languages/groovy/groovy-sonar-runner-cobertura/val.deactivated new file mode 100644 index 00000000..a5f10734 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-cobertura/val.deactivated @@ -0,0 +1,14 @@ +start server + with plugin groovy 1.3.1 +sonar-runner +verify org.sonarqube:groovy-cobertura-sq-scanner + measure lines is 23 + measure ncloc is 17 + measure files is 2 + measure classes is 3 + measure coverage is 25.0 +verify org.sonarqube:groovy-cobertura-sq-scanner:src/example/Greeting.groovy + measure lines is 8 + measure ncloc is 6 + measure coverage is 100.0 +stop server diff --git a/projects/languages/groovy/groovy-sonar-runner-jacoco/README.md b/projects/languages/groovy/groovy-sonar-runner-jacoco/README.md new file mode 100644 index 00000000..0172d2bd --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-jacoco/README.md @@ -0,0 +1,18 @@ +This example demonstrates how to import JaCoCo reports with a maven project + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Groovy Plugin](http://docs.sonarqube.org/display/PLUG/Groovy+Plugin) 1.3.1+ +* Maven 3.0+ + +Usage +===== +* Compile the project: + + mvn clean install + +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/groovy/groovy-sonar-runner-jacoco/pom.xml b/projects/languages/groovy/groovy-sonar-runner-jacoco/pom.xml new file mode 100644 index 00000000..cfcfb998 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-jacoco/pom.xml @@ -0,0 +1,146 @@ + + + 4.0.0 + + org.sonarqube + groovy-sonar-runner-jacoco + 1.0-SNAPSHOT + + + UTF-8 + UTF-8 + false + false + 0.8.7 + + + + + org.codehaus.groovy + groovy-all + 2.4.7 + + + junit + junit + 4.10 + test + + + org.jacoco + org.jacoco.core + ${jacoco.version} + + + + + src/main/groovy + + + org.codehaus.gmaven + gmaven-plugin + 1.5 + + 2.0 + + + + + generateTestStubs + compile + generateTestStubs + testCompile + + + + + + org.codehaus.groovy + groovy-all + 2.4.7 + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.15 + + ${surefireArgLine} + ${skip.unit.tests} + + **/IT*.groovy + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.15 + + + integration-tests + + integration-test + verify + + + ${failsafeArgLine} + ${skip.integration.tests} + + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + default-prepare-agent + + prepare-agent + + + ${project.build.directory}/coverage-reports/jacoco-ut.exec + surefireArgLine + + + + post-unit-test + test + + report + + + ${project.build.directory}/coverage-reports/jacoco-ut.exec + ${project.reporting.outputDirectory}/jacoco-ut + + + + pre-integration-test + pre-integration-test + + prepare-agent + + + ${project.build.directory}/coverage-reports/jacoco-it.exec + failsafeArgLine + + + + post-integration-test + post-integration-test + + report + + + ${project.build.directory}/coverage-reports/jacoco-it.exec + ${project.reporting.outputDirectory}/jacoco-it + + + + + + + diff --git a/projects/languages/groovy/groovy-sonar-runner-jacoco/sonar-project.properties b/projects/languages/groovy/groovy-sonar-runner-jacoco/sonar-project.properties new file mode 100644 index 00000000..13fee169 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-jacoco/sonar-project.properties @@ -0,0 +1,25 @@ +# Required metadata +sonar.projectKey=org.sonarqube:groovy-jacoco-sq-scanner +sonar.projectName=Groovy :: JaCoCo :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src/main/groovy +# Comma-separated paths to directories with tests (required if you want to load UT Exec Reports) +sonar.tests=src/test/groovy + +# Language +sonar.language=grvy + +# Comma-separated paths to directories with binaries (required) +sonar.binaries=target/classes + +# JaCoCo exec files +sonar.groovy.jacoco.reportPath=target/coverage-reports/jacoco-ut.exec +sonar.groovy.jacoco.itReportPath=target/coverage-reports/jacoco-it.exec + +# Unit Tests Execution Reports +sonar.junit.reportsPath=target/surefire-reports + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/groovy/groovy-sonar-runner-jacoco/src/main/groovy/example/Hello.groovy b/projects/languages/groovy/groovy-sonar-runner-jacoco/src/main/groovy/example/Hello.groovy new file mode 100644 index 00000000..c3ae4f70 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-jacoco/src/main/groovy/example/Hello.groovy @@ -0,0 +1,50 @@ +package example; + +class Hello { + + def name + def innerClass + + Hello(name) { + this.name = name + this.innerClass = new InnerClass() + } + + String salute() { + if (name != null) { + return "Hello $name!" + } + return "Hello!" + } + + def sayHelloToUnitTests() { + println "Hello Unit Tests" + } + + def sayHelloToIntegrationTests() { + println "Hello Integration Tests" + } + + def branches(boolean test) { + if (test) { + println "branch 1" + } else { + println "branch 2" + println "branch 2 bis" + } + } + + def notcovered() { + println "Not covered" + } + + def bar() { + innerClass.foo() + } + + class InnerClass { + void foo() { + println "foo" + } + } +} diff --git a/projects/languages/groovy/groovy-sonar-runner-jacoco/src/test/groovy/example/HelloIT.groovy b/projects/languages/groovy/groovy-sonar-runner-jacoco/src/test/groovy/example/HelloIT.groovy new file mode 100644 index 00000000..a4010d71 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-jacoco/src/test/groovy/example/HelloIT.groovy @@ -0,0 +1,13 @@ +package example; + +import org.junit.Test; + +class HelloIT { + + @Test + void test_sayHelloToIntegrationTests() { + def hello = new Hello() + hello.sayHelloToIntegrationTests() + assert hello != null + } +} diff --git a/projects/languages/groovy/groovy-sonar-runner-jacoco/src/test/groovy/example/HelloTest.groovy b/projects/languages/groovy/groovy-sonar-runner-jacoco/src/test/groovy/example/HelloTest.groovy new file mode 100644 index 00000000..f0c274dc --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner-jacoco/src/test/groovy/example/HelloTest.groovy @@ -0,0 +1,37 @@ +package example; + +import org.junit.Test; + +class HelloTest { + + @Test + void test_salute_full_coverage() { + def hello = new Hello() + assert hello != null + assert hello.name == null + assert hello.salute().equals("Hello!") + + hello = new Hello("Nico") + assert hello != null + assert hello.name != null + assert hello.salute() == "Hello Nico!" + } + + @Test + void test_sayHelloToUnitTests() { + def hello = new Hello() + hello.sayHelloToUnitTests() + } + + @Test + void test_branches_partial_coverage() { + def hello = new Hello() + hello.branches(false); + } + + @Test + void test_inner_class() { + def hello = new Hello() + hello.bar() + } +} diff --git a/projects/languages/groovy/groovy-sonar-runner/README.md b/projects/languages/groovy/groovy-sonar-runner/README.md new file mode 100644 index 00000000..50b9120c --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a Groovy project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Groovy Plugin](http://docs.sonarqube.org/display/PLUG/Groovy+Plugin) 1.3.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner \ No newline at end of file diff --git a/projects/languages/groovy/groovy-sonar-runner/sonar-project.properties b/projects/languages/groovy/groovy-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..48ec5c51 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner/sonar-project.properties @@ -0,0 +1,14 @@ +# Required metadata +sonar.projectKey=org.sonarqube:groovy-simple-sq-scanner +sonar.projectName=Groovy :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=grvy + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 + diff --git a/projects/languages/groovy/groovy-sonar-runner/src/example/Greeting.groovy b/projects/languages/groovy/groovy-sonar-runner/src/example/Greeting.groovy new file mode 100644 index 00000000..ef635498 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner/src/example/Greeting.groovy @@ -0,0 +1,7 @@ +package example + +class Greeting { + def say() { + println 'Hello World' + } +} diff --git a/projects/languages/groovy/groovy-sonar-runner/src/innerclass/InnerClassExample.groovy b/projects/languages/groovy/groovy-sonar-runner/src/innerclass/InnerClassExample.groovy new file mode 100644 index 00000000..caf298d2 --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner/src/innerclass/InnerClassExample.groovy @@ -0,0 +1,14 @@ +package innerclass + +class InnerClassExample +{ + def show() { + println 'Hello World' + new ExampleInnerClass().show() + } + + class ExampleInnerClass { + def show() { println "Hello Inner"} + } + +} diff --git a/projects/languages/groovy/groovy-sonar-runner/validation.txt b/projects/languages/groovy/groovy-sonar-runner/validation.txt new file mode 100644 index 00000000..bfa425be --- /dev/null +++ b/projects/languages/groovy/groovy-sonar-runner/validation.txt @@ -0,0 +1,12 @@ +start server + with plugin groovy 1.3.1 +sonar-runner +verify org.sonarqube:groovy-simple-sq-scanner + measure lines is 23 + measure ncloc is 17 + measure files is 2 + measure classes is 3 +verify org.sonarqube:groovy-simple-sq-scanner:src/example/Greeting.groovy + measure lines is 8 + measure ncloc is 6 +stop server diff --git a/projects/languages/java/ant/java-ant-simple/README.md b/projects/languages/java/ant/java-ant-simple/README.md new file mode 100644 index 00000000..8f14c608 --- /dev/null +++ b/projects/languages/java/ant/java-ant-simple/README.md @@ -0,0 +1,15 @@ +This example demonstrates how to analyze a simple Java project with Ant. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner for Ant](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Ant) 2.4.1+ +* [Ant](http://ant.apache.org/) 1.7.1 or higher + +Usage +===== +* Set the path to the SonarQube Ant Task in the build.xml file +* Set the sonar.jdbc.* properties in the build.xml file +* Run the following command: + + ant all diff --git a/projects/languages/java/ant/java-ant-simple/build.xml b/projects/languages/java/ant/java-ant-simple/build.xml new file mode 100644 index 00000000..2b6e3a77 --- /dev/null +++ b/projects/languages/java/ant/java-ant-simple/build.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/languages/java/ant/java-ant-simple/src/One.java b/projects/languages/java/ant/java-ant-simple/src/One.java new file mode 100644 index 00000000..1ff2941e --- /dev/null +++ b/projects/languages/java/ant/java-ant-simple/src/One.java @@ -0,0 +1,11 @@ +public class One { + String message = "foo"; + + public String foo() { + return message; + } + + public void uncoveredMethod() { + System.out.println(foo()); + } +} diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/README.md b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/README.md new file mode 100644 index 00000000..e2ab2808 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/README.md @@ -0,0 +1,17 @@ +This example demonstrates how to collect code coverage by integration tests, tests are located in a separate Java Maven module. +SonarQube aggregates code coverage by unit tests and integration tests to compute an overall code coverage (this feature requires SonarQube 4.5+). + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* Maven 2.2.1 or higher + +Usage +===== +* Build the project and execute all the tests: + + mvn clean install + +* Analyze the project with SonarQube using Maven: + + mvn sonar:sonar diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app-it/pom.xml b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app-it/pom.xml new file mode 100644 index 00000000..22e1fdcf --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app-it/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + + org.sonarqube + parent + 1.0-SNAPSHOT + + + app-it + + Java :: JaCoco Multi Modules :: App IT + + + + ${project.groupId} + app + ${project.version} + + + + + + + org.jacoco + jacoco-maven-plugin + + + ${project.basedir}/../target/jacoco-it.exec + + + + + + diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app-it/src/test/java/example/HelloWorldIntegrationTest.java b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app-it/src/test/java/example/HelloWorldIntegrationTest.java new file mode 100644 index 00000000..0183c6d7 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app-it/src/test/java/example/HelloWorldIntegrationTest.java @@ -0,0 +1,12 @@ +package example; + +import org.junit.Test; + +public class HelloWorldIntegrationTest { + + @Test + public void test() { + new HelloWorld().coveredByIntegrationTest(); + } + +} diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/pom.xml b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/pom.xml new file mode 100644 index 00000000..d3846cf9 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + + org.sonarqube + parent + 1.0-SNAPSHOT + + + app + + Java :: JaCoco Multi Modules :: App + + diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/src/main/java/example/HelloWorld.java b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/src/main/java/example/HelloWorld.java new file mode 100644 index 00000000..48cb48e6 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/src/main/java/example/HelloWorld.java @@ -0,0 +1,20 @@ +package example; + +public class HelloWorld { + + public void coveredByUnitTest() { + System.out.println("coveredByUnitTest1"); + System.out.println("coveredByUnitTest2"); + } + + public void coveredByIntegrationTest() { + System.out.println("coveredByIntegrationTest1"); + System.out.println("coveredByIntegrationTest2"); + System.out.println("coveredByIntegrationTest3"); + } + + public void notCovered() { + System.out.println("notCovered"); + } + +} diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/src/test/java/example/HelloWorldUnitTest.java b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/src/test/java/example/HelloWorldUnitTest.java new file mode 100644 index 00000000..44231b7f --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/app/src/test/java/example/HelloWorldUnitTest.java @@ -0,0 +1,12 @@ +package example; + +import org.junit.Test; + +public class HelloWorldUnitTest { + + @Test + public void test() { + new HelloWorld().coveredByUnitTest(); + } + +} diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/pom.xml b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/pom.xml new file mode 100644 index 00000000..d4a3d305 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco/pom.xml @@ -0,0 +1,101 @@ + + + 4.0.0 + + org.sonarqube + parent + pom + 1.0-SNAPSHOT + + Java :: JaCoco Multi Modules :: Parent + + + app + app-it + + + + UTF-8 + UTF-8 + + + + ${project.basedir}/../target/jacoco-it.exec + java + + + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + + + + sonar-coverage + + true + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.2.201409121644 + + + + + + org.jacoco + jacoco-maven-plugin + + true + + + + agent-for-ut + + prepare-agent + + + + agent-for-it + + prepare-agent-integration + + + + jacoco-site + verify + + report + + + + + + + + + diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/README.md b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/README.md new file mode 100644 index 00000000..d0f045d1 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/README.md @@ -0,0 +1,14 @@ +This example demonstrates how to collect code coverage by unit tests and integration tests. +SonarQube aggregates these code coverage data to compute an overall code coverage. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.13+ + +Usage +===== +* Analyze the project with SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/classes/example/HelloWorld.class b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/classes/example/HelloWorld.class new file mode 100644 index 00000000..dd0da84b Binary files /dev/null and b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/classes/example/HelloWorld.class differ diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/jacoco/jacoco-it.exec b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/jacoco/jacoco-it.exec new file mode 100644 index 00000000..0d39ceee Binary files /dev/null and b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/jacoco/jacoco-it.exec differ diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/jacoco/jacoco-ut.exec b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/jacoco/jacoco-ut.exec new file mode 100644 index 00000000..fc44ddbc Binary files /dev/null and b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/jacoco/jacoco-ut.exec differ diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/junit/TEST-example.HelloWorldUnitTest.xml b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/junit/TEST-example.HelloWorldUnitTest.xml new file mode 100644 index 00000000..e913fc42 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/junit/TEST-example.HelloWorldUnitTest.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/junit/example.HelloWorldUnitTest.txt b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/junit/example.HelloWorldUnitTest.txt new file mode 100644 index 00000000..d44947ee --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/reports/junit/example.HelloWorldUnitTest.txt @@ -0,0 +1,4 @@ +------------------------------------------------------------------------------- +Test set: example.HelloWorldUnitTest +------------------------------------------------------------------------------- +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.065 sec diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/sonar-project.properties b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/sonar-project.properties new file mode 100644 index 00000000..65b5031a --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/sonar-project.properties @@ -0,0 +1,21 @@ +sonar.projectKey=org.sonarqube:java-ut-it-jacoco-sq-scanner +sonar.projectName=Java :: UT + IT Jacoco :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src/main/java +sonar.tests=src/test/java +sonar.java.binaries=classes + +sonar.language=java + +#Tells SonarQube where the unit tests execution reports are +sonar.junit.reportsPath=reports/junit + +#Tells SonarQube where the unit tests code coverage report is +sonar.jacoco.reportPath=reports/jacoco/jacoco-ut.exec + +#Tells SonarQube where the integration tests code coverage report is +sonar.jacoco.itReportPath=reports/jacoco/jacoco-it.exec + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/src/main/java/example/HelloWorld.java b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/src/main/java/example/HelloWorld.java new file mode 100644 index 00000000..48cb48e6 --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/src/main/java/example/HelloWorld.java @@ -0,0 +1,20 @@ +package example; + +public class HelloWorld { + + public void coveredByUnitTest() { + System.out.println("coveredByUnitTest1"); + System.out.println("coveredByUnitTest2"); + } + + public void coveredByIntegrationTest() { + System.out.println("coveredByIntegrationTest1"); + System.out.println("coveredByIntegrationTest2"); + System.out.println("coveredByIntegrationTest3"); + } + + public void notCovered() { + System.out.println("notCovered"); + } + +} diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/src/test/java/example/HelloWorldUnitTest.java b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/src/test/java/example/HelloWorldUnitTest.java new file mode 100644 index 00000000..44231b7f --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/src/test/java/example/HelloWorldUnitTest.java @@ -0,0 +1,12 @@ +package example; + +import org.junit.Test; + +public class HelloWorldUnitTest { + + @Test + public void test() { + new HelloWorld().coveredByUnitTest(); + } + +} diff --git a/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/validation.txt b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/validation.txt new file mode 100644 index 00000000..60e7a9fe --- /dev/null +++ b/projects/languages/java/code-coverage/combined ut-it/combined-ut-it-sonar-runner-jacoco/validation.txt @@ -0,0 +1,21 @@ +start server + with plugin java 3.10 +sonar-runner +verify org.sonarqube:java-ut-it-jacoco-sq-scanner + measure lines is 21 + measure ncloc is 15 + measure files is 1 + measure classes is 1 + measure tests is 1 + measure test_success_density is 100.0 + measure coverage is 40.0 + measure it_coverage is 50.0 + measure overall_coverage is 80.0 +verify org.sonarqube:java-ut-it-jacoco-sq-scanner:src/main/java/example/HelloWorld.java + measure lines is 21 + measure ncloc is 15 + measure lines_to_cover is 10 + measure uncovered_lines is 6 + measure it_lines_to_cover is 10 + measure it_uncovered_lines is 5 +stop server diff --git a/projects/languages/java/code-coverage/it/it-jacoco-maven/README.md b/projects/languages/java/code-coverage/it/it-jacoco-maven/README.md new file mode 100644 index 00000000..76e782a6 --- /dev/null +++ b/projects/languages/java/code-coverage/it/it-jacoco-maven/README.md @@ -0,0 +1,16 @@ +This example demonstrates how to add information on integration tests coverage for a Java project using JaCoCo and Maven. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* Maven 3.0+ + +Usage +===== +* Build the project and run tests: + + mvn clean install + +* Analyze the project with SonarQube using Maven: + + mvn sonar:sonar diff --git a/projects/languages/java/code-coverage/it/it-jacoco-maven/pom.xml b/projects/languages/java/code-coverage/it/it-jacoco-maven/pom.xml new file mode 100644 index 00000000..103bbd28 --- /dev/null +++ b/projects/languages/java/code-coverage/it/it-jacoco-maven/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + org.sonarqube + example-it-jacoco-maven + 1.0-SNAPSHOT + Java :: IT Coverage with JaCoCo :: Maven + + + UTF-8 + java + + ${project.basedir}/reports/jacoco.exec + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + + diff --git a/projects/languages/java/code-coverage/it/it-jacoco-maven/reports/jacoco.exec b/projects/languages/java/code-coverage/it/it-jacoco-maven/reports/jacoco.exec new file mode 100644 index 00000000..6cb8333a Binary files /dev/null and b/projects/languages/java/code-coverage/it/it-jacoco-maven/reports/jacoco.exec differ diff --git a/projects/languages/java/code-coverage/it/it-jacoco-maven/src/main/java/example/One.java b/projects/languages/java/code-coverage/it/it-jacoco-maven/src/main/java/example/One.java new file mode 100644 index 00000000..52baaaf4 --- /dev/null +++ b/projects/languages/java/code-coverage/it/it-jacoco-maven/src/main/java/example/One.java @@ -0,0 +1,13 @@ +package example; + +public class One { + String message = "foo"; + + public String foo() { + return message; + } + + public void uncoveredMethod() { + System.out.println(foo()); + } +} diff --git a/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/README.md b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/README.md new file mode 100644 index 00000000..c28d7521 --- /dev/null +++ b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to add information on integration tests coverage for a Java project using JaCoCo and SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ + +Usage +===== +* Analyze it with SonarQube using the SonarQube Scanner: + + sonar-scanner + \ No newline at end of file diff --git a/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/classes/One.class b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/classes/One.class new file mode 100644 index 00000000..af32a24d Binary files /dev/null and b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/classes/One.class differ diff --git a/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/reports/jacoco.exec b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/reports/jacoco.exec new file mode 100644 index 00000000..cbe4a740 Binary files /dev/null and b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/reports/jacoco.exec differ diff --git a/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/sonar-project.properties b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..e40b52e8 --- /dev/null +++ b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/sonar-project.properties @@ -0,0 +1,10 @@ +sonar.projectKey=org.sonarqube:example-it-jacoco-sonar-scanner +sonar.projectName=Java :: IT Coverage with JaCoCo :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src +sonar.binaries=classes +sonar.language=java +sonar.sourceEncoding=UTF-8 + +sonar.jacoco.itReportPath=reports/jacoco.exec \ No newline at end of file diff --git a/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/src/One.java b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/src/One.java new file mode 100644 index 00000000..1ff2941e --- /dev/null +++ b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/src/One.java @@ -0,0 +1,11 @@ +public class One { + String message = "foo"; + + public String foo() { + return message; + } + + public void uncoveredMethod() { + System.out.println(foo()); + } +} diff --git a/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/validation.txt b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/validation.txt new file mode 100644 index 00000000..3e59d13f --- /dev/null +++ b/projects/languages/java/code-coverage/it/it-jacoco-sonar-runner/validation.txt @@ -0,0 +1,15 @@ +start server + with plugin java 3.10 +sonar-runner +verify org.sonarqube:example-it-jacoco-sonar-scanner + measure lines is 12 + measure ncloc is 9 + measure files is 1 + measure classes is 1 + measure it_coverage is 60.0 +verify org.sonarqube:example-it-jacoco-sonar-scanner:src/One.java + measure lines is 12 + measure ncloc is 9 + measure it_lines_to_cover is 5 + measure it_uncovered_lines is 2 +stop server diff --git a/projects/languages/java/code-coverage/ut/ut-maven-cobertura/README.md b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/README.md new file mode 100644 index 00000000..78f5690b --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/README.md @@ -0,0 +1,19 @@ +This example demonstrates how to import JUnit and Cobertura reports. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 5.6+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.14+ +* [SonarQube Cobertura Plugin](https://github.com/SonarQubeCommunity/sonar-cobertura) 1.6.3+ +* Maven 3.0+ + +Usage +===== +* Build the project, run the unit tests and generate the Cobertura report in XML format: + + mvn clean compile + mvn cobertura:cobertura -Dcobertura.report.format=xml + +* Analyze the project with SonarQube using Maven: + + mvn sonar:sonar diff --git a/projects/languages/java/code-coverage/ut/ut-maven-cobertura/pom.xml b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/pom.xml new file mode 100644 index 00000000..4d87a602 --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + org.sonarqube + example-ut-maven-cobertura + 1.0-SNAPSHOT + + Java :: UT Coverage with Cobertura :: Maven + + + UTF-8 + target/surefire-reports + target/site/cobertura/coverage.xml + + + + + junit + junit + 4.8.1 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + + + + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + + + + + diff --git a/projects/languages/java/code-coverage/ut/ut-maven-cobertura/src/main/java/example/One.java b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/src/main/java/example/One.java new file mode 100644 index 00000000..52baaaf4 --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/src/main/java/example/One.java @@ -0,0 +1,13 @@ +package example; + +public class One { + String message = "foo"; + + public String foo() { + return message; + } + + public void uncoveredMethod() { + System.out.println(foo()); + } +} diff --git a/projects/languages/java/code-coverage/ut/ut-maven-cobertura/src/test/java/example/OneTest.java b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/src/test/java/example/OneTest.java new file mode 100644 index 00000000..6e1a4fe9 --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-cobertura/src/test/java/example/OneTest.java @@ -0,0 +1,13 @@ +package example; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class OneTest { + @Test + public void testFoo() throws Exception { + One one = new One(); + assertEquals("foo", one.foo()); + } + +} diff --git a/projects/languages/java/code-coverage/ut/ut-maven-jacoco/README.md b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/README.md new file mode 100644 index 00000000..31ce3f59 --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/README.md @@ -0,0 +1,22 @@ +This example demonstrates how to import JUnit and JaCoCo reports. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.13+ +* Maven 3.0+ + + +Usage +===== +* Prepare jacoco agent to allow coverage report generation, build the project, and execute the unit tests: + + mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install + +* To get coverage per tests information, you will need to activate the profile when running the instrumented tests: + + mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install -Pcoverage-per-test + +* Analyze the project with SonarQube using Maven: + + mvn sonar:sonar diff --git a/projects/languages/java/code-coverage/ut/ut-maven-jacoco/pom.xml b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/pom.xml new file mode 100644 index 00000000..21104a68 --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + + org.sonarqube + example-ut-maven-jacoco + 1.0-SNAPSHOT + + Java :: UT Coverage with JaCoCo :: Maven + + + UTF-8 + + + + + junit + junit + + 4.11 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.5 + 1.5 + + + + + + + + + + coverage-per-test + + + + org.apache.maven.plugins + maven-surefire-plugin + + 2.13 + + + + listener + org.sonar.java.jacoco.JUnitListener + + + + + + + + + + org.sonarsource.java + sonar-jacoco-listeners + 3.8 + test + + + + + + + diff --git a/projects/languages/java/code-coverage/ut/ut-maven-jacoco/src/main/java/example/One.java b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/src/main/java/example/One.java new file mode 100644 index 00000000..52933b08 --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/src/main/java/example/One.java @@ -0,0 +1,18 @@ +package example; + +public class One { + String message = "foo"; + String message2 = "toto"; + + public String foo() { + return message; + } + + public String toto() { + return message2; + } + + public void uncoveredMethod() { + System.out.println(foo()); + } +} diff --git a/projects/languages/java/code-coverage/ut/ut-maven-jacoco/src/test/java/example/OneTest.java b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/src/test/java/example/OneTest.java new file mode 100644 index 00000000..113e3e57 --- /dev/null +++ b/projects/languages/java/code-coverage/ut/ut-maven-jacoco/src/test/java/example/OneTest.java @@ -0,0 +1,19 @@ +package example; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class OneTest { + @Test + public void testFoo() throws Exception { + One one = new One(); + assertEquals("foo", one.foo()); + } + + @Test + public void testBoth() throws Exception { + One one = new One(); + assertEquals("toto", one.toto()); + assertEquals("foo", one.foo()); + } +} diff --git a/projects/languages/java/gradle/README.md b/projects/languages/java/gradle/README.md new file mode 100644 index 00000000..747b02e1 --- /dev/null +++ b/projects/languages/java/gradle/README.md @@ -0,0 +1 @@ +For multi-module project samples, see /projects/multi-module/gradle \ No newline at end of file diff --git a/projects/languages/java/gradle/java-gradle-simple/README.md b/projects/languages/java/gradle/java-gradle-simple/README.md new file mode 100644 index 00000000..9c700970 --- /dev/null +++ b/projects/languages/java/gradle/java-gradle-simple/README.md @@ -0,0 +1,12 @@ +This example demonstrates how to analyze a simple Java project with Gradle. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [Gradle](http://www.gradle.org/) 2.1 or higher + +Usage +===== +* Analyze the project with SonarQube using Gradle: + + gradle sonarqube [-Dsonar.host.url=... -Dsonar.jdbc.url=... -Dsonar.jdbc.username=... -Dsonar.jdbc.password=...] diff --git a/projects/languages/java/gradle/java-gradle-simple/build.gradle b/projects/languages/java/gradle/java-gradle-simple/build.gradle new file mode 100644 index 00000000..442f96e6 --- /dev/null +++ b/projects/languages/java/gradle/java-gradle-simple/build.gradle @@ -0,0 +1,41 @@ +// Uses DSL plugins resolution introduced in Gradle 2.1 +plugins { + id "java" + id "jacoco" + id "org.sonarqube" version "1.2" +} + +sonarqube { + properties { + property "sonar.projectName", "Java :: Simple Project :: SonarQube Scanner for Gradle" + property "sonar.projectKey", "org.sonarqube:java-gradle-simple" + property "sonar.jacoco.reportPath", "${project.buildDir}/jacoco/test.exec" + } +} + +allprojects { + ext.baseVersion = "0.1" + ext.snapshotVersion = true + + group = "org.sonarqube" + version = "$baseVersion" + (snapshotVersion ? "-SNAPSHOT" : "") +} + +test { + ignoreFailures = true +} + +dependencies { + testCompile 'junit:junit:4.12' +} + +repositories { + repositories { + maven { + url "http://repo1.maven.org/maven2/" + } + maven { + url "https://plugins.gradle.org/m2/" + } + } +} diff --git a/projects/gradle/src/main/java/example/Greeting.java b/projects/languages/java/gradle/java-gradle-simple/src/main/java/example/Greeting.java similarity index 100% rename from projects/gradle/src/main/java/example/Greeting.java rename to projects/languages/java/gradle/java-gradle-simple/src/main/java/example/Greeting.java diff --git a/projects/languages/java/gradle/java-gradle-simple/src/test/java/example/FailingTest.java b/projects/languages/java/gradle/java-gradle-simple/src/test/java/example/FailingTest.java new file mode 100644 index 00000000..963a4f1a --- /dev/null +++ b/projects/languages/java/gradle/java-gradle-simple/src/test/java/example/FailingTest.java @@ -0,0 +1,16 @@ +package example; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.fail; + +public class FailingTest { + + @Test + public void testAuthenticator() throws Exception { + fail("FAIL!"); + } +} diff --git a/projects/gradle/src/test/java/example/GreetingTest.java b/projects/languages/java/gradle/java-gradle-simple/src/test/java/example/GreetingTest.java similarity index 100% rename from projects/gradle/src/test/java/example/GreetingTest.java rename to projects/languages/java/gradle/java-gradle-simple/src/test/java/example/GreetingTest.java diff --git a/projects/languages/java/maven/java-maven-simple/README.md b/projects/languages/java/maven/java-maven-simple/README.md new file mode 100644 index 00000000..d594a271 --- /dev/null +++ b/projects/languages/java/maven/java-maven-simple/README.md @@ -0,0 +1,17 @@ +This example demonstrates how to analyze a simple Java Maven project. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.13.1+ +* Maven 2.2.1 or higher + +Usage +===== +* Build the project: + + mvn clean install + +* Analyze it with SonarQube using Maven: + + mvn sonar:sonar diff --git a/projects/languages/java/maven/java-maven-simple/pom.xml b/projects/languages/java/maven/java-maven-simple/pom.xml new file mode 100644 index 00000000..b46caa8a --- /dev/null +++ b/projects/languages/java/maven/java-maven-simple/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + org.sonarqube + example-java-maven + 1.0-SNAPSHOT + + Java :: Simple Project :: SonarQube Scanner for Maven + + + UTF-8 + java + + + diff --git a/projects/languages/java/maven/java-maven-simple/src/main/java/example/One.java b/projects/languages/java/maven/java-maven-simple/src/main/java/example/One.java new file mode 100644 index 00000000..52baaaf4 --- /dev/null +++ b/projects/languages/java/maven/java-maven-simple/src/main/java/example/One.java @@ -0,0 +1,13 @@ +package example; + +public class One { + String message = "foo"; + + public String foo() { + return message; + } + + public void uncoveredMethod() { + System.out.println(foo()); + } +} diff --git a/projects/languages/java/sonar-runner/java-sonar-runner-simple/README.md b/projects/languages/java/sonar-runner/java-sonar-runner-simple/README.md new file mode 100644 index 00000000..5a041f2e --- /dev/null +++ b/projects/languages/java/sonar-runner/java-sonar-runner-simple/README.md @@ -0,0 +1,12 @@ +This example demonstrates how to analyze a simple Java project with the Sonar Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/java/sonar-runner/java-sonar-runner-simple/sonar-project.properties b/projects/languages/java/sonar-runner/java-sonar-runner-simple/sonar-project.properties new file mode 100644 index 00000000..9ee18f53 --- /dev/null +++ b/projects/languages/java/sonar-runner/java-sonar-runner-simple/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:java-simple-sq-scanner +sonar.projectName=Java :: Simple Project Not Compiled :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=java + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/java/sonar-runner/java-sonar-runner-simple/src/ComplexMethod.java b/projects/languages/java/sonar-runner/java-sonar-runner-simple/src/ComplexMethod.java new file mode 100644 index 00000000..c942bb96 --- /dev/null +++ b/projects/languages/java/sonar-runner/java-sonar-runner-simple/src/ComplexMethod.java @@ -0,0 +1,28 @@ +public class ComplexMethod { + + public String intToEnglishValue(int i) { + if (i == 1) { + return "One"; + } + if (i == 2) { + return "Two"; + } + if (i == 3) { + return "Three"; + } + if (i == 4) { + return "Four"; + } + if (i == 5) { + return "Five"; + } + if (i == 6) { + return "Six"; + } + if (i > 6) { + throw new NotImplementedException(); + } + return null; + } + +} \ No newline at end of file diff --git a/projects/languages/java/sonar-runner/java-sonar-runner-simple/src/HelloWorld.java b/projects/languages/java/sonar-runner/java-sonar-runner-simple/src/HelloWorld.java new file mode 100644 index 00000000..2d03d228 --- /dev/null +++ b/projects/languages/java/sonar-runner/java-sonar-runner-simple/src/HelloWorld.java @@ -0,0 +1,6 @@ +public class HelloWorld { + + public static void main(String[] args) { + System.out.println("Hello World !"); + } +} diff --git a/projects/languages/java/sonar-runner/java-sonar-runner-simple/validation.txt b/projects/languages/java/sonar-runner/java-sonar-runner-simple/validation.txt new file mode 100644 index 00000000..6e216b77 --- /dev/null +++ b/projects/languages/java/sonar-runner/java-sonar-runner-simple/validation.txt @@ -0,0 +1,15 @@ +start server + with plugin java 3.12 +sonar-runner +verify org.sonarqube:java-simple-sq-scanner + measure lines is 35 + measure ncloc is 31 + measure files is 2 + measure classes is 2 +verify org.sonarqube:java-simple-sq-scanner:src/HelloWorld.java + measure lines is 7 + measure ncloc is 5 +verify org.sonarqube:java-simple-sq-scanner:src/ComplexMethod.java + measure lines is 28 + measure ncloc is 26 +stop server diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/README.md b/projects/languages/javascript/javascript-sonar-runner-lcov/README.md new file mode 100644 index 00000000..bea45e94 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a JavaScript project with the SonarQube Scanner reusing an LCOV report. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [Sonar JavaScript Plugin](http://docs.sonarqube.org/display/PLUG/JavaScript+Plugin) 2.12+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/report/lcov.dat b/projects/languages/javascript/javascript-sonar-runner-lcov/report/lcov.dat new file mode 100644 index 00000000..30b016dd --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/report/lcov.dat @@ -0,0 +1,71 @@ +SF:sources/Person.js +DA:2,1 +DA:3,2 +DA:4,2 +DA:5,2 +DA:8,1 +DA:11,2 +end_of_record +SF:sources/com/company/Car.js +DA:1,1 +DA:2,3 +DA:3,3 +DA:4,3 +DA:5,3 +DA:6,3 +DA:9,1 +DA:12,1 +DA:16,1 +DA:17,0 +DA:18,1 +DA:19,1 +DA:21,0 +DA:26,0 +DA:27,0 +DA:31,0 +DA:32,0 +DA:36,1 +DA:37,0 +DA:38,0 +DA:39,0 +DA:41,1 +DA:42,1 +DA:47,0 +end_of_record +SF:sources/com/company/Truck.js +DA:1,1 +DA:2,0 +DA:3,0 +DA:4,0 +DA:5,0 +DA:6,0 +DA:9,1 +DA:12,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:21,0 +end_of_record +SF:sources/com/company/Vehicle.js +DA:9,1 +DA:10,0 +DA:11,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:22,1 +DA:25,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:50,0 +end_of_record diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/sonar-project.properties b/projects/languages/javascript/javascript-sonar-runner-lcov/sonar-project.properties new file mode 100644 index 00000000..84d1c2e2 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/sonar-project.properties @@ -0,0 +1,13 @@ +sonar.projectKey=org.sonarqube:javascript-lcov-sq-scanner +sonar.projectName=JavaScript :: Coverage LCOV :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.language=js +sonar.sources=sources +sonar.sourceEncoding=UTF-8 + +# Optional +sonar.tests=tests + +# To import the LCOV report +sonar.javascript.lcov.reportPath=report/lcov.dat diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/sources/Person.js b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/Person.js new file mode 100644 index 00000000..f536a4f4 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/Person.js @@ -0,0 +1,14 @@ + +var Person = function(first, last, middle) { + this.first = first; + this.middle = middle; + this.last = last; +}; + +Person.prototype = { + + whoAreYou : function() { + return this.first + (this.middle ? ' ' + this.middle: '') + ' ' + this.last; + } + +}; \ No newline at end of file diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Car.js b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Car.js new file mode 100644 index 00000000..40a9da78 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Car.js @@ -0,0 +1,50 @@ +var Car = function(brand, model, year) { + this.brand = brand; + this.model = model; + this.year = year; + this.engineState = 'stopped'; + this.messageToDriver = ''; +}; + +Car.prototype = { + + getFullName : function() { + return this.brand + ' ' + this.model + ' ' + 'Y: ' + this.year; + }, + + calculatePrice : function() { + if (this.year < 1990) { + return '$1500'; + } else if (this.year > 2011) { + return '$30000'; + } else { + return '$1500 - 30000'; + } + }, + + startEngine : function() { + this.engineState = 'started'; + return 'engine started'; + }, + + stopEngine : function() { + this.engineState = 'stopped'; + return 'engine stopped'; + }, + + stopEngineWithCheck : function() { + if (this.engineState === 'started') { + this.engineState = 'stopped'; + this.messageToDriver = 'all good. c u later'; + return 'engine stopped'; + } else { + this.messageToDriver = 'engine not started. what do you want me to do?'; + return 'engine was not running'; + } + }, + + tuneCar : function() { + this.year = '2011'; + } + +}; \ No newline at end of file diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Truck.js b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Truck.js new file mode 100644 index 00000000..98df0732 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Truck.js @@ -0,0 +1,24 @@ +var Truck = function(brand, model, year) { + this.brand = brand; + this.model = model; + this.year = year; + this.engineState = 'stopped'; + this.messageToDriver = ''; +}; + +Truck.prototype = { + + getFullName : function() { + return this.brand + ' ' + this.model + ' ' + 'Y: ' + this.year; + }, + + calculatePrice : function() { + if (this.year < 1990) { + return '$15000'; + } else if (this.year > 2011) { + return '$300000'; + } else { + return '$15000 - 300000'; + } + } +}; \ No newline at end of file diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Vehicle.js b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Vehicle.js new file mode 100644 index 00000000..e004a007 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/sources/com/company/Vehicle.js @@ -0,0 +1,53 @@ +/** + * This is copy/paste file from Car.js with couple methods removed + * + * Removed methods: + * - startEngine () + * - stopEngine () + * + */ +var Vehicle = function(brand, model, year) { + this.brand = brand; + this.model = model; + this.year = year; + this.engineState = 'stopped'; + this.messageToDriver = ''; +}; + + +// single line comments line 1 +// single line comments line 2 +// single line comments line 3 +// single line comments line 4 +Vehicle.prototype = { + + getFullName : function() { + return this.brand + ' ' + this.model + ' ' + 'Y: ' + this.year; + }, + + calculatePrice : function() { + if (this.year < 1990) { + return '$1500'; + } else if (this.year > 2011) { + return '$30000'; + } else { + return '$1500 - 30000'; + } + }, + + stopEngineWithCheck : function() { + if (this.engineState === 'started') { + this.engineState = 'stopped'; + this.messageToDriver = 'all good. c u later'; + return 'engine stopped'; + } else { + this.messageToDriver = 'engine not started. what do you want me to do?'; + return 'engine was not running'; + } + }, + + tuneCar : function() { + this.year = '2011'; + } + +}; \ No newline at end of file diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/tests/PersonTest.js b/projects/languages/javascript/javascript-sonar-runner-lcov/tests/PersonTest.js new file mode 100644 index 00000000..36b8fb05 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/tests/PersonTest.js @@ -0,0 +1,13 @@ +TestCase('PersonTest', { + + testWhoAreYou : function() { + var p = new Person('John', 'Doe', 'P.'); + assertEquals('Should have responded with full name', 'John P. Doe', p.whoAreYou()); + }, + + testWhoAreYouWithNoMiddleName : function() { + var p = new Person('John', 'Doe'); + assertEquals('Should have used only first and last name', 'John Doe', p.whoAreYou()); + } + +}); \ No newline at end of file diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/tests/com/company/CarTest.js b/projects/languages/javascript/javascript-sonar-runner-lcov/tests/com/company/CarTest.js new file mode 100644 index 00000000..b63b17d1 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/tests/com/company/CarTest.js @@ -0,0 +1,18 @@ +TestCase('com.company.CarTest', { + + testfullName : function() { + var car = new Car('VW', 'Beatle', 1971); + assertEquals('VW Beatle Y: 1971', car.getFullName()); + }, + + testStopEngineWithCheck : function() { + var car = new Car('VW', 'Beatle', 1971); + assertEquals('engine was not running', car.stopEngineWithCheck()); + }, + + testCalculatePrice : function() { + var car = new Car('Volvo', 'XC70', 2012); + assertEquals('$30000', car.calculatePrice()); + } + +}); \ No newline at end of file diff --git a/projects/languages/javascript/javascript-sonar-runner-lcov/validation.txt b/projects/languages/javascript/javascript-sonar-runner-lcov/validation.txt new file mode 100644 index 00000000..05da87c3 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner-lcov/validation.txt @@ -0,0 +1,13 @@ +start server + with plugin javascript 2.11 +sonar-runner +verify org.sonarqube:javascript-lcov-sq-scanner + measure lines is 141 + measure ncloc is 107 + measure files is 4 + measure coverage is 38.1 +verify org.sonarqube:javascript-lcov-sq-scanner:sources/com/company/Car.js + measure lines is 50 + measure ncloc is 42 + measure coverage is 58.3 +stop server diff --git a/projects/languages/javascript/javascript-sonar-runner/README.md b/projects/languages/javascript/javascript-sonar-runner/README.md new file mode 100644 index 00000000..a6f2ae85 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a simple JavaScript project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [Sonar JavaScript Plugin](http://docs.sonarqube.org/display/PLUG/JavaScript+Plugin) 2.12+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/javascript/javascript-sonar-runner/sonar-project.properties b/projects/languages/javascript/javascript-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..21f98643 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:javascript-simple-sq-scanner +sonar.projectName=JavaScript :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=js + +# Encoding of sources files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/javascript/javascript-sonar-runner/src/Person.js b/projects/languages/javascript/javascript-sonar-runner/src/Person.js new file mode 100644 index 00000000..7bde72c7 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner/src/Person.js @@ -0,0 +1,31 @@ +var Person = function(first, last, middle) { + this.first = first; + this.middle = middle; + this.last = last; +}; + +Person.prototype = { + + whoAreYou : function() { + return this.first + (this.middle ? ' ' + this.middle: '') + ' ' + this.last; + } + +}; + +var a = NaN; + +if (a === NaN) { // Noncompliant; always false + console.log("a is not a number"); // this is dead code +} +if (a !== NaN) { // Noncompliant; always true + console.log("a is not NaN"); // this statement is not necessarily true +} + + +for (var i = 0; i < strings.length; i--) { + console.log("dead code") +} + +if (str == null && str.length == 0) { + console.log("String is empty"); +} diff --git a/projects/languages/javascript/javascript-sonar-runner/validation.txt b/projects/languages/javascript/javascript-sonar-runner/validation.txt new file mode 100644 index 00000000..76189fa9 --- /dev/null +++ b/projects/languages/javascript/javascript-sonar-runner/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin javascript 2.11 +sonar-runner +verify org.sonarqube:javascript-simple-sq-scanner + measure lines is 32 + measure ncloc is 23 + measure files is 1 +verify org.sonarqube:javascript-simple-sq-scanner:src/Person.js + measure lines is 32 + measure ncloc is 23 +stop server diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/README.md b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/README.md new file mode 100644 index 00000000..1fb80bb5 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/README.md @@ -0,0 +1,16 @@ +This example demonstrates how to analyze Gradle project with mixed Groovy (Spock) and Java (JUnit) test suite. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Groovy Plugin](http://docs.sonarqube.org/display/PLUG/Groovy+Plugin) 1.3+ + +Usage +===== +* Compile the project: + + ./gradlew check + +* Analyze it with SonarQube using Gradle: + + ./gradlew sonarqube diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/build.gradle b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/build.gradle new file mode 100644 index 00000000..c421ecf2 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/build.gradle @@ -0,0 +1,30 @@ +buildscript { + repositories { + jcenter() + maven { url "https://plugins.gradle.org/m2/" } + } + dependencies { + classpath "org.sonarqube.gradle:gradle-sonarqube-plugin:1.0" + } +} + +apply plugin: 'groovy' +apply plugin: 'jacoco' +apply plugin: 'org.sonarqube' + +repositories { + jcenter() +} + +dependencies { + compile 'org.codehaus.groovy:groovy-all:2.4.7' + + testCompile 'org.spockframework:spock-core:1.0-groovy-2.4' + testCompile 'junit:junit:4.12' +} + +sonarqube { + properties { + property "sonar.groovy.jacoco.reportPath", "$buildDir/jacoco/test.exec" //TODO: Could be set by default when Groovy plugin is detected + } +} diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradle/wrapper/gradle-wrapper.jar b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..b5166dad Binary files /dev/null and b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradle/wrapper/gradle-wrapper.jar differ diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradle/wrapper/gradle-wrapper.properties b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..3d69fde4 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 26 10:21:09 CEST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradlew b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradlew new file mode 100755 index 00000000..91a7e269 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradlew.bat b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/settings.gradle b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/settings.gradle new file mode 100644 index 00000000..69a6ae5d --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'groovy-java-gradle-mixed-tests' diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/main/groovy/sonar/examples/Library.groovy b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/main/groovy/sonar/examples/Library.groovy new file mode 100644 index 00000000..ac7eab1a --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/main/groovy/sonar/examples/Library.groovy @@ -0,0 +1,11 @@ +package sonar.examples + +class Library { + boolean someLibraryMethodJUnit() { + true + } + + boolean someLibraryMethodSpock() { + true + } +} diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/main/groovy/sonar/examples/LibraryJava.java b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/main/groovy/sonar/examples/LibraryJava.java new file mode 100644 index 00000000..6de12f91 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/main/groovy/sonar/examples/LibraryJava.java @@ -0,0 +1,11 @@ +package sonar.examples; + +class LibraryJava { + boolean someLibraryMethodJUnit() { + return true; + } + + boolean someLibraryMethodSpock() { + return true; + } +} diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryJavaSpec.groovy b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryJavaSpec.groovy new file mode 100644 index 00000000..f707a857 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryJavaSpec.groovy @@ -0,0 +1,11 @@ +package sonar.examples + +import spock.lang.Specification + +class LibraryJavaSpec extends Specification { + + def "should be Spock test"() { + expect: + new LibraryJava().someLibraryMethodSpock() + } +} diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryJavaTest.java b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryJavaTest.java new file mode 100644 index 00000000..b30022c4 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryJavaTest.java @@ -0,0 +1,13 @@ +package sonar.examples; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class LibraryJavaTest { + + @Test + public void shouldBeJUnitTest() { + assertTrue(new LibraryJava().someLibraryMethodJUnit()); + } +} diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibrarySpec.groovy b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibrarySpec.groovy new file mode 100644 index 00000000..e596d7f0 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibrarySpec.groovy @@ -0,0 +1,11 @@ +package sonar.examples + +import spock.lang.Specification + +class LibrarySpec extends Specification { + + def "should be Spock test"() { + expect: + new Library().someLibraryMethodSpock() + } +} diff --git a/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryTest.java b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryTest.java new file mode 100644 index 00000000..dc1f9308 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-groovy-tests-gradle/src/test/groovy/sonar/examples/LibraryTest.java @@ -0,0 +1,13 @@ +package sonar.examples; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class LibraryTest { + + @Test + public void shouldBeJUnitTest() { + assertTrue(new Library().someLibraryMethodJUnit()); + } +} diff --git a/projects/languages/multi-language/multi-language-java-javascript-ant/README.md b/projects/languages/multi-language/multi-language-java-javascript-ant/README.md new file mode 100644 index 00000000..4d5cb5ec --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-ant/README.md @@ -0,0 +1,17 @@ +This example demonstrates how to analyze a multi-language project (Java / JavaScript) with the SonarQube Ant Task. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner for Ant](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Ant) 2.4.1+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.13.1+ +* [SonarQube JavaScript Plugin](http://docs.sonarqube.org/display/PLUG/JavaScript+Plugin) 2.12+ +* [Ant](http://ant.apache.org/) 1.7.1+ + +Usage +===== +* Set the path to the SonarQube Ant Task in the build.xml file +* Set the sonar.jdbc.* properties in the build.xml file +* Run the following command: + + ant all diff --git a/projects/languages/multi-language/multi-language-java-javascript-ant/build.xml b/projects/languages/multi-language/multi-language-java-javascript-ant/build.xml new file mode 100644 index 00000000..f5ed71e8 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-ant/build.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/languages/multi-language/multi-language-java-javascript-ant/src/Helloworld.java b/projects/languages/multi-language/multi-language-java-javascript-ant/src/Helloworld.java new file mode 100644 index 00000000..4d4870a6 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-ant/src/Helloworld.java @@ -0,0 +1,8 @@ +public class Helloworld { + + public void helloWorld() { + System.out.println("HelloWorld"); + System.exit(33); + } + +} diff --git a/projects/languages/multi-language/multi-language-java-javascript-ant/src/Person.js b/projects/languages/multi-language/multi-language-java-javascript-ant/src/Person.js new file mode 100644 index 00000000..6bae2cad --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-ant/src/Person.js @@ -0,0 +1,12 @@ + +var Person = function(first, last, middle) { + this.first = first; + this.middle = middle; + this.last = last; +}; +Person.prototype = { + + whoAreYou : function() { + return this.first + (this.middle ? ' ' + this.middle: '') + ' ' + this.last; + } +}; diff --git a/projects/languages/multi-language/multi-language-java-javascript-maven/README.md b/projects/languages/multi-language/multi-language-java-javascript-maven/README.md new file mode 100644 index 00000000..678465ed --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-maven/README.md @@ -0,0 +1,18 @@ +This example demonstrates how to analyze a multi-language project (Java / JavaScript) with Maven. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.13.1+ +* [SonarQube JavaScript Plugin](http://docs.sonarqube.org/display/PLUG/JavaScript+Plugin) 2.12+ +* Maven 3.0+ + +Usage +===== +* Build the project: + + mvn clean install + +* Analyze the project with SonarQube using Maven: + + mvn sonar:sonar diff --git a/projects/languages/multi-language/multi-language-java-javascript-maven/pom.xml b/projects/languages/multi-language/multi-language-java-javascript-maven/pom.xml new file mode 100644 index 00000000..d403ea27 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-maven/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + org.sonarqube + multi-language-project-java-javascript-maven + 1.0-SNAPSHOT + + Java and JavaScript :: SonarQube Scanner for Maven + + + UTF-8 + src + + + diff --git a/projects/languages/multi-language/multi-language-java-javascript-maven/src/main/java/Helloworld.java b/projects/languages/multi-language/multi-language-java-javascript-maven/src/main/java/Helloworld.java new file mode 100644 index 00000000..4d4870a6 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-maven/src/main/java/Helloworld.java @@ -0,0 +1,8 @@ +public class Helloworld { + + public void helloWorld() { + System.out.println("HelloWorld"); + System.exit(33); + } + +} diff --git a/projects/languages/multi-language/multi-language-java-javascript-maven/src/webapp/static/js/Person.js b/projects/languages/multi-language/multi-language-java-javascript-maven/src/webapp/static/js/Person.js new file mode 100644 index 00000000..6bae2cad --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-maven/src/webapp/static/js/Person.js @@ -0,0 +1,12 @@ + +var Person = function(first, last, middle) { + this.first = first; + this.middle = middle; + this.last = last; +}; +Person.prototype = { + + whoAreYou : function() { + return this.first + (this.middle ? ' ' + this.middle: '') + ' ' + this.last; + } +}; diff --git a/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/README.md b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/README.md new file mode 100644 index 00000000..5881996c --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/README.md @@ -0,0 +1,14 @@ +This example demonstrates how to analyze a multi-language project (Java / JavaScript) with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.13.1+ +* [SonarQube JavaScript Plugin](http://docs.sonarqube.org/display/PLUG/JavaScript+Plugin) 2.12+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/classes/Helloworld.class b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/classes/Helloworld.class new file mode 100644 index 00000000..d8f679ad Binary files /dev/null and b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/classes/Helloworld.class differ diff --git a/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/sonar-project.properties b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..6f9e12df --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/sonar-project.properties @@ -0,0 +1,8 @@ +sonar.projectKey=org.sonarqube:multi-language-project-java-javascript-sq-scanner +sonar.projectName=Java and JavaScript :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sourceEncoding=UTF-8 + +sonar.sources=src +sonar.binaries=classes diff --git a/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/src/Helloworld.java b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/src/Helloworld.java new file mode 100644 index 00000000..4d4870a6 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/src/Helloworld.java @@ -0,0 +1,8 @@ +public class Helloworld { + + public void helloWorld() { + System.out.println("HelloWorld"); + System.exit(33); + } + +} diff --git a/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/src/Person.js b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/src/Person.js new file mode 100644 index 00000000..6bae2cad --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/src/Person.js @@ -0,0 +1,12 @@ + +var Person = function(first, last, middle) { + this.first = first; + this.middle = middle; + this.last = last; +}; +Person.prototype = { + + whoAreYou : function() { + return this.first + (this.middle ? ' ' + this.middle: '') + ' ' + this.last; + } +}; diff --git a/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/validation.txt b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/validation.txt new file mode 100644 index 00000000..72739c11 --- /dev/null +++ b/projects/languages/multi-language/multi-language-java-javascript-sonar-runner/validation.txt @@ -0,0 +1,16 @@ +start server + with plugin java 3.7.1 + with plugin javascript 2.8 +sonar-runner +verify org.sonarqube:multi-language-project-java-javascript-sq-scanner + measure lines is 22 + measure ncloc is 16 + measure files is 2 + measure classes is 1 +verify org.sonarqube:multi-language-project-java-javascript-sq-scanner:src/Helloworld.java + measure lines is 9 + measure ncloc is 6 +verify org.sonarqube:multi-language-project-java-javascript-sq-scanner:src/Person.js + measure lines is 13 + measure ncloc is 10 +stop server diff --git a/projects/languages/objc/objc-sonar-runner/README.md b/projects/languages/objc/objc-sonar-runner/README.md new file mode 100644 index 00000000..f6f7dcdc --- /dev/null +++ b/projects/languages/objc/objc-sonar-runner/README.md @@ -0,0 +1,15 @@ +This example demonstrates how to analyze an Objective-C project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarSource Objective-C Plugin](http://www.sonarsource.com/products/plugins/languages/objective-c/) 3.11+ +* [SonarSource Build Wrapper](http://www.sonarsource.com/products/plugins/languages/objective-c/) 3.11+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + /path/to/build-wrapper-macosx-x86 --out-dir out xcodebuild clean build + sonar-scanner diff --git a/projects/languages/objc/objc-sonar-runner/helloworld.xcodeproj/project.pbxproj b/projects/languages/objc/objc-sonar-runner/helloworld.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c132e238 --- /dev/null +++ b/projects/languages/objc/objc-sonar-runner/helloworld.xcodeproj/project.pbxproj @@ -0,0 +1,251 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 041441E4198A725F00234FDF /* Other.m in Sources */ = {isa = PBXBuildFile; fileRef = 041441E3198A725F00234FDF /* Other.m */; }; + 049685BC198A4DDB0048323D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 049685BB198A4DDB0048323D /* Foundation.framework */; }; + 049685BF198A4DDB0048323D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 049685BE198A4DDB0048323D /* main.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 049685B6198A4DDB0048323D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 041441E2198A725F00234FDF /* Other.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Other.h; sourceTree = ""; }; + 041441E3198A725F00234FDF /* Other.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Other.m; sourceTree = ""; }; + 049685B8198A4DDB0048323D /* helloworld */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = helloworld; sourceTree = BUILT_PRODUCTS_DIR; }; + 049685BB198A4DDB0048323D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 049685BE198A4DDB0048323D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 049685B5198A4DDB0048323D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 049685BC198A4DDB0048323D /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 049685AF198A4DDB0048323D = { + isa = PBXGroup; + children = ( + 049685BD198A4DDB0048323D /* helloworld */, + 049685BA198A4DDB0048323D /* Frameworks */, + 049685B9198A4DDB0048323D /* Products */, + ); + sourceTree = ""; + }; + 049685B9198A4DDB0048323D /* Products */ = { + isa = PBXGroup; + children = ( + 049685B8198A4DDB0048323D /* helloworld */, + ); + name = Products; + sourceTree = ""; + }; + 049685BA198A4DDB0048323D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 049685BB198A4DDB0048323D /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 049685BD198A4DDB0048323D /* helloworld */ = { + isa = PBXGroup; + children = ( + 049685BE198A4DDB0048323D /* main.m */, + 041441E2198A725F00234FDF /* Other.h */, + 041441E3198A725F00234FDF /* Other.m */, + ); + path = helloworld; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 049685B7198A4DDB0048323D /* helloworld */ = { + isa = PBXNativeTarget; + buildConfigurationList = 049685C6198A4DDB0048323D /* Build configuration list for PBXNativeTarget "helloworld" */; + buildPhases = ( + 049685B4198A4DDB0048323D /* Sources */, + 049685B5198A4DDB0048323D /* Frameworks */, + 049685B6198A4DDB0048323D /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = helloworld; + productName = helloworld; + productReference = 049685B8198A4DDB0048323D /* helloworld */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 049685B0198A4DDB0048323D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + ORGANIZATIONNAME = helloworld; + }; + buildConfigurationList = 049685B3198A4DDB0048323D /* Build configuration list for PBXProject "helloworld" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 049685AF198A4DDB0048323D; + productRefGroup = 049685B9198A4DDB0048323D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 049685B7198A4DDB0048323D /* helloworld */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 049685B4198A4DDB0048323D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 041441E4198A725F00234FDF /* Other.m in Sources */, + 049685BF198A4DDB0048323D /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 049685C4198A4DDB0048323D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 049685C5198A4DDB0048323D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SDKROOT = macosx; + }; + name = Release; + }; + 049685C7198A4DDB0048323D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 049685C8198A4DDB0048323D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 049685B3198A4DDB0048323D /* Build configuration list for PBXProject "helloworld" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 049685C4198A4DDB0048323D /* Debug */, + 049685C5198A4DDB0048323D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 049685C6198A4DDB0048323D /* Build configuration list for PBXNativeTarget "helloworld" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 049685C7198A4DDB0048323D /* Debug */, + 049685C8198A4DDB0048323D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 049685B0198A4DDB0048323D /* Project object */; +} diff --git a/projects/languages/objc/objc-sonar-runner/helloworld.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/projects/languages/objc/objc-sonar-runner/helloworld.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..60c2c64f --- /dev/null +++ b/projects/languages/objc/objc-sonar-runner/helloworld.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/projects/languages/objc/objc-sonar-runner/helloworld/Other.h b/projects/languages/objc/objc-sonar-runner/helloworld/Other.h new file mode 100644 index 00000000..0b25b669 --- /dev/null +++ b/projects/languages/objc/objc-sonar-runner/helloworld/Other.h @@ -0,0 +1,10 @@ +// +// Other.h +// helloworld +// + +#import + +@interface Other : NSObject +- (void)sayHello; +@end diff --git a/projects/languages/objc/objc-sonar-runner/helloworld/Other.m b/projects/languages/objc/objc-sonar-runner/helloworld/Other.m new file mode 100644 index 00000000..e1f2c22a --- /dev/null +++ b/projects/languages/objc/objc-sonar-runner/helloworld/Other.m @@ -0,0 +1,14 @@ +// +// Other.m +// helloworld +// + +#import + +#import "Other.h" + +@implementation Other +- (void)sayHello { + NSLog(@"Hello, world!"); +} +@end diff --git a/projects/languages/objc/objc-sonar-runner/helloworld/main.m b/projects/languages/objc/objc-sonar-runner/helloworld/main.m new file mode 100644 index 00000000..341eae63 --- /dev/null +++ b/projects/languages/objc/objc-sonar-runner/helloworld/main.m @@ -0,0 +1,23 @@ +// +// main.m +// helloworld +// + +#import "Other.h" + +int main(int argc, const char * argv[]) { + + @autoreleasepool { + int c = 0; + if (argc == 1) { + c = 1; + } else if (argc == 1) { + c = 2; + } else { + } + Other *object = [[Other alloc] init]; + [object sayHello]; + } + return 0; +} + diff --git a/projects/languages/objc/objc-sonar-runner/sonar-project.properties b/projects/languages/objc/objc-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..81ff5fca --- /dev/null +++ b/projects/languages/objc/objc-sonar-runner/sonar-project.properties @@ -0,0 +1,18 @@ +# Required metadata +sonar.projectKey=org.sonarqube:objc-sq-scanner + +sonar.projectName=Objective-C :: Simple :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=helloworld + +sonar.c.file.suffixes= +sonar.objc.file.suffixes=.h,.m + +# The build-wrapper output dir +sonar.cfamily.build-wrapper-output=out + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 + diff --git a/projects/languages/php/php-sonar-runner-unit-tests/README.md b/projects/languages/php/php-sonar-runner-unit-tests/README.md new file mode 100644 index 00000000..272c82e5 --- /dev/null +++ b/projects/languages/php/php-sonar-runner-unit-tests/README.md @@ -0,0 +1,15 @@ +This example demonstrates how to analyze a PHP project with the SonarQube Scanner. +It reuses existing unit test execution and code coverage reports from PHPUnit. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube PHP Plugin](http://docs.sonarqube.org/display/PLUG/PHP+Plugin) 2.8+ + +Usage +===== +* In "reports/phpunit.coverage.xml", change the path "src/Math.php" to the full path of this file on your machine. +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/php/php-sonar-runner-unit-tests/reports/phpunit.coverage.xml b/projects/languages/php/php-sonar-runner-unit-tests/reports/phpunit.coverage.xml new file mode 100644 index 00000000..184a0dd8 --- /dev/null +++ b/projects/languages/php/php-sonar-runner-unit-tests/reports/phpunit.coverage.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/languages/php/php-sonar-runner-unit-tests/reports/phpunit.xml b/projects/languages/php/php-sonar-runner-unit-tests/reports/phpunit.xml new file mode 100644 index 00000000..1942bdf4 --- /dev/null +++ b/projects/languages/php/php-sonar-runner-unit-tests/reports/phpunit.xml @@ -0,0 +1,52 @@ + + + + + + + + PhpUnderControl_Example_MathTest::testSubFail + Failed asserting that 1 matches expected 0. + + + + + + + PhpUnderControl_Example_MathTest::testDataProviderOneWillFail with data set #2 (7, 1) + Failed asserting that 6 matches expected 1. + + + + + + + PhpUnderControl_Example_MathTest::testDataProviderAllWillFail with data set #0 (17, 42) + Failed asserting that -25 matches expected 1. + + + + + PhpUnderControl_Example_MathTest::testDataProviderAllWillFail with data set #1 (13, 23) + Failed asserting that -10 matches expected 1. + + + + PhpUnderControl_Example_MathTest::testDataProviderAllWillFail with data set #2 (42, 17) + Failed asserting that 25 matches expected 1. + + + + PhpUnderControl_Example_MathTest::testDataProviderAllWillFail with data set #3 (23, 13) + Failed asserting that 10 matches expected 1. + + + + + PhpUnderControl_Example_MathTest::testFail + Failed because... + + + + + diff --git a/projects/languages/php/php-sonar-runner-unit-tests/sonar-project.properties b/projects/languages/php/php-sonar-runner-unit-tests/sonar-project.properties new file mode 100644 index 00000000..7f915194 --- /dev/null +++ b/projects/languages/php/php-sonar-runner-unit-tests/sonar-project.properties @@ -0,0 +1,14 @@ +sonar.projectKey=org.sonarqube:php-ut-sq-scanner +sonar.projectName=PHP :: PHPUnit :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src +sonar.tests=tests + +sonar.language=php + +sonar.sourceEncoding=UTF-8 + +# Reusing PHPUnit reports +sonar.php.coverage.reportPath=reports/phpunit.coverage.xml +sonar.php.tests.reportPath=reports/phpunit.xml diff --git a/projects/languages/php/php-sonar-runner-unit-tests/src/Foo/Math5.php b/projects/languages/php/php-sonar-runner-unit-tests/src/Foo/Math5.php new file mode 100644 index 00000000..b06ce5b4 --- /dev/null +++ b/projects/languages/php/php-sonar-runner-unit-tests/src/Foo/Math5.php @@ -0,0 +1,210 @@ +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Manuel Pichler nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package Example + * @author Manuel Pichler + * @copyright 2007-2009 Manuel Pichler. All rights reserved. + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version SVN: $Id: Math.php 4429 2009-01-04 15:39:45Z mapi $ + * @link http://www.phpundercontrol.org/ + */ + +/** + * Simple math class. + * + * @package Example + * @author Manuel Pichler + * @copyright 2007-2009 Manuel Pichler. All rights reserved. + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: 0.5.0 + * @link http://www.phpundercontrol.org/ + */ +class PhpUnderControl_Example2_Math +{ + /** + * Adds the two given values. + * + * @param integer $v1 Value one. + * @param integer $v2 Value two. + * + * @return integer. + */ + public function add($v1 , $v2) + { + return ($v1 + $v2); + } + + /** + * Subtract param two from param one + * + * @param integer $v1 Value one. + * @param integer $v2 Value two. + * + * @return integer. + */ + public function sub($v1, $v2) + { + return ($v1 - $v2); + } + + /** + * Not tested method that should be visible with low coverage. + */ + public function div($v1, $v2) + { + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + return $v8; + } + + /** + * Simple copy for cpd detection. + */ + public function complex($v1, $v2) + { + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end( $d ); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + return $v8; + } +} diff --git a/projects/languages/php/php-sonar-runner-unit-tests/src/Math.php b/projects/languages/php/php-sonar-runner-unit-tests/src/Math.php new file mode 100644 index 00000000..5c1ab480 --- /dev/null +++ b/projects/languages/php/php-sonar-runner-unit-tests/src/Math.php @@ -0,0 +1,214 @@ +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Manuel Pichler nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package Example + * @author Manuel Pichler + * @copyright 2007-2009 Manuel Pichler. All rights reserved. + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version SVN: $Id: Math.php 4429 2009-01-04 15:39:45Z mapi $ + * @link http://www.phpundercontrol.org/ + */ +function add($v1 , $v2) + { + return ($v1 + $v2); + } + +/** + * Simple math class. + * + * @package Example + * @author Manuel Pichler + * @copyright 2007-2009 Manuel Pichler. All rights reserved. + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: 0.5.0 + * @link http://www.phpundercontrol.org/ + */ +class PhpUnderControl_Example_Math +{ + /** + * Adds the two given values. + * + * @param integer $v1 Value one. + * @param integer $v2 Value two. + * + * @return integer. + */ + public function add($v1 , $v2) + { + return ($v1 + $v2); + } + + /** + * Subtract param two from param one + * + * @param integer $v1 Value one. + * @param integer $v2 Value two. + * + * @return integer. + */ + public function sub($v1, $v2) + { + return ($v1 - $v2); + } + + /** + * Not tested method that should be visible with low coverage. + */ + public function div($v1, $v2) + { + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + return $v8; + } + + /** + * Simple copy for cpd detection. + */ + public function complex($v1, $v2) + { + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end( $d ); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + return $v8; + } +} diff --git a/projects/languages/php/php-sonar-runner-unit-tests/tests/SomeTest.php b/projects/languages/php/php-sonar-runner-unit-tests/tests/SomeTest.php new file mode 100644 index 00000000..a5ead9c3 --- /dev/null +++ b/projects/languages/php/php-sonar-runner-unit-tests/tests/SomeTest.php @@ -0,0 +1,169 @@ +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Manuel Pichler nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +require_once dirname(__FILE__) . '/../src/Math.php'; + +/** + * Simple math test class. + * + * @package Example + * @author Manuel Pichler + * @copyright 2007-2009 Manuel Pichler. All rights reserved. + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: 0.5.0 + * @link http://www.phpundercontrol.org/ + */ +class PhpUnderControl_Example_MathTest extends PHPUnit_Framework_TestCase +{ + /** + * The used math object. + * + * @var PhpUnderControl_Example_Math $math + */ + protected $math = null; + + /** + * Creates a new {@link PhpUnderControl_Example_Math} object. + */ + public function setUp() + { + parent::setUp(); + + $this->math = new PhpUnderControl_Example_Math(); + } + + /** + * Successful test. + */ + public function testAddSuccess() + { + sleep(2); + $this->assertEquals(4, $this->math->add(1, 3)); + } + + /** + * Successful test. + */ + public function testSubSuccess() + { + $this->assertEquals( -2, $this->math->sub( 1, 3 ) ); + } + + /** + * Failing test. + */ + public function testSubFail() + { + sleep(2); + $this->assertEquals( 0, $this->math->sub( 2, 1 ) ); + } + + /** + * Test case with data provider. + * + * @dataProvider dataProviderOne + */ + public function testDataProviderOneWillFail( $x, $y ) + { + sleep(1); + $this->assertEquals( 1, $this->math->sub( $x, $y ) ); + } + + /** + * Test case with data provider. + * + * @dataProvider dataProviderTwo + */ + public function testDataProviderAllWillFail( $x, $y ) + { + $this->assertEquals( 1, $this->math->sub( $x, $y ) ); + } + + /** + * Failing test. + */ + public function testFail() + { + $this->fail('Failed because...'); + } + + /** + * Skipping test. + */ + public function testMarkSkip() + { + $this->markTestSkipped('Skipped because...'); + } + + /** + * Skipping test. + */ + public function testMarkIncomplete() + { + $this->markTestIncomplete('Incomplete because...'); + } + + /** + * Example data provider. + * + * @return array(array) + */ + public static function dataProviderOne() + { + return array( + array( 2, 1 ), + array( 3, 2 ), + array( 7, 1 ), + array( 9, 8 ), + ); + } + + /** + * Example data provider. + * + * @return array(array) + */ + public static function dataProviderTwo() + { + return array( + array( 17, 42 ), + array( 13, 23 ), + array( 42, 17 ), + array( 23, 13 ), + ); + } +} diff --git a/projects/languages/php/php-sonar-runner/README.md b/projects/languages/php/php-sonar-runner/README.md new file mode 100644 index 00000000..70c9b27d --- /dev/null +++ b/projects/languages/php/php-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a PHP project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube PHP Plugin](http://docs.sonarqube.org/display/PLUG/PHP+Plugin) 2.8+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/php/php-sonar-runner/sonar-project.properties b/projects/languages/php/php-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..b39c3467 --- /dev/null +++ b/projects/languages/php/php-sonar-runner/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:php-simple-sq-scanner +sonar.projectName=PHP :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=php + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/php/php-sonar-runner/src/Math.php b/projects/languages/php/php-sonar-runner/src/Math.php new file mode 100644 index 00000000..5c1ab480 --- /dev/null +++ b/projects/languages/php/php-sonar-runner/src/Math.php @@ -0,0 +1,214 @@ +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Manuel Pichler nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package Example + * @author Manuel Pichler + * @copyright 2007-2009 Manuel Pichler. All rights reserved. + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version SVN: $Id: Math.php 4429 2009-01-04 15:39:45Z mapi $ + * @link http://www.phpundercontrol.org/ + */ +function add($v1 , $v2) + { + return ($v1 + $v2); + } + +/** + * Simple math class. + * + * @package Example + * @author Manuel Pichler + * @copyright 2007-2009 Manuel Pichler. All rights reserved. + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: 0.5.0 + * @link http://www.phpundercontrol.org/ + */ +class PhpUnderControl_Example_Math +{ + /** + * Adds the two given values. + * + * @param integer $v1 Value one. + * @param integer $v2 Value two. + * + * @return integer. + */ + public function add($v1 , $v2) + { + return ($v1 + $v2); + } + + /** + * Subtract param two from param one + * + * @param integer $v1 Value one. + * @param integer $v2 Value two. + * + * @return integer. + */ + public function sub($v1, $v2) + { + return ($v1 - $v2); + } + + /** + * Not tested method that should be visible with low coverage. + */ + public function div($v1, $v2) + { + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + return $v8; + } + + /** + * Simple copy for cpd detection. + */ + public function complex($v1, $v2) + { + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end( $d ); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + $v3 = $v1 / ($v2 + $v1); + if ($v3 > 14) + { + $v4 = 0; + for ($i = 0; $i < $v3; $i++) + { + $v4 += ($v2 * $i); + } + } + $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); + + $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); + + $d = array($v1, $v2, $v3, $v4, $v5, $v6); + + $v7 = 1; + for ($i = 0; $i < $v6; $i++) + { + shuffle( $d ); + $v7 = $v7 + $i * end($d); + } + + $v8 = $v7; + foreach ( $d as $x ) + { + $v8 *= $x; + } + + return $v8; + } +} diff --git a/projects/languages/php/php-sonar-runner/validation.txt b/projects/languages/php/php-sonar-runner/validation.txt new file mode 100644 index 00000000..c583e11e --- /dev/null +++ b/projects/languages/php/php-sonar-runner/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin php 2.8 +sonar-runner +verify org.sonarqube:php-simple-sq-scanner + measure lines is 215 + measure ncloc is 115 + measure files is 1 +verify org.sonarqube:php-simple-sq-scanner:src/Math.php + measure lines is 215 + measure ncloc is 115 +stop server diff --git a/projects/languages/pli/README.md b/projects/languages/pli/README.md new file mode 100644 index 00000000..457ea0be --- /dev/null +++ b/projects/languages/pli/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a PL/I project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarSource PL/I Plugin](http://www.sonarsource.com/products/plugins/languages/pli/) 1.3.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/pli/sonar-project.properties b/projects/languages/pli/sonar-project.properties new file mode 100644 index 00000000..089dfc6d --- /dev/null +++ b/projects/languages/pli/sonar-project.properties @@ -0,0 +1,17 @@ +# Required metadata +sonar.projectKey=org.sonarqube:pli-simple-sq-scanner +sonar.projectName=PL/I :: Simple :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=pli + +# Properties specific to PL/I +sonar.pli.marginLeft=2 +sonar.pli.marginRight=0 + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/pli/src/center.pli b/projects/languages/pli/src/center.pli new file mode 100644 index 00000000..d6d79e5b --- /dev/null +++ b/projects/languages/pli/src/center.pli @@ -0,0 +1,212 @@ + /* Copyright (c) 1995 by R. A. Vowels, from "Introduction to PL/I, Algorithms, and */ + /* Structured Programming". Permission is given to reproduce and to use these procedures */ + /* as part of a program, and to include them as part of a larger work to be sold for profit. */ + /* However, the user is not permitted to sell the procedures separately. Provided always */ + /* that these procedures and this copyright notice are reproduced in full. */ + + DECLARE CENTERLEFT GENERIC + (CENTER_LEFT_2 WHEN (*, *), + CENTER_LEFT_3 WHEN (*, *, *) ); + DECLARE CENTER GENERIC + (CENTER_LEFT_2 WHEN (*, *), + CENTER_LEFT_3 WHEN (*, *, *) ); + DECLARE CENTERRIGHT GENERIC + (CENTER_RIGHT_2 WHEN (*, *), + CENTER_RIGHT_3 WHEN (*, *, *) ); + DECLARE CENTRELEFT GENERIC + (CENTER_LEFT_2 WHEN (*, *), + CENTER_LEFT_3 WHEN (*, *, *) ); + DECLARE CENTRERIGHT GENERIC + (CENTER_RIGHT_2 WHEN (*, *), + CENTER_RIGHT_3 WHEN (*, *, *) ); + /* This procedure returns a string of length LEN, with STRING in the dead center, or one */ + /* position to the left of dead center if it cannot be dead center. */ + CENTER_LEFT_2: + PROCEDURE (STRING, LEN) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be centered; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* centered. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + + DECLARE WORK CHARACTER (LEN); + DECLARE (K, L) FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + K = (LEN - L + 2)/2; + + WORK = ''; + SUBSTR (WORK, K, L) = STRING; + RETURN (WORK); + END CENTER_LEFT_2; + + /* This procedure returns a string of length LEN, with STRING in the dead center, or one */ + /* position to the left of dead center if it cannot be dead center. A specified fill */ + /* character FILL extends STRING right and left. */ + CENTER_LEFT_3: + PROCEDURE (STRING, LEN, FILL) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be centered; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* centered. */ + /* FILL = a fill character used to extend STRING at both ends. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + DECLARE FILL CHARACTER (1); + + DECLARE WORK CHARACTER (LEN); + DECLARE (K, L) FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + K = (LEN - L + 2)/2; + + WORK = REPEAT (FILL, LEN-1); + SUBSTR (WORK, K, L) = STRING; + RETURN (WORK); + END CENTER_LEFT_3; + + /* This procedure returns a string of length LEN, with STRING in the dead center, or one */ + /* position to the right of dead center if it cannot be dead center. */ + CENTER_RIGHT_2: + PROCEDURE (STRING, LEN) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be centered; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* centered. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + + DECLARE WORK CHARACTER (LEN); + DECLARE (K, L) FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + K = (LEN - L + 3)/2; + + WORK = ''; + SUBSTR (WORK, K, L) = STRING; + RETURN (WORK); + END CENTER_RIGHT_2; + + /* This procedure returns a string of length LEN, with STRING in the dead center, or one */ + /* position to the right of dead center if it cannot be dead center. A specified fill */ + /* character FILL extends STRING right and left. */ + CENTER_RIGHT_3: + PROCEDURE (STRING, LEN, FILL) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be centered; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* centered. */ + /* FILL = a fill character used to extend STRING at both ends. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + DECLARE FILL CHARACTER (1); + + DECLARE WORK CHARACTER (LEN); + DECLARE (K, L) FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + K = (LEN - L + 3)/2; + + WORK = REPEAT (FILL, LEN-1); + SUBSTR (WORK, K, L) = STRING; + RETURN (WORK); + END CENTER_RIGHT_3; + + DECLARE LEFT GENERIC + (LEFT_blank WHEN (*,*), + LEFT_other WHEN (*,*,*) ); + + /* This procedure returns STRING in a string of length LEN, with blank characters padded on */ + /* the right. */ + LEFT_blank: + PROCEDURE (STRING, LEN) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be positioned left; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* placed. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + + DECLARE WORK CHARACTER (LEN); + DECLARE L FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + WORK = ''; + SUBSTR (WORK, 1, L) = STRING; + RETURN (WORK); + END LEFT_blank; + + /* This procedure returns STRING in a string of length LEN, padded with the character */ + /* FILL on the right. */ + LEFT_other: + PROCEDURE (STRING, LEN, FILL) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be positioned left; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* positioned left; */ + /* FILL = the character to be used to fill out the finished string. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + DECLARE FILL CHARACTER (1); + + DECLARE WORK CHARACTER (LEN); + DECLARE L FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + WORK = STRING || REPEAT (FILL, LEN-L-1); + RETURN (WORK); + END LEFT_other; + + DECLARE RIGHT GENERIC + (RIGHT_blank WHEN (*,*), + RIGHT_other WHEN (*,*,*) ); + + /* This procedure returns STRING right-adjusted in a string of length N, padded with blanks */ + /* on the left. */ + RIGHT_blank: + PROCEDURE (STRING, LEN) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be positioned right; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* positioned right. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + + DECLARE WORK CHARACTER (LEN); + DECLARE L FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + WORK = ''; + SUBSTR (WORK, LEN-L+1, L) = STRING; + RETURN (WORK); + END RIGHT_blank; + + /* This procedure returns STRING right-adjusted in a string of length N, padded with the */ + /* character FILL on the left. */ + RIGHT_other: + PROCEDURE (STRING, LEN, FILL) RETURNS (CHARACTER(1000) VARYING); + /* INCOMING: STRING = the string to be positioned right; */ + /* LEN = the length of the produced string in which STRING is to be */ + /* positioned right; */ + /* FILL = the character to be used to fill out the finished string. */ + DECLARE STRING CHARACTER (*) VARYING; + DECLARE LEN FIXED BINARY; + DECLARE FILL CHARACTER (1); + + DECLARE WORK CHARACTER (LEN); + DECLARE L FIXED BINARY; + + L = LENGTH (STRING); + IF L >= LEN THEN RETURN (STRING); + + WORK = REPEAT (FILL, LEN-L-1) || STRING; + RETURN (WORK); + END RIGHT_other; diff --git a/projects/languages/pli/src/chess.pli b/projects/languages/pli/src/chess.pli new file mode 100644 index 00000000..f1e9c1aa --- /dev/null +++ b/projects/languages/pli/src/chess.pli @@ -0,0 +1,760 @@ + /* This is a chess program written in PL/I. */ + /* The original was written in Fortran 90 by Dean Menezes. */ + /* This translation by R. A. Vowels, 30 May 2008. */ + /* Moves are input in this form: */ + /* E2-E4 (start square, hyphen, end square). */ + + /* Sources: */ + + /* http://ai-depot.com/articles/minimax-explained/ */ + /* http://www.aihorizon.com/essays/chessai/index.htm */ + /* http://www.ascotti.org/programming/chess/Shannon%20-%20Programming + %20a%20computer%20for%20playing%20chess.pdf */ + + (SUBRG, SIZE, FOFL, STRINGRANGE, STRINGSIZE): + CHESS: PROCEDURE OPTIONS (MAIN, REORDER); + /* Global variables: */ + /* level = current recursion level for calculation */ + /* maxlevel = maximum recursion level */ + /* score = current score (evaluation) */ + /* besta, bestb, bestx, besty = holds best moves for each recursion level */ + /* wcksflag, wcqsflag = flags to detemine castling abilities */ + /* board = the 8x8 array to hold chessboard */ + DECLARE ( MAXLEVEL VALUE ( 5) ) FIXED BINARY; + DECLARE ( LEVEL, SCORE, BESTA(0:7) ) FIXED BINARY (31); + DECLARE ( BESTB(1:MAXLEVEL), BESTX(1:MAXLEVEL), BESTY(1:MAXLEVEL) ) FIXED + BINARY (31); + DECLARE ( WCKSFLAG, WCQSFLAG ) BIT(1) ALIGNED; + DECLARE ( A, B, X, Y, RES ) FIXED BINARY (31); + + + /* initialize board to starting position */ + DECLARE BOARD(0:7, 0:7) FIXED BINARY (31) STATIC INITIAL ( + -500, -270, -300, -900, -7500, -300, -270, -500, + -100, -100, -100, -100, -100, -100, -100, -100, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 100, 100, 100, 100, 100, 100, 100, + 500, 270, 300, 900, 5000, 300, 270, 500 ); + + LEVEL=0; A=-1; RES=0; + WCKSFLAG = '0'B ; WCQSFLAG = '0'B; + /* main loop: get white move from user, calculate black move */ + DO FOREVER; + SCORE=0; + CALL IO(A, B, X, Y, RES); + RES=EVALUATE(-1, 10000); + A=BESTA(1); B=BESTB(1); X=BESTX(1); Y=BESTY(1); + END; + + /* figure out if white is in check */ + INCHECK: PROCEDURE () RETURNS( FIXED BINARY (31)) OPTIONS (REORDER); + DECLARE (XX(0:26), YY(0:26), CC(0:26)) FIXED BINARY (31); + DECLARE (I, A, B, X, Y, NDX) FIXED BINARY (31); + + DO B = 0 TO 7; + DO A = 0 TO 7; + IF BOARD(B, A)>=0 THEN + ITERATE; + CALL MOVELIST(A, B, XX, YY, CC, NDX); + /* iterate through move list and see if */ + /* piece can get to king */ + DO I = 0 TO NDX BY 1; + X = XX(I); + Y = YY(I); + IF BOARD(Y, X) = 5000 THEN + RETURN (1); + END; + END; + END; + RETURN (0); + END INCHECK; + + EVALUATE: PROCEDURE (ID, PRUNE) RETURNS ( FIXED BINARY (31) ) RECURSIVE; + DECLARE ( ID, PRUNE ) FIXED BINARY (31); + /* local variables. */ + DECLARE ( XX(0:26), YY(0:26), CC(0:26) ) FIXED BINARY (31); + DECLARE ( A, B, X, Y, C, OLDSCORE, BESTSCORE, MOVER, TARG, NDX, + I ) FIXED BINARY (31); + + LEVEL=LEVEL+1; + BESTSCORE=10000*ID; + DO B=7 TO 0 BY -1; + DO A=7 TO 0 BY -1; + /* generate the moves for all the pieces */ + /* and iterate through them */ + IF SIGN(BOARD(B,A))^=ID THEN + ITERATE; + CALL MOVELIST (A, B, XX, YY, CC, NDX); + DO I=0 TO NDX BY 1; + X=XX(I); Y=YY(I); C=CC(I); + OLDSCORE=SCORE; MOVER=BOARD(B,A); TARG=BOARD(Y,X); + /* make the move and evaluate the new position */ + /* recursively. Targ holds the relative value of the piece */ + /* allowing use to calculate material gain/loss */ + CALL MAKEMOVE (A, B, X, Y, C); + IF LEVELBESTSCORE) | (ID>0 & SCORE=PRUNE) | (ID>0 & BESTSCORE<=PRUNE) THEN + DO; + BOARD(B,A)=MOVER; BOARD(Y,X)=TARG; SCORE=OLDSCORE; + LEVEL=LEVEL-1; + RETURN (BESTSCORE); + END; + END; + BOARD(B,A)=MOVER; BOARD(Y,X)=TARG; SCORE=OLDSCORE; + END; + END; + END; + LEVEL=LEVEL-1; + RETURN (BESTSCORE); + END EVALUATE; + + /* make a move given the start square and end square */ + /* currently always promotes to queen */ + /* Moves from position (A, B) to position (X,Y). */ + + MAKEMOVE: PROCEDURE (A, B, X, Y, C) OPTIONS (REORDER); + DECLARE (A, B, X, Y, C) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26)) FIXED BINARY (31); + + BOARD(Y, X)=BOARD(B, A); BOARD(B, A)=0; + IF Y = 0 & BOARD(Y, X) = 100 THEN + BOARD(Y, X)= C; + IF Y = 7 & BOARD(Y, X) = -100 THEN + BOARD(Y, X)= C; + RETURN; + END MAKEMOVE; + + /* select appropriate subprogram to populate xx and yy arrays */ + /* with piece moves */ + /* xx = x coordinates */ + /* yy = y coordinates */ + /* cc = pawn promotion if applicable */ + /* ndx = index into xx, yy, cc arrays showing the number of */ + /* elements that the arrays have been populated with */ + MOVELIST: PROCEDURE (A, B, XX, YY, CC, NDX) OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26), CC(0:26)) FIXED BINARY (31); + DECLARE (NDX) FIXED BINARY (31); + DECLARE (PIECE) FIXED BINARY (31); + + PIECE=ABS(BOARD(B, A)); NDX=-1; + SELECT (PIECE); + WHEN (100) CALL PAWN(A, B, XX, YY, CC, NDX); + WHEN (270) CALL KNIGHT(A, B, XX, YY, NDX); + WHEN (300) CALL BISHOP(A, B, XX, YY, NDX); + WHEN (500) CALL ROOK(A, B, XX, YY, NDX); + WHEN (900) CALL QUEEN(A, B, XX, YY, NDX); + OTHERWISE CALL KING(A, B, XX, YY, NDX); + END; + RETURN; + END MOVELIST; + + /* queen is a combination of rook and bishop */ + QUEEN: PROCEDURE (A, B, XX, YY, NDX) OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26)) FIXED BINARY (31); + DECLARE NDX FIXED BINARY (31); + + CALL ROOK(A, B, XX, YY, NDX); + CALL BISHOP(A, B, XX, YY, NDX); + RETURN; + END QUEEN; + + + KING: PROCEDURE (A, B, XX, YY, NDX) OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26)) FIXED BINARY (31); + DECLARE NDX FIXED BINARY (31); + DECLARE (ID, DX, DY) FIXED BINARY (31); + + ID=SIGN(BOARD(B, A)); + /* negative = left or up */ + /* positive = right or down */ + /* zero = no change */ + DO DY=-1 TO 1; + IF B+DY<0 | B+DY>7 THEN + ITERATE; + DO DX=-1 TO 1; + IF A+DX<0 | A+DX>7 THEN + ITERATE; + IF ID^=SIGN(BOARD(B+DY,A+DX)) THEN + DO; + NDX=NDX+1; XX(NDX)=A+DX; YY(NDX)=B+DY; + END; + END; + END; + RETURN; + END KING; + + + PAWN: PROCEDURE (A, B, XX, YY, CC, NDX) OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26), CC(0:26)) FIXED BINARY (31); + DECLARE NDX FIXED BINARY (31); + DECLARE (I, ID) FIXED BINARY (31); + + ID = SIGN(BOARD(B, A)); + IF ((A - 1) >= 0) & ((A - 1) <= 7) & ((B - ID) >= 0) & ((B - + ID) <= 7) THEN + DO; + IF SIGN(BOARD((B - ID), (A - 1))) = -ID THEN + DO; + IF ((ID<0) & (B = 6)) | ((ID>0) & (B = 1)) THEN + DO; + CC(NDX+1) = 270*ID; + CC(NDX+2) = 300*ID; + CC(NDX+3) = 500*ID; + CC(NDX+4) = 900*ID; + DO I=1 TO 4; + NDX = NDX + 1; + XX(NDX) = A - 1; + YY(NDX) = B - ID; + END; + END; + ELSE + DO; + NDX = NDX + 1; + XX(NDX) = A - 1; + YY(NDX) = B - ID; + END; + END; + END; + IF ((A + 1) >= 0) & ((A + 1) <= 7) & ((B - ID) >= 0) & ((B + - ID) <= 7) THEN + DO; + IF SIGN(BOARD((B - ID), (A + 1))) = -ID THEN + DO; + IF ((ID<0) & (B = 6)) | ((ID>0) & (B = 1)) THEN + DO; + CC(NDX+1) = 270*ID; + CC(NDX+2) = 300*ID; + CC(NDX+3) = 500*ID; + CC(NDX+4) = 900*ID; + DO I=1 TO 4; + NDX = NDX + 1; + XX(NDX) = A + 1; + YY(NDX) = B - ID; + END; + END; + ELSE + DO; + NDX = NDX + 1; + XX(NDX) = A + 1; + YY(NDX) = B - ID; + END; + END; + END; + IF (A >= 0) & (A <= 7) & ((B - ID) >= 0) & ((B - ID) <= 7) THEN + DO; + IF BOARD((B - ID), A) = 0 THEN + DO; + IF ((ID<0) & (B = 6)) | ((ID>0) & (B = 1)) THEN + DO; + CC(NDX+1) = 270*ID; + CC(NDX+2) = 300*ID; + CC(NDX+3) = 500*ID; + CC(NDX+4) = 900*ID; + DO I=1 TO 4; + NDX = NDX + 1; + XX(NDX) = A; + YY(NDX) = B - ID; + END; + END; + ELSE + DO; + NDX = NDX + 1; + XX(NDX) = A; + YY(NDX) = B - ID; + END; + IF ((ID < 0) & (B = 1)) | ((ID > 0) & (B = 6)) THEN + DO; + IF BOARD((B - ID - ID), A) = 0 THEN + DO; + NDX = NDX + 1; + XX(NDX) = A; + YY(NDX) = B - ID - ID; + END; + END; + END; + END; + END PAWN; + + + BISHOP: PROCEDURE (A, B, XX, YY, NDX) OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26)) FIXED BINARY (31); + DECLARE NDX FIXED BINARY (31); + DECLARE (ID, DXY, X, Y) FIXED BINARY; + + ID=SIGN(BOARD(B, A)); + /* four diagonal directions */ + DO DXY=1 TO 7; + X=A-DXY; IF (X<0) THEN LEAVE; + Y=B+DXY; IF (Y>7) THEN LEAVE; + IF ID^=SIGN(BOARD(Y, X)) THEN /* cannot capture piece of same color */ + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + IF BOARD(Y, X)^=0 THEN + LEAVE /* cannot jump over pieces */; + END; + DO DXY=1 TO 7; + X=A+DXY; IF (X>7) THEN LEAVE; + Y=B+DXY; IF (Y>7) THEN LEAVE; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + IF BOARD(Y, X)^=0 THEN + LEAVE; + END; + DO DXY=1 TO 7; + X=A-DXY; IF (X<0) THEN LEAVE; + Y=B-DXY; IF (Y<0) THEN LEAVE; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + IF BOARD(Y, X)^=0 THEN + LEAVE; + END; + DO DXY=1 TO 7; + X=A+DXY; IF (X>7) THEN LEAVE; + Y=B-DXY; IF (Y<0) THEN LEAVE; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + IF BOARD(Y, X)^=0 THEN + LEAVE; + END; + END BISHOP; + + ROOK: PROCEDURE (A, B, XX, YY, NDX) OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26)) FIXED BINARY (31); + DECLARE NDX FIXED BINARY (31); + DECLARE (ID, X, Y) FIXED BINARY (31); + + ID=SIGN(BOARD(B, A)); + /* four different orthagonal directions */ + DO X = A-1 TO 0 BY -1; + IF ID^=SIGN(BOARD(B, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=B; + END; + IF BOARD(B, X)^=0 THEN + LEAVE; + END; + DO X = A+1 TO 7 BY 1; + IF ID^=SIGN(BOARD(B, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=B; + END; + IF BOARD(B, X)^=0 THEN + LEAVE; + END; + DO Y = B-1 TO 0 BY -1; + IF ID^=SIGN(BOARD(Y, A)) THEN + DO; + NDX=NDX+1; XX(NDX)=A; YY(NDX)=Y; + END; + IF BOARD(Y, A)^=0 THEN + LEAVE; + END; + DO Y = B+1 TO 7 BY 1; + IF ID^=SIGN(BOARD(Y, A)) THEN + DO; + NDX=NDX+1; XX(NDX)=A; YY(NDX)=Y; + END; + IF BOARD(Y, A)^=0 THEN + LEAVE; + END; + RETURN; + END ROOK; + + + KNIGHT: PROCEDURE (A, B, XX, YY, NDX) OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + DECLARE (XX(0:26), YY(0:26)) FIXED BINARY (31); + DECLARE NDX FIXED BINARY (31); + DECLARE (ID, X, Y) FIXED BINARY (31); + + ID=SIGN(BOARD(B, A)); + /* 2 vertical, 1 horizontal */ + /* or 2 horizontal, 1 vertical */ + X=A-1; Y=B-2; + IF X>=0 & Y>=0 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + X=A-2; Y=B-1; + IF X>=0 & Y>=0 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + X=A+1; Y=B-2; + IF X<=7 & Y>=0 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + X=A+2; Y=B-1; + IF X<=7 & Y>=0 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + X=A-1; Y=B+2; + IF X>=0 & Y<=7 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + X=A-2; Y=B+1; + IF X>=0 & Y<=7 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + X=A+1; Y=B+2; + IF X<=7 & Y<=7 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + X=A+2; Y=B+1; + IF X<=7 & Y<=7 THEN + DO; + IF ID^=SIGN(BOARD(Y, X)) THEN + DO; + NDX=NDX+1; XX(NDX)=X; YY(NDX)=Y; + END; + END; + RETURN; + END KNIGHT; + + /* display chessboard */ + SHOW: PROCEDURE OPTIONS (REORDER); + DECLARE (A, B) FIXED BINARY (31); + + DO B=0 TO 7; + PUT SKIP EDIT ( ' +---+---+---+---+---+---+---+---+' )(COL(20), A); + PUT SKIP EDIT ( 8-B, ' |' )(COL(20), F(1), A); + DO A=0 TO 7; + SELECT (BOARD(B, A)); + WHEN (-7500) PUT EDIT ( ' *k|' )(A); + WHEN (-900) PUT EDIT ( ' *q|' )(A); + WHEN (-500) PUT EDIT ( ' *r|' )(A); + WHEN (-300) PUT EDIT ( ' *b|' )(A); + WHEN (-270) PUT EDIT ( ' *n|' )(A); + WHEN (-100) PUT EDIT ( ' *p|' )(A); + WHEN (0) PUT EDIT ( ' |' )(A); + WHEN (100) PUT EDIT ( ' P |' )(A); + WHEN (270) PUT EDIT ( ' N |' )(A); + WHEN (300) PUT EDIT ( ' B |' )(A); + WHEN (500) PUT EDIT ( ' R |' )(A); + WHEN (900) PUT EDIT ( ' Q |' )(A); + WHEN (5000) PUT EDIT ( ' K |' )(A); + END; + END; + END; + PUT SKIP EDIT ( ' +---+---+---+---+---+---+---+---+' )(COL(20), A); + PUT SKIP EDIT ( ' A B C D E F G H' )(COL(20), A); + RETURN; + END SHOW; + + /* io -- input/output: */ + /* display black move and get white move */ + IO: PROCEDURE (A, B, X, Y, RES) OPTIONS (REORDER); + DECLARE (A, B, X, Y, RES) FIXED BINARY (31); + DECLARE ( INPUT ) CHARACTER (10); + DECLARE (XX(0:26), YY(0:26), CC(0:26)) FIXED BINARY (31); + DECLARE (I, K, NDX, PIECE, TARG, MOVER, C) FIXED BINARY (31); + DECLARE NULL FIXED BINARY; /* This variable is assigned but never used. */ + DECLARE LETTER (0:7) CHAR (1) STATIC INITIAL + ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'); + + DECLARE SL FIXED BINARY; + + /* >>>>>>>>> CAUTION - WATCH FOR UNINITIALIZED XX, YY <<<<<<<<<<< */ + DECLARE ( WCKSOLD, WCQSOLD ) BIT(1) ALIGNED; + + ON ERROR SNAP BEGIN; + PUT SKIP LIST ('at line ' || TRIM(SL) ); + END; + + SL = SOURCELINE(); + + IF A>=0 THEN + DO; + IF RES<-2500 THEN + DO; + PUT SKIP LIST ( 'I RESIGN'); + CALL SHOW; + PUT SKIP; + STOP; + END; + PIECE=BOARD(Y, X); + CALL MAKEMOVE(A, B, X, Y, C); + PUT SKIP EDIT ( 'MY MOVE: ' )(A); + PUT EDIT ( LETTER(A), 8-B, '-', LETTER(X), 8-Y) + (A, F(1), A, A, F(1)); + + SELECT (PIECE); + WHEN (100) PUT SKIP LIST ( 'I TOOK YOUR PAWN'); + WHEN (270) PUT SKIP LIST ( 'I TOOK YOUR KNIGHT'); + WHEN (300) PUT SKIP LIST ( 'I TOOK YOUR BISHOP'); + WHEN (500) PUT SKIP LIST ( 'I TOOK YOUR ROOK'); + WHEN (900) PUT SKIP LIST ( 'I TOOK YOUR QUEEN'); + WHEN (5000) PUT SKIP LIST ( 'I TOOK YOUR KING'); + OTHERWISE ; + END; + END; + DO_FOREVER1: + DO FOREVER; + CALL SHOW; + PUT SKIP EDIT ( 'YOUR MOVE: ' )(A); + RETRY_MOVE: + GET EDIT (INPUT) (L); + CALL UPCASE(INPUT); + IF (INPUT = 'QUIT') | (INPUT = 'BYE') | (INPUT = 'EXIT') THEN + STOP; + /* castling */ + IF (INPUT = 'O-O') | (INPUT = '0-0') THEN + DO; + IF INCHECK() ^= 0 THEN + ITERATE DO_FOREVER1; /* cannot castle out of check */ + IF WCKSFLAG THEN + ITERATE DO_FOREVER1; + IF BOARD(7, 7) ^= 500 THEN + ITERATE DO_FOREVER1; + IF (BOARD (7,6) ^= 0) | (BOARD(7,5) ^=0) THEN + ITERATE DO_FOREVER1; + BOARD(7, 4) = 0; + BOARD(7, 5) = 5000; + IF INCHECK() ^= 0 THEN /* cannot castle through check */ + DO; + BOARD(7, 4) = 5000; + BOARD(7, 5) = 0; + ITERATE DO_FOREVER1; + END; + ELSE + DO; + BOARD(7, 4) = 5000; + BOARD(7, 5) = 0; + END; + BOARD(7, 6) = 5000; + BOARD(7, 4) = 0; + BOARD(7, 5) = 500; + BOARD(7, 7) = 0; + IF INCHECK() ^= 0 THEN /* cannot castle into check */ + DO; + BOARD(7, 6) = 0; + BOARD(7, 4) = 5000; + BOARD(7, 5) = 0; + BOARD(7, 7) = 500; + ITERATE DO_FOREVER1; + END; + ELSE + DO; + WCKSFLAG = '1'B; + WCQSFLAG = '1'B; + RETURN; + END; + END; + IF (INPUT = 'O-O-O') | (INPUT = '0-0-0') THEN + DO; + IF INCHECK() ^= 0 THEN + ITERATE DO_FOREVER1; /* cannot castle out of check */ + IF WCQSFLAG THEN + ITERATE DO_FOREVER1; + IF BOARD(7,0) ^= 500 THEN + ITERATE DO_FOREVER1; + IF (BOARD(7,1) ^= 0) | (BOARD(7,2) ^= 0) | (BOARD(7,3) ^= 0) THEN + ITERATE DO_FOREVER1; + BOARD(7, 4) = 0; + BOARD(7, 3) = 5000; + IF INCHECK() ^= 0 THEN /* cannot castle through check */ + DO; + BOARD(7, 4) = 5000; + BOARD(7, 3) = 0; + ITERATE DO_FOREVER1; + END; + ELSE + DO; + BOARD(7, 4) = 5000; + BOARD(7, 3) = 0; + END; + BOARD(7, 2) = 5000; + BOARD(7, 4) = 0; + BOARD(7, 3) = 500; + BOARD(7, 0) = 0; + IF INCHECK() ^= 0 THEN /* cannot castle into check */ + DO; + BOARD(7, 2) = 0; + BOARD(7, 4) = 5000; + BOARD(7, 3) = 0; + BOARD(7, 0) = 500; + ITERATE DO_FOREVER1; + END; + ELSE + DO; + WCKSFLAG = '1'B; + WCQSFLAG = '1'B; + RETURN; + END; + END; + + /* Check that only the proper letters A-H etc are used. */ + /* (this does not check that the letters are in their correct columns.) */ + I = VERIFY (TRIM(INPUT), 'ABCDEFGHO0-12345678'); + IF I > 0 THEN + DO; + PUT SKIP LIST ('That move was invalid. Please try again:'); + GO TO RETRY_MOVE; + END; + + SL = SOURCELINE(); + + /* (A,B) are co-ordinates of the from position. */ + /* (X,Y) are co-ordinates of the destination position. */ + + /* Translate algebraic notation to co-ordinates. */ + + B = 8 - INDEX ('12345678', SUBSTR(INPUT, 2, 1) ); + A = INDEX ('ABCDEFGH', SUBSTR(INPUT, 1, 1) ) - 1; + X = INDEX ('ABCDEFGH', SUBSTR(INPUT, 4, 1) ) - 1; + Y = 8 - INDEX ('12345678', SUBSTR(INPUT, 5, 1) ); + + PUT SKIP DATA (A, B); + PUT SKIP DATA (X, Y); + STOP; + IF B>7 | B<0 | A>7 | A<0 | X>7 | X<0 | Y>7 | Y<0 THEN + DO; + PUT SKIP LIST ('Illegal move. Please try again'); + ITERATE DO_FOREVER1; + END; + IF BOARD(B,A)<=0 THEN + ITERATE DO_FOREVER1; + /* en passant capture */ + IF (Y = 2) & (B = 3) & ((X = A-1) | (X = A+1)) THEN + DO; + IF (BOARD(B,A) = 100) & (BOARD(Y,X) = 0) & (BOARD(Y+1,X) =-100) THEN + DO; + IF (BESTB(1) = 1) & (BESTA(1) = X) THEN + DO; + MOVER = BOARD(B,A); + TARG = BOARD(Y,X); + CALL MAKEMOVE(A,B,X,Y,C); + BOARD(Y+1,X)=0; + IF (INCHECK()) = 0 THEN + RETURN; + BOARD(B,A) = MOVER; + BOARD(Y, X) = TARG; + BOARD(Y+1,X) = -100; + ITERATE DO_FOREVER1; + END; + END; + END; + /* check if selected white move is on list of moves */ + CALL MOVELIST(A, B, XX, YY, CC, NDX); + DOK_LOOP: + DO K = 0 TO NDX BY 1; + IF (X = XX(K)) & (Y = YY(K)) THEN + DO; + MOVER = BOARD(B, A); + TARG = BOARD(Y, X); + IF Y = 0 THEN + FOREVER_LOOP: + DO FOREVER; + PUT SKIP EDIT ( 'PROMOTION PIECE: ' )(A); + GET EDIT (INPUT) (L); + CALL UPCASE(INPUT); + SELECT (INPUT); + WHEN ('N', 'KT', 'KNIGHT', 'HORSE') C = 270; + WHEN ('B', 'BISHOP') C = 300; + WHEN ('R', 'ROOK') C = 500; + WHEN ('Q', 'QUEEN') C = 900; + OTHERWISE ITERATE; + END; + LEAVE FOREVER_LOOP; + END; + CALL MAKEMOVE(A, B, X, Y, C); + IF MOVER = 5000 THEN + DO; + WCQSOLD = WCQSFLAG; + WCKSOLD = WCKSFLAG; + WCKSFLAG = '1'B; + WCQSFLAG = '1'B; + END; + IF (A = 0) & (B = 7) & (MOVER = 500) THEN + DO; + WCQSOLD = WCQSFLAG; + WCQSFLAG = '1'B; + END; + IF (A = 7) & (B = 7) & (MOVER = 500) THEN + DO; + WCKSOLD = WCKSFLAG; + WCKSFLAG = '1'B; + END; + IF INCHECK() = 0 THEN + RETURN; + BOARD(B, A) = MOVER; + BOARD(Y, X) = TARG; + IF MOVER = 5000 THEN + DO; + WCQSFLAG = WCQSOLD; + WCKSFLAG = WCKSOLD; + END; + IF (A = 0) & (B = 7) & (MOVER = 500) THEN + WCQSFLAG = WCQSOLD; + IF (A = 7) & (B = 7) & (MOVER = 500) THEN + WCKSFLAG = WCKSOLD; + LEAVE DOK_LOOP; + END; + END; + END; + END IO; + + /* convert string to uppercase */ + UPCASE: PROCEDURE (STRING) OPTIONS (REORDER); + DECLARE ( STRING ) CHARACTER (*); + + STRING = TRANSLATE (STRING, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', + 'abcdefghijklmnopqrstuvwxyz' ); + + END UPCASE; + + END CHESS; diff --git a/projects/languages/pli/src/maxlen.pli b/projects/languages/pli/src/maxlen.pli new file mode 100644 index 00000000..c7498b09 --- /dev/null +++ b/projects/languages/pli/src/maxlen.pli @@ -0,0 +1,67 @@ + /* Copyright (c) 1995 by R. A. Vowels, from "Introduction to PL/I, Algorithms, and */ + /* Structured Programming". Permission is given to reproduce and to use these procedures */ + /* as part of a program, and to include them as part of a larger work to be sold for profit. */ + /* However, the user is not permitted to sell the procedures separately. Provided always */ + /* that these procedures and this copyright notice are reproduced in full. */ + + DECLARE MAXLENGTH GENERIC + (MAXLEN_graphic WHEN (GRAPHIC), + MAXLEN_bit WHEN (BIT), + MAXLEN_char WHEN (*) ); + + /* This procedure is provided for those who must have the */ + /* built-in function MAXLENGTH. Do not call it often, as */ + /* run-time is relatively high. */ + /* This procedure returns the maximum length that a VARYING character string may take. */ + MAXLEN_char: + PROCEDURE (STRING) RETURNS (FIXED BINARY); + DECLARE STRING CHARACTER (*) VARYING; + + DECLARE LENGTH BUILTIN; + DECLARE TEMP CHARACTER (32767) VARYING; + DECLARE STR CHARACTER (32767) STATIC INITIAL ( ' ' ); + DECLARE K FIXED BINARY; + + TEMP = STRING; /* Preserve a copy of the string. */ + (NOSTRINGSIZE): + STRING = STR; /* Assign something very long to it. */ + K = LENGTH (STRING); /* Find out how long the variable is. */ + STRING = TEMP; /* Restore the string. */ + RETURN (K); /* The declared length of the string. */ + END MAXLEN_char; + + /* This procedure returns the maximum length that a VARYING graphic string may take. */ + MAXLEN_graphic: + PROCEDURE (STRING) RETURNS (FIXED BINARY); + DECLARE STRING GRAPHIC (*) VARYING; + + DECLARE LENGTH BUILTIN; + DECLARE TEMP GRAPHIC (16383) VARYING; + DECLARE STR GRAPHIC (16383) STATIC INITIAL ( ' ' ); + DECLARE K FIXED BINARY; + + TEMP = STRING; /* Preserve a copy of the string. */ + (NOSTRINGSIZE): + STRING = STR; /* Assign something very long to it. */ + K = LENGTH (STRING); /* Find out how long the variable is. */ + STRING = TEMP; /* Restore the string. */ + RETURN (K); /* The declared length of the string. */ + END MAXLEN_graphic; + + /* This procedure returns the maximum length that a VARYING bit string may take. */ + MAXLEN_bit: + PROCEDURE (STRING) RETURNS (FIXED BINARY); + DECLARE STRING BIT (*) VARYING; + + DECLARE LENGTH BUILTIN; + DECLARE TEMP BIT (32767) VARYING; + DECLARE STR BIT (32767) STATIC INITIAL ( '0'B); + DECLARE K FIXED BINARY; + + TEMP = STRING; /* Preserve a copy of the string. */ + (NOSTRINGSIZE): + STRING = STR; /* Assign something very long to it. */ + K = LENGTH (STRING); /* Find out how long the variable is. */ + STRING = TEMP; /* Restore the string. */ + RETURN (K); /* The declared length of the string. */ + END MAXLEN_bit; diff --git a/projects/languages/pli/src/search.pli b/projects/languages/pli/src/search.pli new file mode 100644 index 00000000..ed9a2314 --- /dev/null +++ b/projects/languages/pli/src/search.pli @@ -0,0 +1,246 @@ + /* Copyright (c) 1995 by R. A. Vowels, from "Introduction to PL/I, Algorithms, and */ + /* Structured Programming". Permission is given to reproduce and to use these procedures */ + /* as part of a program, and to include them as part of a larger work to be sold for profit. */ + /* However, the user is not permitted to sell the procedures separately. Provided always */ + /* that these procedures and this copyright notice are reproduced in full. */ + + DECLARE SEARCH GENERIC + (SEARCH_all_graphic WHEN ( GRAPHIC, GRAPHIC), + SEARCH_all_graphic WHEN ( GRAPHIC, *), + SEARCH_all_graphic WHEN (*, GRAPHIC), + SEARCH_all_bit WHEN ( BIT, BIT), + SEARCH_all WHEN (*,*), + SEARCH_sub_graphic WHEN ( GRAPHIC, GRAPHIC, *), + SEARCH_sub_graphic WHEN ( GRAPHIC, *, *), + SEARCH_sub_graphic WHEN (*, GRAPHIC, *), + SEARCH_sub_bit WHEN ( BIT, BIT, *), + SEARCH_sub WHEN (*,*,*) ); + + /* This function procedure searches the first string STRING for any characters given in the */ + /* second string SUB. If there are any such characters, the function returns the position */ + /* of the left-most. */ + SEARCH_all: + PROCEDURE (STRING, SUB) OPTIONS (REORDER) + RETURNS (FIXED BINARY (31)); + /* INCOMING: STRING = the string to be searched; */ + /* SUB = contains characters to look for. */ + DECLARE (STRING, SUB) CHARACTER (*); + + DECLARE (LENGTH, SUBSTR, + UNSPEC, INDEX) BUILTIN; + DECLARE Table (0:255) BIT (1) STATIC ALIGNED; + DECLARE (J, K) FIXED BINARY (31); + + IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */ + RETURN (0); + IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */ + RETURN (0); + IF LENGTH (SUB) = 1 THEN /* Looking for one character is fast. */ + RETURN (INDEX (STRING, SUB)); + + /* SETS UP A LOOK-UP TABLE (which is independent of the character set). */ + Table = '0'B; /* All entries are FALSE. */ + DO J = 1 TO LENGTH (Sub); + K = UNSPEC (SUBSTR (Sub, J, 1)); + Table (K) = '1'B; /* Table(k) is TRUE for each character in SUB. */ + END; + + /* CONDUCT THE SEARCH. */ + DO J = 1 TO LENGTH (STRING); + K = UNSPEC (SUBSTR (STRING, J, 1)); + IF Table(K) THEN /* TRUE when a SUB character matches one in */ + RETURN (J); /* STRING. */ + END; + RETURN (0); /* Unsuccessful search. */ + END SEARCH_all; + + /* This function procedure searches the first string STRING for any characters given in the */ + /* second string SUB. If there are any such characters, the function returns the position */ + /* of the left-most. */ + /* The search is performed from left to right, commencing from character position */ + /* POSITION. */ + SEARCH_sub: + PROCEDURE (STRING, SUB, POSITION) RETURNS (FIXED BINARY (31)); + /* INCOMING: STRING = the string to be searched; */ + /* SUB = contains characters to look for; */ + /* POSITION = where to start the search (measured from the left-hand end of */ + /* STRING). */ + DECLARE (STRING, SUB) CHARACTER (*); + DECLARE POSITION FIXED BINARY (31); + + DECLARE (LENGTH, INDEX) BUILTIN; + DECLARE K FIXED BINARY (31); + + IF (Position > LENGTH (String)+1) | (Position <= 0) THEN + DO; + SIGNAL STRINGRANGE; + RETURN (0); + END; + IF LENGTH (STRING) = 0 THEN RETURN (0); + K = SEARCH_all ( SUBSTR (STRING, POSITION), SUB); + IF K = 0 THEN RETURN (0); + RETURN (POSITION+K-1); + END SEARCH_sub; + + /* This function procedure searches the first string STRING for any characters given in the */ + /* second string SUB. If there are any such characters, the function returns the position */ + /* of the left-most. */ + SEARCH_all_graphic: + PROCEDURE (STRING, SUB) OPTIONS (REORDER) + RETURNS ( FIXED BINARY (31)); + /* INCOMING: STRING = the string to be searched; */ + /* SUB = contains characters to look for. */ + DECLARE (STRING, SUB) GRAPHIC (*); + + DECLARE (LENGTH, + SUBSTR, + INDEX) BUILTIN; + DECLARE (J, K) FIXED BINARY (31); + DECLARE Ch GRAPHIC (1); + + IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */ + RETURN (0); + IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */ + RETURN (0); + IF LENGTH (SUB) = 1 THEN /* Looking for one character is fast. */ + RETURN (INDEX (STRING, SUB)); + + DO J = 1 TO LENGTH(String); + Ch = SUBSTR(String, J, 1); /* Select one graphic character from the string to*/ + /* be searched. */ + K = INDEX (Sub, Ch); /* Check whether it is one of those on our search list.*/ + IF K ^= 0 THEN /* If it is, we are done. */ + RETURN (J); + END; + + RETURN (0); /* The search was unsuccessful. */ + END SEARCH_all_graphic; + + /* This function procedure searches the first string STRING for any graphic characters */ + /* given in the second string SUB. If there are any such graphic characters, the function */ + /* returns the position of the left-most. */ + /* The search is performed from left to right, commencing from graphic character position */ + /* POSITION. */ + SEARCH_sub_graphic: + PROCEDURE (STRING, SUB, POSITION) RETURNS (FIXED BINARY (31)); + /* INCOMING: STRING = the string to be searched; */ + /* SUB = contains characters to look for; */ + /* POSITION = where to start the search (measured from the left-hand end of */ + /* STRING). */ + DECLARE (STRING, SUB) GRAPHIC (*); + DECLARE POSITION FIXED BINARY (31); + + DECLARE (LENGTH, SUBSTR, + INDEX) BUILTIN; + DECLARE (J, K) FIXED BINARY (31); + DECLARE Ch GRAPHIC (1); + + IF (Position > LENGTH (String)+1) | (Position <= 0) THEN + DO; + SIGNAL STRINGRANGE; + RETURN (0); + END; + IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */ + RETURN (0); + IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */ + RETURN (0); + IF LENGTH (SUB) = 1 THEN /* Looking for one character is fast. */ + RETURN (INDEX (SUBSTR (STRING, Position), SUB)+Position-1); + + DO J = Position TO LENGTH(String); + Ch = SUBSTR(String, J, 1); /* Select one graphic character from the string to */ + /* be searched. */ + K = INDEX (Sub, Ch); /* Check whether it is one of those on our search list.*/ + IF K ^= 0 THEN /* If it is, we are done. */ + RETURN (J); + END; + + RETURN (0); /* The search was unsuccessful. */ + + END SEARCH_sub_graphic; + + /* This function procedure searches the first string STRING for any bits given in the */ + /* second string SUB. If there are any such bits, the function returns the position */ + /* of the left-most. */ + SEARCH_all_bit: + PROCEDURE (STRING, SUB) OPTIONS (REORDER) + RETURNS ( FIXED BINARY (31)); + /* INCOMING: STRING = the string to be searched; */ + /* SUB = contains bits to look for. */ + DECLARE (STRING, SUB) BIT (*); + + DECLARE (LENGTH, SUBSTR, + INDEX) BUILTIN; + DECLARE (J, K) FIXED BINARY (31); + + IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */ + RETURN (0); + IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */ + RETURN (0); + IF LENGTH (SUB) = 1 THEN /* Looking for one bit is fast. */ + RETURN (INDEX (STRING, SUB)); + + /* When we come here, SUB has 2 or more bits. */ + + K = INDEX (SUB, ^SUBSTR(SUB, 1, 1)); /* Look for a bit of the opposite kind. */ + + IF K > 0 THEN /* No need for a search -- the key SUB consists */ + /* of both 0 and 1. */ + RETURN (1); /* Always get a match at position 1. */ + + /* The pattern SUB contains either all ones or all zeros. */ + + /* CONDUCT THE SEARCH. */ + IF SUBSTR(SUB, 1, 1) THEN + RETURN (INDEX(STRING, '1'B)); + ELSE + RETURN (INDEX(STRING, '0'B)); + + END SEARCH_all_bit; + + /* This function procedure searches the first string STRING for any bits given in the */ + /* second string SUB. If there are any such bits, the function returns the position */ + /* of the left-most. */ + SEARCH_sub_bit: + PROCEDURE (String, Sub, Position) OPTIONS (REORDER) + RETURNS ( FIXED BINARY (31)); + /* INCOMING: STRING = the string to be searched; */ + /* SUB = contains bits to look for. */ + DECLARE (String, Sub) BIT (*); + + DECLARE (LENGTH, SUBSTR, + INDEX) BUILTIN; + DECLARE (J, K) FIXED BINARY (31); + + IF (Position > LENGTH (String)+1) | (Position <= 0) THEN + DO; + SIGNAL STRINGRANGE; + RETURN (0); + END; + IF LENGTH (SUB) = 0 THEN /* Nothing with which to search. */ + RETURN (0); + IF LENGTH (STRING) = 0 THEN /* There's nothing to search. */ + RETURN (0); + IF Position = LENGTH(String)+1 THEN + RETURN (0); + IF LENGTH (SUB) = 1 THEN /* Looking for one bit is fast. */ + RETURN (INDEX(SUBSTR(STRING, Position), SUB)+Position-1); + + /* When we come here, SUB has 2 or more bits. */ + + K = INDEX (SUBSTR(String, Position), ^SUBSTR(SUB, 1, 1)); + /* Look for a bit of the opposite kind. */ + + IF K > 0 THEN /* No need for a search -- the key SUB consists */ + /* of both 0 and 1. */ + RETURN (Position); /* Always get a match at position "Position". */ + + /* The pattern SUB contains either all ones or all zeros. */ + + /* CONDUCT THE SEARCH. */ + IF SUBSTR(SUB, 1, 1) THEN + RETURN (INDEX(SUBSTR(STRING, Position), '1'B)+Position-1); + ELSE + RETURN (INDEX(SUBSTR(STRING, Position), '0'B)+Position-1); + + END SEARCH_sub_bit; diff --git a/projects/languages/pli/validation.txt b/projects/languages/pli/validation.txt new file mode 100644 index 00000000..f2fa221f --- /dev/null +++ b/projects/languages/pli/validation.txt @@ -0,0 +1,8 @@ +start server + with plugin pli 1.3.1 +sonar-runner +verify org.sonarqube:pli-simple-sq-scanner + measure lines is 1289 + measure ncloc is 970 + measure files is 4 +stop server diff --git a/projects/languages/plsql/plsql-oracle-forms/README.md b/projects/languages/plsql/plsql-oracle-forms/README.md new file mode 100644 index 00000000..37cf6723 --- /dev/null +++ b/projects/languages/plsql/plsql-oracle-forms/README.md @@ -0,0 +1,19 @@ +This example demonstrates how to analyze PL/SQL from Oracle Forms. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarSource PL/SQL Plugin](http://www.sonarsource.com/products/plugins/languages/plsql/) 2.7.1+ +* [SonarQube Oracle Forms PL/SQL Extractor](https://github.com/SonarCommunity/sonar-forms-plsql-extractor) 1.1+ + +Usage +===== +* Extract the PL/SQL source code from your Oracle Forms. Let's say that you downloaded the project sample to C:\plsql-oracle-forms. + + set FORMS_PATH=C:\plsql-oracle-forms\forms + java -DinputDir=C:\plsql-oracle-forms\forms -DoutputDir=C:\plsql-oracle-forms\src -cp C:\path\to\sonar-forms-plsql-extractor-X.X-jar-with-dependencies.jar;C:\path\to\oracle\forms\java\frmjdapi.jar org.sonar.oracleforms.plsql.PlSqlExtractor + +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/plsql/plsql-oracle-forms/forms/ue_samp.fmb b/projects/languages/plsql/plsql-oracle-forms/forms/ue_samp.fmb new file mode 100644 index 00000000..d946e157 Binary files /dev/null and b/projects/languages/plsql/plsql-oracle-forms/forms/ue_samp.fmb differ diff --git a/projects/languages/plsql/plsql-oracle-forms/sonar-project.properties b/projects/languages/plsql/plsql-oracle-forms/sonar-project.properties new file mode 100644 index 00000000..0bee029c --- /dev/null +++ b/projects/languages/plsql/plsql-oracle-forms/sonar-project.properties @@ -0,0 +1,7 @@ +sonar.projectKey=org.sonarqube:plsql-oracle-forms-sq-scanner +sonar.projectName=Oracle Forms :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src +sonar.language=plsql +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/plsql/plsql-sonar-runner/README.md b/projects/languages/plsql/plsql-sonar-runner/README.md new file mode 100644 index 00000000..eb49a95e --- /dev/null +++ b/projects/languages/plsql/plsql-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a PL/SQL project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarSource PL/SQL Plugin](http://www.sonarsource.com/products/plugins/languages/plsql/) 2.7.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/plsql/plsql-sonar-runner/sonar-project.properties b/projects/languages/plsql/plsql-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..d88b0a12 --- /dev/null +++ b/projects/languages/plsql/plsql-sonar-runner/sonar-project.properties @@ -0,0 +1,10 @@ +# Required metadata +sonar.projectKey=org.sonarqube:plsql-simple-sq-scanner +sonar.projectName=PL/SQL :: Simple Project : SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/plsql/plsql-sonar-runner/src/ddl.sql b/projects/languages/plsql/plsql-sonar-runner/src/ddl.sql new file mode 100644 index 00000000..78a3ddd1 --- /dev/null +++ b/projects/languages/plsql/plsql-sonar-runner/src/ddl.sql @@ -0,0 +1,9 @@ +CREATE TABLE OWNER.TABLE01 (ID NUMBER(12)); +/ +ALTER TABLE OWNER.TABLE01 ADD (COL1 VARCHAR2(4000)); +/ + +CREATE TABLE OWNER.TABLE02 (ID NUMBER(12)); +/ +ALTER TABLE OWNER.TABLE02 ADD (COL1 VARCHAR2(4000)); +/ diff --git a/projects/languages/plsql/plsql-sonar-runner/src/ut_report.pkb b/projects/languages/plsql/plsql-sonar-runner/src/ut_report.pkb new file mode 100644 index 00000000..15bdc4e4 --- /dev/null +++ b/projects/languages/plsql/plsql-sonar-runner/src/ut_report.pkb @@ -0,0 +1,213 @@ +/* Formatted on 2002/03/31 23:53 (Formatter Plus v4.5.2) */ +CREATE OR REPLACE PACKAGE BODY Utreport +IS + +/************************************************************************ +GNU General Public License for utPLSQL + +Copyright (C) 2000-2003 +Steven Feuerstein and the utPLSQL Project +(steven@stevenfeuerstein.com) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (see license.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +************************************************************************ +$Log: ut_report.pkb,v $ +Revision 1.3 2005/05/11 21:33:36 chrisrimmer +Added testing of reporter infrastructure + +Revision 1.2 2004/11/16 09:46:49 chrisrimmer +Changed to new version detection system. + +Revision 1.1 2004/07/14 17:01:57 chrisrimmer +Added first version of pluggable reporter packages + + +************************************************************************/ + + DEFAULT_REPORTER VARCHAR2(100) := 'Output'; + + DYNAMIC_PLSQL_FAILURE NUMBER(10) := -6550; + + --This is the reporter we have been asked to use + g_reporter VARCHAR2(100); + + --This is the reporter we are actually using + --(this differs from the above in the event of error) + g_actual VARCHAR2(100); + + FUNCTION parse_it(proc IN VARCHAR2, params IN NUMBER, force_reporter IN VARCHAR2) + RETURN INTEGER + IS + dyn_handle INTEGER := NULL; + query VARCHAR2(1000); + BEGIN + dyn_handle := DBMS_SQL.OPEN_CURSOR; + QUERY := 'BEGIN ut' || NVL(force_reporter, g_actual) || 'Reporter.' || proc ; + IF params = 1 THEN + QUERY := QUERY || '(:p)'; + END IF; + QUERY := QUERY || '; END;'; + DBMS_SQL.PARSE(dyn_handle, QUERY, DBMS_SQL.NATIVE); + RETURN dyn_handle; + EXCEPTION + WHEN OTHERS THEN + DBMS_SQL.CLOSE_CURSOR (dyn_handle); + RAISE; + END; + + PROCEDURE execute_it(dyn_handle IN OUT INTEGER) + IS + dyn_result INTEGER; + BEGIN + dyn_result := DBMS_SQL.EXECUTE (dyn_handle); + DBMS_SQL.CLOSE_CURSOR (dyn_handle); + END; + + --We use this to make dynamic calls to reporter packages + PROCEDURE call(proc IN VARCHAR2, + param IN VARCHAR2, + params IN NUMBER := 1, + force_reporter IN VARCHAR2 := NULL, + failover IN BOOLEAN := TRUE) + IS + dyn_handle INTEGER := NULL; + BEGIN + dyn_handle := parse_it(proc, params, force_reporter); + IF params = 1 THEN + DBMS_SQL.BIND_VARIABLE (dyn_handle, 'p', param); + END IF; + execute_it(dyn_handle); + EXCEPTION + WHEN OTHERS THEN + + IF dyn_handle IS NOT NULL THEN + DBMS_SQL.CLOSE_CURSOR (dyn_handle); + END IF; + + IF g_actual <> DEFAULT_REPORTER THEN + + IF NOT failover OR SQLCODE <> DYNAMIC_PLSQL_FAILURE THEN + g_actual := DEFAULT_REPORTER; + pl(SQLERRM); + pl('** REVERTING TO DEFAULT REPORTER **'); + END IF; + + ELSE + RAISE; + END IF; + + call(proc, param, params, force_reporter => DEFAULT_REPORTER); + END; + + PROCEDURE call(proc IN VARCHAR2, + failover IN BOOLEAN := TRUE) + IS + BEGIN + call(proc => proc, + param => '', + params => 0, + failover => failover); + END; + + PROCEDURE use(reporter IN VARCHAR2) + IS + BEGIN + g_reporter := NVL(reporter, DEFAULT_REPORTER); + g_actual := g_reporter; + END; + + FUNCTION using RETURN VARCHAR2 + IS + BEGIN + RETURN g_reporter; + END; + + PROCEDURE open + IS + BEGIN + g_actual := g_reporter; + call('open', failover => FALSE); + END; + + PROCEDURE pl (str IN VARCHAR2) + IS + BEGIN + call('pl', str); + END; + + PROCEDURE pl (bool IN BOOLEAN) + IS + BEGIN + pl (Utplsql.bool2vc (bool)); + END; + + PROCEDURE before_results(run_id IN utr_outcome.run_id%TYPE) + IS + BEGIN + call('before_results', run_id); + END; + + PROCEDURE show_failure(rec_result IN utr_outcome%ROWTYPE) + IS + BEGIN + outcome := rec_result; + call('show_failure'); + END; + + PROCEDURE show_result(rec_result IN utr_outcome%ROWTYPE) + IS + BEGIN + outcome := rec_result; + call('show_result'); + END; + + PROCEDURE after_results(run_id IN utr_outcome.run_id%TYPE) + IS + BEGIN + call('after_results', run_id); + END; + + PROCEDURE before_errors(run_id IN utr_error.run_id%TYPE) + IS + BEGIN + call('before_errors', run_id); + END; + + PROCEDURE show_error(rec_error IN utr_error%ROWTYPE) + IS + BEGIN + error := rec_error; + call('show_error'); + END; + + PROCEDURE after_errors(run_id IN utr_error.run_id%TYPE) + IS + BEGIN + call('after_errors', run_id); + END; + + PROCEDURE close + IS + BEGIN + call('close'); + END; + +BEGIN + + g_reporter := NVL(utconfig.getreporter, DEFAULT_REPORTER); + g_actual := g_reporter; + +END; +/ diff --git a/projects/languages/python/python-sonar-runner-coverage/README.md b/projects/languages/python/python-sonar-runner-coverage/README.md new file mode 100644 index 00000000..8ddc6a3f --- /dev/null +++ b/projects/languages/python/python-sonar-runner-coverage/README.md @@ -0,0 +1,22 @@ +This example demonstrates how to import Python Coverage Execution Results into SonarQube with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Python Plugin](http://docs.sonarqube.org/display/PLUG/Python+Plugin) 1.5+ +* [Coverage from Ned Batchelder](http://nedbatchelder.com/code/coverage/cmd.html) + +Tests Execution Results Generation +================================== +* Run from your project root directory: +** coverage erase +** coverage run --branch --source=src ./src/purchase.py +** coverage xml -i +* Path to the generated file coverage.xml is referenced in sonar-project.properties + +Usage +===== +* Analyze the projec with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/python/python-sonar-runner-coverage/coverage.xml b/projects/languages/python/python-sonar-runner-coverage/coverage.xml new file mode 100644 index 00000000..2d769712 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-coverage/coverage.xml @@ -0,0 +1,25 @@ + + + + + + /Users/alexandregigleux/Repos/sonar-examples/projects/languages/python/python-sonar-runner-coverage + + + + + + + + + + + + + + + + + + diff --git a/projects/languages/python/python-sonar-runner-coverage/sonar-project.properties b/projects/languages/python/python-sonar-runner-coverage/sonar-project.properties new file mode 100644 index 00000000..e3c48305 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-coverage/sonar-project.properties @@ -0,0 +1,15 @@ +# Required metadata +sonar.projectKey=org.sonarqube:python-coverage-sonar-scanner +sonar.projectName=Python :: Import Coverage Report :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=py + +sonar.python.coverage.reportPath=coverage.xml + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/python/python-sonar-runner-coverage/src/purchase.py b/projects/languages/python/python-sonar-runner-coverage/src/purchase.py new file mode 100644 index 00000000..dfedf672 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-coverage/src/purchase.py @@ -0,0 +1,9 @@ +print 'Bill Computation Start' + +prices = {'apple': 0.40, 'banana': 0.50} +my_purchase = { + 'apple': 1, + 'banana': 6} +grocery_bill = sum(prices[fruit] * my_purchase[fruit] + for fruit in my_purchase) +print 'I owe the grocer $%.2f' % grocery_bill diff --git a/projects/languages/python/python-sonar-runner-coverage/validation.txt b/projects/languages/python/python-sonar-runner-coverage/validation.txt new file mode 100644 index 00000000..f89b7b2a --- /dev/null +++ b/projects/languages/python/python-sonar-runner-coverage/validation.txt @@ -0,0 +1,8 @@ +start server + with plugin python 1.5 +sonar-runner +verify org.sonarqube:python-coverage-sonar-scanner + measure lines is 10 + measure ncloc is 8 + measure files is 1 +stop server diff --git a/projects/languages/python/python-sonar-runner-ut/README.md b/projects/languages/python/python-sonar-runner-ut/README.md new file mode 100644 index 00000000..e26e1be8 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-ut/README.md @@ -0,0 +1,19 @@ +This example demonstrates how to import Python Tests Execution Results into SonarQube with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Python Plugin](http://docs.sonarqube.org/display/PLUG/Python+Plugin) 1.5+ + +Tests Execution Results Generation +================================== +* Go in nosetests directory and run the command : nosetests --with-xunit ../src/samples/datepattern.py +* Tests Execution Results report is generated in nosetests under this name nosetests.xml +* Path to this file is referenced in sonar-project.properties + +Usage +===== +* Analyze the projec with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/python/python-sonar-runner-ut/nosetests/nosetests.xml b/projects/languages/python/python-sonar-runner-ut/nosetests/nosetests.xml new file mode 100644 index 00000000..a69479f8 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-ut/nosetests/nosetests.xml @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/projects/languages/python/python-sonar-runner-ut/sonar-project.properties b/projects/languages/python/python-sonar-runner-ut/sonar-project.properties new file mode 100644 index 00000000..a6b378a8 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-ut/sonar-project.properties @@ -0,0 +1,15 @@ +# Required metadata +sonar.projectKey=org.sonarqube:python-ut-sonar-scanner +sonar.projectName=Python :: Import Unit Test Report :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=py + +sonar.python.xunit.reportPath=nosetests/nosetests.xml + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/python/python-sonar-runner-ut/src/__init__.py b/projects/languages/python/python-sonar-runner-ut/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/projects/languages/python/python-sonar-runner-ut/src/samples/__init__.py b/projects/languages/python/python-sonar-runner-ut/src/samples/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/projects/languages/python/python-sonar-runner-ut/src/samples/datepattern.py b/projects/languages/python/python-sonar-runner-ut/src/samples/datepattern.py new file mode 100644 index 00000000..7250ea70 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-ut/src/samples/datepattern.py @@ -0,0 +1,34 @@ +import unittest +import datetime + +class DatePattern: + + def __init__(self, year, month, day): + self.year = year + self.month = month + self.day = day + + def matches(self, date): + return ((self.year and self.year == date.year or True) and + self.month == date.month and + self.day == date.day) + +class DatePatternTest(unittest.TestCase): + + def testMatchesYearAndMonthAsWildCards(self): + p = DatePattern(0, 0, 1) + d = datetime.date(2004, 10, 1) + self.failUnless(p.matches(d)) + + def testMatchesWeekday(self): + p = DatePattern(0, 0, 0, 2) # 2 is Wednesday + d = datetime.date(2004, 9, 29) + self.failUnless(p.matches(d)) + + def testMatchesYearAsWildCard(self): + p = DatePattern(0, 4, 10) + d = datetime.date(2005, 4, 10) + self.failUnless(p.matches(d)) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/projects/languages/python/python-sonar-runner-ut/validation.txt b/projects/languages/python/python-sonar-runner-ut/validation.txt new file mode 100644 index 00000000..61f75e34 --- /dev/null +++ b/projects/languages/python/python-sonar-runner-ut/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin python 1.5 +sonar-runner +verify org.sonarqube:python-ut-sonar-scanner + measure lines is 36 + measure ncloc is 26 + measure files is 3 +verify org.sonarqube:python-ut-sonar-scanner:src/samples/datepattern.py + measure lines is 34 + measure ncloc is 26 +stop server diff --git a/projects/languages/python/python-sonar-runner/README.md b/projects/languages/python/python-sonar-runner/README.md new file mode 100644 index 00000000..dc1974fe --- /dev/null +++ b/projects/languages/python/python-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a Python project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Python Plugin](http://docs.sonarqube.org/display/PLUG/Python+Plugin) 1.5+ + +Usage +===== +* Analyze the projec with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/python/python-sonar-runner/sonar-project.properties b/projects/languages/python/python-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..518873ca --- /dev/null +++ b/projects/languages/python/python-sonar-runner/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:python-simple-sonar-scanner +sonar.projectName=Python :: Simple Project : SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=py + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/python/python-sonar-runner/src/__init__.py b/projects/languages/python/python-sonar-runner/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/projects/languages/python/python-sonar-runner/src/badfortune.py b/projects/languages/python/python-sonar-runner/src/badfortune.py new file mode 100644 index 00000000..b0900dc1 --- /dev/null +++ b/projects/languages/python/python-sonar-runner/src/badfortune.py @@ -0,0 +1,92 @@ + +# fortune.py -- chooses a random fortune, as the fortune(8) program in +# the BSD-games package does +# +# Copyright (c) 2010, Andrew M. Kuchling +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import struct, random, string + +# C long variables are different sizes on 32-bit and 64-bit machines, +# so we have to measure how big they are on the machine where this is running. +LONG_SIZE = struct.calcsize('L') +is_64_bit = (LONG_SIZE == 8) + +def get(filename): + "Select a random quotation, using a pregenerated .dat file" + + # First, we open the .dat file, and read the header information. + # The C structure containing this info looks like: + ## typedef struct { /* information table */ + ## #define VERSION 1 + ## unsigned long str_version; /* version number */ + ## unsigned long str_numstr; /* # of strings in the file */ + ## unsigned long str_longlen; /* length of longest string */ + ## unsigned long str_shortlen; /* length of shortest string */ + ## #define STR_RANDOM 0x1 /* randomized pointers */ + ## #define STR_ORDERED 0x2 /* ordered pointers */ + ## #define STR_ROTATED 0x4 /* rot-13'd text */ + ## unsigned long str_flags; /* bit field for flags */ + ## unsigned char stuff[4]; /* long aligned space */ + ## #define str_delim stuff[0] /* delimiting character */ + ## } STRFILE; + + datfile = open(filename+'.dat', 'r') + data = datfile.read(5 * LONG_SIZE) + if is_64_bit: + v1, v2, n1, n2, l1, l2, s1, s2, f1, f2 = struct.unpack('!10L', data) + version = v1 + (v2 << 32) + numstr = n1 + (n2 << 32) + longlen = l1 + (l2 << 32) + shortlen = s1 + (s2 << 32) + flags = f1 + (f2 << 32) + else: + version, numstr, longlen, shortlen, flags = struct.unpack('5l', data) + + delimiter = datfile.read(1) + datfile.read(3) # Throw away padding bytes + if is_64_bit: datfile.read(4) # 64-bit machines align to 8 bytes + + # Pick a random number + r = random.randint(0, numstr) + datfile.seek(LONG_SIZE * r, 1) # Seek to the chosen pointer + data = datfile.read(LONG_SIZE * 2) + + if is_64_bit: + s1, s2, e1, e2 = struct.unpack('!4L', data) + start, end = s1 + (s2 << 32), e1 + (e2 << 32) + else: + start, end = struct.unpack('!ll', data) + datfile.close() + + file = open(filename, 'r') + file.seek(start) + quotation = file.read(end-start) + L=string.split(quotation, '\n') + while string.strip(L[-1]) == delimiter or string.strip(L[-1]) == "": + L=L[:-1] + return string.join(L, '\n') + +if __name__ == '__main__': + import sys + if len(sys.argv) == 1: + print 'Usage: fortune.py ' + sys.exit() + print get(sys.argv[1]) diff --git a/projects/languages/python/python-sonar-runner/src/directory/file_in_directory.py b/projects/languages/python/python-sonar-runner/src/directory/file_in_directory.py new file mode 100644 index 00000000..0708437a --- /dev/null +++ b/projects/languages/python/python-sonar-runner/src/directory/file_in_directory.py @@ -0,0 +1 @@ +lst = [] diff --git a/projects/languages/python/python-sonar-runner/src/package/__init__.py b/projects/languages/python/python-sonar-runner/src/package/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/projects/languages/python/python-sonar-runner/src/package/file_in_package.py b/projects/languages/python/python-sonar-runner/src/package/file_in_package.py new file mode 100644 index 00000000..fc7f2ba0 --- /dev/null +++ b/projects/languages/python/python-sonar-runner/src/package/file_in_package.py @@ -0,0 +1 @@ +dictionary = {} diff --git a/projects/languages/python/python-sonar-runner/src/samples/__init__.py b/projects/languages/python/python-sonar-runner/src/samples/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/projects/languages/python/python-sonar-runner/src/samples/fortune.py b/projects/languages/python/python-sonar-runner/src/samples/fortune.py new file mode 100644 index 00000000..b0900dc1 --- /dev/null +++ b/projects/languages/python/python-sonar-runner/src/samples/fortune.py @@ -0,0 +1,92 @@ + +# fortune.py -- chooses a random fortune, as the fortune(8) program in +# the BSD-games package does +# +# Copyright (c) 2010, Andrew M. Kuchling +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import struct, random, string + +# C long variables are different sizes on 32-bit and 64-bit machines, +# so we have to measure how big they are on the machine where this is running. +LONG_SIZE = struct.calcsize('L') +is_64_bit = (LONG_SIZE == 8) + +def get(filename): + "Select a random quotation, using a pregenerated .dat file" + + # First, we open the .dat file, and read the header information. + # The C structure containing this info looks like: + ## typedef struct { /* information table */ + ## #define VERSION 1 + ## unsigned long str_version; /* version number */ + ## unsigned long str_numstr; /* # of strings in the file */ + ## unsigned long str_longlen; /* length of longest string */ + ## unsigned long str_shortlen; /* length of shortest string */ + ## #define STR_RANDOM 0x1 /* randomized pointers */ + ## #define STR_ORDERED 0x2 /* ordered pointers */ + ## #define STR_ROTATED 0x4 /* rot-13'd text */ + ## unsigned long str_flags; /* bit field for flags */ + ## unsigned char stuff[4]; /* long aligned space */ + ## #define str_delim stuff[0] /* delimiting character */ + ## } STRFILE; + + datfile = open(filename+'.dat', 'r') + data = datfile.read(5 * LONG_SIZE) + if is_64_bit: + v1, v2, n1, n2, l1, l2, s1, s2, f1, f2 = struct.unpack('!10L', data) + version = v1 + (v2 << 32) + numstr = n1 + (n2 << 32) + longlen = l1 + (l2 << 32) + shortlen = s1 + (s2 << 32) + flags = f1 + (f2 << 32) + else: + version, numstr, longlen, shortlen, flags = struct.unpack('5l', data) + + delimiter = datfile.read(1) + datfile.read(3) # Throw away padding bytes + if is_64_bit: datfile.read(4) # 64-bit machines align to 8 bytes + + # Pick a random number + r = random.randint(0, numstr) + datfile.seek(LONG_SIZE * r, 1) # Seek to the chosen pointer + data = datfile.read(LONG_SIZE * 2) + + if is_64_bit: + s1, s2, e1, e2 = struct.unpack('!4L', data) + start, end = s1 + (s2 << 32), e1 + (e2 << 32) + else: + start, end = struct.unpack('!ll', data) + datfile.close() + + file = open(filename, 'r') + file.seek(start) + quotation = file.read(end-start) + L=string.split(quotation, '\n') + while string.strip(L[-1]) == delimiter or string.strip(L[-1]) == "": + L=L[:-1] + return string.join(L, '\n') + +if __name__ == '__main__': + import sys + if len(sys.argv) == 1: + print 'Usage: fortune.py ' + sys.exit() + print get(sys.argv[1]) diff --git a/projects/languages/python/python-sonar-runner/src/samples/letters.py b/projects/languages/python/python-sonar-runner/src/samples/letters.py new file mode 100644 index 00000000..0f54b31c --- /dev/null +++ b/projects/languages/python/python-sonar-runner/src/samples/letters.py @@ -0,0 +1,203 @@ + +# +# Copyright (c) 2010, Andrew M. Kuchling +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import random, string + +# Logic game +# From a program by Judith Haris, John Swets, and Wallace Feurzeig +# Reference: The Secret Guide to Computers, by Russ Walter, 18th ed 1993. +# Written in Python by A.M. Kuchling (amk@amk.ca) + +# For each letter, we need the various characteristics: +# (curves, loose ends, obliques, horizontals, verticals). +# There should really be a sample character set for the user to look +# at; otherwise, there are ambiguities. For example, does B have +# horizontals? Does D? How about P and R? + +# There's a bug lurking in this data! Can you catch it? +# (See the bottom of the program for the answer.) + +letter_stats={'a': (0, 2, 2, 1, 0), 'b':(2, 0, 0, 3, 1), + 'c': (1, 2, 0, 0, 0), 'd':(1, 0, 0, 0, 1), + 'e': (0, 3, 0, 3, 1), 'f':(0, 3, 0, 2, 1), + 'g': (1, 2, 0, 1, 1), 'h':(0, 4, 0, 1, 2), + 'i': (0, 2, 0, 0, 1), 'j':(1, 2, 0, 0, 1), + 'k': (0, 4, 2, 0, 1), 'l':(0, 2, 0, 1, 1), + 'm': (0, 2, 2, 0, 2), 'n':(0, 2, 1, 0, 2), + 'o': (1, 0, 0, 0, 0), 'p':(1, 1, 0, 2, 1), + 'q': (1, 2, 1, 0, 0), 'r':(1, 2, 1, 0, 1), + 's': (1, 2, 0, 0, 0), 't':(0, 3, 0, 1, 1), + 'u': (1, 2, 0, 0, 2), 'v':(0, 2, 2, 0, 0), + 'w': (0, 2, 4, 0, 0), 'x':(0, 4, 2, 0, 0), + 'y': (0, 3, 2, 0, 1), 'z':(0, 2, 1, 2, 0)} + +# We'll define constants for the various statistics; each constant is +# equal to the position of the statistic in the tuples in +#letter_stats. +CURVES=0 ; LOOSE_ENDS=1 ; OBLIQUES=2 ; HORIZONTALS=3 ; VERTICALS=4 + +# This dictionary is used to map questions to corresponding +# statistics. Note that different keys can map to the same value; +# for example, 'obliques' and 'diagonals' both map to the OBLIQUES constant. +questions={'curves':CURVES, 'looseends':LOOSE_ENDS, + 'obliques':OBLIQUES, 'diagonals':OBLIQUES, + 'horizontals':HORIZONTALS, 'verticals':VERTICALS} + +# Play a single game + +def play_once(): + # Choose a random number between 0 and 26, inclusive. + choice=26*random.random() + # Convert the numeric choice to a letter: 0->a, 1->b, etc. + choice=chr(ord('a')+choice) + + #choice=raw_input("What should I choose?") # (for debugging) + + # We'll track how many possibilities the user still has available. + # Start with all of the letters. + possibilities=string.lower("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + # We'll also track which questions have been asked, and chide the + # user when he repeats a question. + asked=[] + + # Loop forever; the play_once() function will exit by hitting a + # 'return' statement inside the loop. + while (1): + try: + #print possibilities # (for debugging) + + # Get input from the user + query=raw_input('Next? ') + # Convert the input to lowercase + query=string.lower(query) + # Remove all non-letter characters + query=filter(lambda x: x in string.lowercase, query) + # Remove whitespace + query=string.strip(query) + + except (EOFError, KeyboardInterrupt): + # End-Of-File : the user + print '\nOK; give up if you like.' + return + + if len(query)==1: + # The query is one character long, so it's a guess + if query not in possibilities: + print ("Wrong! That guess is inconsistent " + "with the information you've been given.\n" + "I think you made that guess just to see " + "what I would say.") + elif len(possibilities)>1: + print "You don't have enough information yet." + # Temporarily remove the user's guess from + # possibilities, and pick a random letter. + temp=filter(lambda x, query=query: x!=query, possibilities) + r=int(random.random()*len(temp)) + print "How do you know it isn't", temp[r]+',', + print "for example?" + else: + # query is in possibilities, and + # len(possibilities)==1, so the user is right. + print "Yes, you've done it. Good work!" ; return + elif questions.has_key(query): + # Get the field of the letter_stats tuple to compare. + field=questions[query] + # Determine the answer for the computer's letter + result=letter_stats[choice][field] + original_length=len(possibilities) + + # Exclude possibilities that don't match those of the + # mystery letter. + # filter(func, sequence) calls func() on each element in + # the sequence, and returns a new sequence object + # containing only elements for which func() returned true. + # For strings, each character is an element. Instead of + # defining a formal function, a lambda is used to create + # an anonymous function (one without a name). + # Various other things required by the function are set + # as default arguments, so they're accessible inside the + # scope of the anonymous function. + possibilities=filter(lambda letter, letter_stats=letter_stats, + field=field, result=result: + letter_stats[letter][field]==result, + possibilities) + new_length=len(possibilities) + if field in asked: + print "You asked me that already." + print "The answer is the same as before:", + else: asked.append(field) # Note that this question was asked. + print str(result)+'.' + if (original_length==new_length): + print 'That was a wasted question; it did not exclude any possibilities.' + elif (new_length") + +# The solution to the bug-hunt is below... + + + + + + + + + + + +# It's not a bug that the Python interpreter can catch; instead, it's +# a specification bug: +# +# 'C' and 'S' both have the same stats: 1 curve, 2 loose ends, +# and no obliques, horizontals, or verticals. If either C or S is +# chosen as the computer's letter, the user can never get the right +# answer, because he/she can't narrow down the possibilities to just +# one! To fix this, you'd have to add another statistic, like +# number of intersections or number of closed loops. However, the +# statistic would have to be *different* for 'C' and 'S', and neither +# of those two suggestions qualify. Can you think of a property to +# distinguish between the two letters? diff --git a/projects/languages/python/python-sonar-runner/src/samples/strfile.py b/projects/languages/python/python-sonar-runner/src/samples/strfile.py new file mode 100644 index 00000000..ca15a607 --- /dev/null +++ b/projects/languages/python/python-sonar-runner/src/samples/strfile.py @@ -0,0 +1,100 @@ + +# strfile.py -- write an index file for a fortune file, as the strfile(8) +# program in the BSD-games package does +# +# Copyright (c) 2010, Andrew M. Kuchling +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import struct, string, sys + +if len(sys.argv)==1: + print "Usage: strfile.py " + sys.exit() + +# C long variables are different sizes on 32-bit and 64-bit machines, +# so we have to measure how big they are on the machine where this is running. +LONG_SIZE = struct.calcsize('L') +is_64_bit = (LONG_SIZE == 8) + +delimiter = '%' # The standard delimiter + +filename = sys.argv[1] +input = open(filename, 'r') +output = open(filename + '.dat', 'w') +output.seek(LONG_SIZE * 6) # Skip over the header for now + +# Output a 32- or 64-bit integer + +def write_long(x): + if is_64_bit: + output.write( struct.pack("!LL", x & 0xffffFFFFL, x >> 32) ) + else: + output.write( struct.pack("!L", x) ) + +write_long(0) # Write the first pointer + +# We need to track various statistics: the longest and shortest +# quotations, and their number + +shortest = sys.maxint ; longest = 0 +numstr = 0 +quotation = "" + +while (1): + L=input.readline() # Get a line + if L=="": break # Check for end-of-file + if string.strip(L) != delimiter: + # We haven't come to the end yet, so we just add the line to + # the quotation we're building and continue + quotation = quotation + L ; continue + + # If there's a leading % in the file, the first quotation will be + # empty; we'll just ignore it + if quotation == "": continue + + # Update the shortest and longest variables + shortest = min(shortest, len(quotation) ) + longest = max(longest, len(quotation) ) + + # Output the current file pointer + write_long( input.tell() ) + numstr = numstr + 1 + quotation = "" # Reset the quotation to null + +# To simplify the programming, we'll assume there's a trailing % line +# in the file, with no quotation following. +assert quotation == "" + +input.close() + +# We're done, so rewind to the beginning of the file and write the header +output.seek(0) +write_long( 1 ) # Version +write_long(numstr) # Number of strings +write_long(longest) # Longest string length +write_long(shortest) # Shortest string length +write_long(0) # Flags; we'll set them to zero +output.write(delimiter + '\0'*(LONG_SIZE-1)) +output.close() + +print '''"%s.dat" created +There were %i strings +Longest string: %i bytes +Shortest string: %i bytes''' % (filename, numstr, longest, shortest) diff --git a/projects/languages/python/python-sonar-runner/validation.txt b/projects/languages/python/python-sonar-runner/validation.txt new file mode 100644 index 00000000..fcd7e336 --- /dev/null +++ b/projects/languages/python/python-sonar-runner/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin python 1.5 +sonar-runner +verify org.sonarqube:python-simple-sonar-scanner + measure lines is 498 + measure ncloc is 215 + measure files is 9 +verify org.sonarqube:python-simple-sonar-scanner:src/badfortune.py + measure lines is 93 + measure ncloc is 41 +stop server diff --git a/projects/languages/rpg/README.md b/projects/languages/rpg/README.md new file mode 100644 index 00000000..d27e4898 --- /dev/null +++ b/projects/languages/rpg/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze an RPG project with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarSource RPG Plugin](http://www.sonarsource.com/products/plugins/languages/rpg/) 1.4.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/rpg/sonar-project.properties b/projects/languages/rpg/sonar-project.properties new file mode 100644 index 00000000..0f2212ed --- /dev/null +++ b/projects/languages/rpg/sonar-project.properties @@ -0,0 +1,8 @@ +sonar.projectKey=org.sonarqube:rpg-sq-scanner +sonar.projectName=RPG :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src +sonar.language=rpg + +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/rpg/src/MYPROGRAM.rpg b/projects/languages/rpg/src/MYPROGRAM.rpg new file mode 100644 index 00000000..b7d36daa --- /dev/null +++ b/projects/languages/rpg/src/MYPROGRAM.rpg @@ -0,0 +1,53 @@ +123456789012 C* Expressions in Extended Factor 2 syntax +123456789012 C IF A=X OR A=Y AND A=Z +123456789012 C AND B=Y +123456789012 C READ Y +123456789012 C ENDIF +123456789012 C IF A=X OR A=Y AND A=Z +123456789012 C AND B=Y OR B=Z +123456789012 C READ Y +123456789012 C ENDIF +123456789012 C* Expressions composed over several operations in IF +123456789012 C A IFEQ X +123456789012 C A OREQ Y +123456789012 C A ANDEQ Z +123456789012 C B ANDEQ Y +123456789012 C READ Y +123456789012 C ENDIF +123456789012 C A IFEQ X +123456789012 C A OREQ Y +123456789012 C A ANDEQ Z +123456789012 C B ANDEQ Y +123456789012 C B OREQ Z +123456789012 C READ Y +123456789012 C ENDIF +123456789012 C* Expressions composed over several operations in DO +123456789012 C A DOUEQ X +123456789012 C A OREQ Y +123456789012 C A ANDEQ Z +123456789012 C B ANDEQ Y +123456789012 C READ Y +123456789012 C END +123456789012 C A DOUEQ X +123456789012 C A OREQ Y +123456789012 C A ANDEQ Z +123456789012 C B ANDEQ Y +123456789012 C B OREQ Z +123456789012 C READ Y +123456789012 C END +123456789012 C* Expressions composed over several operations in WHEN +123456789012 C SELECT +123456789012 C A WHENEQ X +123456789012 C A OREQ Y +123456789012 C A ANDEQ Z +123456789012 C B ANDEQ Y +123456789012 C READ Y +123456789012 C END +123456789012 C SELECT +123456789012 C A WHENEQ X +123456789012 C A OREQ Y +123456789012 C A ANDEQ Z +123456789012 C B ANDEQ Y +123456789012 C B OREQ Z +123456789012 C READ Y +123456789012 C END \ No newline at end of file diff --git a/projects/languages/rpg/validation.txt b/projects/languages/rpg/validation.txt new file mode 100644 index 00000000..b316550d --- /dev/null +++ b/projects/languages/rpg/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin rpg 1.4.1 +sonar-runner +verify org.sonarqube:rpg-sq-scanner + measure lines is 53 + measure ncloc is 49 + measure files is 1 +verify org.sonarqube:rpg-sq-scanner:src/MYPROGRAM.rpg + measure lines is 53 + measure ncloc is 49 +stop server diff --git a/projects/languages/sonar-project.properties b/projects/languages/sonar-project.properties new file mode 100644 index 00000000..d92d181a --- /dev/null +++ b/projects/languages/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:it-sonar-examples +sonar.projectName=IT Sonar Examples Quality +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=. + +# Language +sonar.language=text + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/swift/swift-sonar-runner/README.md b/projects/languages/swift/swift-sonar-runner/README.md new file mode 100644 index 00000000..97d12f0e --- /dev/null +++ b/projects/languages/swift/swift-sonar-runner/README.md @@ -0,0 +1,12 @@ +This example demonstrates how to analyze a simple Swift project with the Sonar Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/swift/swift-sonar-runner/sonar-project.properties b/projects/languages/swift/swift-sonar-runner/sonar-project.properties new file mode 100755 index 00000000..a39df615 --- /dev/null +++ b/projects/languages/swift/swift-sonar-runner/sonar-project.properties @@ -0,0 +1,5 @@ +sonar.projectKey=org.sonarqube:swift-simple-sq-scanner +sonar.projectName=Swift :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +sonar.sources=src diff --git a/projects/languages/swift/swift-sonar-runner/src/example.swift b/projects/languages/swift/swift-sonar-runner/src/example.swift new file mode 100644 index 00000000..194455d6 --- /dev/null +++ b/projects/languages/swift/swift-sonar-runner/src/example.swift @@ -0,0 +1,10 @@ + +let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] + +func backwards(s1: String, s2: String) -> Bool { + return s1 > s2 +} + +var reversed = sorted(names, backwards); + +if (true) { print(reversed) } diff --git a/projects/languages/swift/swift-sonar-runner/validation.txt b/projects/languages/swift/swift-sonar-runner/validation.txt new file mode 100644 index 00000000..a80b0eb5 --- /dev/null +++ b/projects/languages/swift/swift-sonar-runner/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin swift 1.5 +sonar-runner +verify org.sonarqube:swift-simple-sq-scanner + measure lines is 11 + measure ncloc is 6 + measure files is 1 +verify org.sonarqube:swift-simple-sq-scanner:src/example.swift + measure lines is 11 + measure ncloc is 6 +stop server diff --git a/projects/languages/vb6/README.md b/projects/languages/vb6/README.md new file mode 100644 index 00000000..0e81957b --- /dev/null +++ b/projects/languages/vb6/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a VB6 project with the Sonar Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarSource VB6 Plugin](http://www.sonarsource.com/products/plugins/languages/visual-basic-6/) 2.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/vb6/sonar-project.properties b/projects/languages/vb6/sonar-project.properties new file mode 100644 index 00000000..00ec016b --- /dev/null +++ b/projects/languages/vb6/sonar-project.properties @@ -0,0 +1,16 @@ +# Required metadata +sonar.projectKey=org.sonarqube:vb-simple-sq-scanner +sonar.projectName=VB6 :: Simple Project :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Description of project (optional) +sonar.projectDescription=Simple Visual Basic 6 project analyzed using the SonarQube Runner + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=vb + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 diff --git a/projects/languages/vb6/src/Info.frm b/projects/languages/vb6/src/Info.frm new file mode 100644 index 00000000..d762b1c4 --- /dev/null +++ b/projects/languages/vb6/src/Info.frm @@ -0,0 +1,67 @@ +VERSION 5.00 +Begin VB.Form frmInfo + BorderStyle = 3 'Fixed Dialog + Caption = "Info" + ClientHeight = 3750 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 6270 + Icon = "Info.frx":0000 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 3750 + ScaleWidth = 6270 + ShowInTaskbar = 0 'False + StartUpPosition = 1 'CenterOwner + Begin VB.CommandButton cmdOK + Caption = "&OK" + Default = -1 'True + Height = 375 + Left = 5100 + TabIndex = 1 + Top = 3300 + Width = 1095 + End + Begin VB.TextBox txtGPL + BackColor = &H8000000F& + BorderStyle = 0 'None + Height = 3075 + Left = 120 + Locked = -1 'True + MultiLine = -1 'True + TabIndex = 0 + Text = "Info.frx":000C + Top = 120 + Width = 6015 + End +End +Attribute VB_Name = "frmInfo" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' --- GPL --- +' +' Copyright (C) 1999 SAP AG +' +' This program is free software; you can redistribute it and/or +' modify it under the terms of the GNU General Public License +' as published by the Free Software Foundation; either version 2 +' of the License, or (at your option) any later version. +' +' This program is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY; without even the implied warranty of +' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +' GNU General Public License for more details. +' +' You should have received a copy of the GNU General Public License +' along with this program; if not, write to the Free Software +' Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +' +' --- GPL --- +Option Explicit + +Private Sub cmdOK_Click() + Unload Me +End Sub diff --git a/projects/languages/vb6/src/Registry.bas b/projects/languages/vb6/src/Registry.bas new file mode 100644 index 00000000..17c2cb1a --- /dev/null +++ b/projects/languages/vb6/src/Registry.bas @@ -0,0 +1,166 @@ +Attribute VB_Name = "modRegistry" +' --- GPL --- +' +' Copyright (C) 1999 SAP AG +' +' This program is free software; you can redistribute it and/or +' modify it under the terms of the GNU General Public License +' as published by the Free Software Foundation; either version 2 +' of the License, or (at your option) any later version. +' +' This program is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY; without even the implied warranty of +' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +' GNU General Public License for more details. +' +' You should have received a copy of the GNU General Public License +' along with this program; if not, write to the Free Software +' Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +' +' --- GPL --- +Option Explicit + +'Structures Needed For Registry Prototypes +Public Type SECURITY_ATTRIBUTES + nLength As Long + lpSecurityDescriptor As Long + bInheritHandle As Boolean +End Type + +Public Type FILETIME + dwLowDateTime As Long + dwHighDateTime As Long +End Type + +'Registry Function Prototypes +Public Declare Function RegOpenKeyEx Lib "advapi32" Alias "RegOpenKeyExA" ( _ + ByVal hKey As Long, _ + ByVal lpSubKey As String, _ + ByVal ulOptions As Long, _ + ByVal samDesired As Long, _ + phkResult As Long) As Long + +Public Declare Function RegCreateKeyEx Lib "advapi32" Alias "RegCreateKeyExA" ( _ + ByVal hKey As Long, _ + ByVal lpSubKey As String, _ + ByVal Reserved As Long, _ + ByVal lpClass As String, _ + ByVal dwOptions As Long, _ + ByVal samDesired As Long, _ + lpSecurityAttributes As SECURITY_ATTRIBUTES, _ + phkResult As Long, _ + lpdwDisposition As Long) As Long + +Public Declare Function RegQueryValueExNull Lib "advapi32.dll" Alias "RegQueryValueExA" ( _ + ByVal hKey As Long, _ + ByVal lpValueName As String, _ + ByVal lpReserved As Long, _ + lpType As Long, _ + ByVal lpData As Long, _ + lpcbData As Long) As Long + +Public Declare Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" ( _ + ByVal hKey As Long, _ + ByVal lpValueName As String, _ + ByVal lpReserved As Long, _ + lpType As Long, _ + ByVal lpData As String, _ + lpcbData As Long) As Long + +Public Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias "RegQueryValueExA" ( _ + ByVal hKey As Long, _ + ByVal lpValueName As String, _ + ByVal lpReserved As Long, _ + lpType As Long, _ + lpData As Long, _ + lpcbData As Long) As Long + +Public Declare Function RegSetValueExString Lib "advapi32.dll" Alias "RegSetValueExA" ( _ + ByVal hKey As Long, _ + ByVal lpValueName As String, _ + ByVal Reserved As Long, _ + ByVal dwType As Long, _ + ByVal lpValue As String, _ + ByVal cbData As Long) As Long + +Public Declare Function RegSetValueExLong Lib "advapi32.dll" Alias "RegSetValueExA" ( _ + ByVal hKey As Long, _ + ByVal lpValueName As String, _ + ByVal Reserved As Long, _ + ByVal dwType As Long, _ + lpValue As Long, _ + ByVal cbData As Long) As Long + +Public Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" ( _ + ByVal hKey As Long, _ + ByVal dwIndex As Long, _ + ByVal lpName As String, _ + lpcbName As Long, _ + ByVal lpReserved As Long, _ + ByVal lpClass As String, _ + lpcbClass As Long, _ + lpftLastWriteTime As FILETIME) As Long + +Public Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" ( _ + ByVal hKey As Long, _ + ByVal dwIndex As Long, _ + ByVal lpValueName As String, _ + lpcbValueName As Long, _ + ByVal lpReserved As Long, _ + lpType As Long, _ + lpData As Any, _ + lpcbData As Long) As Long + +Public Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" ( _ + ByVal hKey As Long, _ + ByVal lpSubKey As String) As Long + +Public Declare Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueA" ( _ + ByVal hKey As Long, _ + ByVal lpValueName As String) As Long + +Public Declare Function RegCloseKey Lib "advapi32" ( _ + ByVal hKey As Long) As Long + +' +''masks for the predefined standard access types +'Private Const STANDARD_RIGHTS_ALL = &H1F0000 +'Private Const SPECIFIC_RIGHTS_ALL = &HFFFF +' +''Define severity codes +' +''Public Const ERROR_ACCESS_DENIED = 5 +'' +''Global Const ERROR_NONE = 0 +''Global Const ERROR_BADDB = 1 +''Global Const ERROR_CANTOPEN = 3 +''Global Const ERROR_CANTREAD = 4 +''Global Const ERROR_CANTWRITE = 5 +''Global Const ERROR_OUTOFMEMORY = 6 +''Global Const ERROR_INVALID_PARAMETER = 7 +''Global Const ERROR_ACCESS_DENIED = 8 +''Global Const ERROR_INVALID_PARAMETERS = 87 +''Global Const ERROR_NO_MORE_ITEMS = 259 + +Public Type ByteValue + b(1024) As Byte +End Type + +Public Type LongValue + l As Long +End Type + +Public Function BytesToString(bValue As ByteValue) As String + Dim s As String + Dim i As Integer + s = StrConv(bValue.b(), vbUnicode) + i = InStr(s, Chr(0)) - 1 + BytesToString = Left(s, i) +End Function + +Public Function BytesToLong(bValue As ByteValue) As Long + Dim lValue As LongValue + LSet lValue = bValue + BytesToLong = lValue.l +End Function + diff --git a/projects/languages/vb6/src/Registry.cls b/projects/languages/vb6/src/Registry.cls new file mode 100644 index 00000000..f0321eeb --- /dev/null +++ b/projects/languages/vb6/src/Registry.cls @@ -0,0 +1,428 @@ +VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True + Persistable = 0 'NotPersistable + DataBindingBehavior = 0 'vbNone + DataSourceBehavior = 0 'vbNone + MTSTransactionMode = 0 'NotAnMTSObject +END +Attribute VB_Name = "Registry" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = True +Attribute VB_PredeclaredId = False +Attribute VB_Exposed = False +' --- GPL --- +' +' Copyright (C) 1999 SAP AG +' +' This program is free software; you can redistribute it and/or +' modify it under the terms of the GNU General Public License +' as published by the Free Software Foundation; either version 2 +' of the License, or (at your option) any later version. +' +' This program is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY; without even the implied warranty of +' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +' GNU General Public License for more details. +' +' You should have received a copy of the GNU General Public License +' along with this program; if not, write to the Free Software +' Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +' +' --- GPL --- +Option Explicit + +Public Enum RegistryHKeyConstants + HKEY_CLASSES_ROOT = &H80000000 + HKEY_CURRENT_USER = &H80000001 + HKEY_LOCAL_MACHINE = &H80000002 + HKEY_USERS = &H80000003 + HKEY_PERFORMANCE_DATA = &H80000004 + HKEY_CURRENT_CONFIG = &H80000005 + HKEY_DYN_DATA = &H80000006 +End Enum + +Public Enum RegistryTypeConstants + REG_NONE = (0) 'No value type + REG_SZ = (1) 'Unicode nul terminated string +' REG_EXPAND_SZ = (2) 'Unicode nul terminated string w/enviornment var +' REG_BINARY = (3) 'Free form binary + REG_DWORD = (4) '32-bit number +' REG_DWORD_LITTLE_ENDIAN = (4) '32-bit number (same as REG_DWORD) +' REG_DWORD_BIG_ENDIAN = (5) '32-bit number +' REG_LINK = (6) 'Symbolic Link (unicode) +' REG_MULTI_SZ = (7) 'Multiple Unicode strings +' REG_RESOURCE_LIST = (8) 'Resource list in the resource map +' REG_FULL_RESOURCE_DESCRIPTOR = (9) 'Resource list in the hardware description +' REG_RESOURCE_REQUIREMENTS_LIST = (10) +End Enum + +Public Enum RegistryAccessConstants + KEY_QUERY_VALUE = &H1 + KEY_SET_VALUE = &H2 + KEY_CREATE_SUB_KEY = &H4 + KEY_ENUMERATE_SUB_KEYS = &H8 + KEY_NOTIFY = &H10 + KEY_CREATE_LINK = &H20 + KEY_ALL_ACCESS = &H3F +End Enum + +Public Enum RegistryErrorConstants + ERROR_SUCCESS = 0 + ERROR_BADKEY = 2 + ERROR_OUTOFMEMORY = 6 + ERROR_MORE_DATA = 234 + ERROR_NO_MORE_ITEMS = 259 +End Enum + +Public Enum RegistryVolatileConstants + REG_OPTION_NON_VOLATILE = 0& + REG_OPTION_VOLATILE = &H1 +End Enum + +Public Enum RegistryDispositionConstants + REG_CREATED_NEW_KEY = &H1 + REG_OPENED_EXISTING_KEY = &H2 +End Enum + +Private oKeys As Keys + +Private bShowErrors As Boolean +Private bRaiseErrors As Boolean +' +' Public Properties +' +Public Property Get Keys() As Keys + If oKeys Is Nothing Then + Set oKeys = New Keys + With oKeys + Set .Registry = Me + Set .Parent = Me + .Root = True + End With + End If + Set Keys = oKeys +End Property + +Public Property Get ShowErrors() As Boolean + ShowErrors = bShowErrors +End Property +Public Property Let ShowErrors(ByVal NewVal As Boolean) + bShowErrors = NewVal +End Property + +Public Property Get RaiseErrors() As Boolean + RaiseErrors = bRaiseErrors +End Property +Public Property Let RaiseErrors(ByVal NewVal As Boolean) + bRaiseErrors = NewVal +End Property +' +' Public Sub/Function +' +' Base Functions +' +Public Function OpenKey(ByVal hKey As RegistryHKeyConstants, _ + ByVal Path As String, _ + ByVal Access As RegistryAccessConstants, _ + Key As Long) As Boolean + + Dim lRC As Long + + OpenKey = False + + lRC = RegOpenKeyEx(hKey, Path, 0&, Access, Key) + If lRC = ERROR_SUCCESS Then + OpenKey = True + Else + HandleError lRC, Path + End If +End Function + +Public Function CreateKey(ByVal hKey As RegistryHKeyConstants, _ + ByVal Path As String, _ + ByVal Volatile As RegistryVolatileConstants, _ + ByVal Access As RegistryAccessConstants, _ + Key As Long, _ + Disposition As Long) As Boolean + + Dim lRC As Long + Dim saKey As SECURITY_ATTRIBUTES + + CreateKey = False + + lRC = RegCreateKeyEx(hKey, Path, 0, "", Volatile, Access, saKey, Key, Disposition) + If lRC = ERROR_SUCCESS Then + CreateKey = True + Else + HandleError lRC, Path + End If +End Function + +Public Function DeleteKey(ByVal hKey As RegistryHKeyConstants, _ + ByVal Path As String) As Boolean + + Dim lRC As Long + + DeleteKey = False + + lRC = RegDeleteKey(hKey, Path) + If lRC = ERROR_SUCCESS Then + DeleteKey = True + Else + HandleError lRC, Path + End If +End Function + +Public Function CloseKey(ByVal Path, _ + Key As Long) As Boolean + + Dim lRC As Long + + CloseKey = False + + lRC = RegCloseKey(Key) + If lRC = ERROR_SUCCESS Then + Key = 0 + CloseKey = True + Else + HandleError lRC, Path + End If +End Function + +Public Function QueryValueNull(ByVal hKey As Long, _ + ByVal Name As String, _ + ValueType As RegistryTypeConstants, _ + ValueLen As Long) As Boolean + + Dim lRC As Long + + QueryValueNull = False + + lRC = RegQueryValueExNull(hKey, Name, 0&, ValueType, 0&, ValueLen) + If lRC = ERROR_SUCCESS Then + QueryValueNull = True + Else + HandleError lRC, Name + End If +End Function + +Public Function QueryValueString(ByVal hKey As Long, _ + ByVal Name As String, _ + Value As String, _ + ValueLen As Long) As Boolean + + Dim lRC As Long + + QueryValueString = False + + Value = String(ValueLen, 0) + + lRC = RegQueryValueExString(hKey, Name, 0&, REG_SZ, Value, ValueLen) + If lRC = ERROR_SUCCESS Then + Value = Left(Value, ValueLen - 1) + QueryValueString = True + Else + HandleError lRC, Name + End If +End Function + +Public Function QueryValueLong(ByVal hKey As Long, _ + ByVal Name As String, _ + Value As Long) As Boolean + + Dim lRC As Long + Dim lValueLen As Long + + QueryValueLong = False + + Value = 0 + + lRC = RegQueryValueExLong(hKey, Name, 0&, REG_DWORD, Value, 4) + If lRC = ERROR_SUCCESS Then + QueryValueLong = True + Else + HandleError lRC, Name + End If +End Function + +Public Function SetValueString(ByVal hKey As Long, _ + ByVal Name As String, _ + ByVal Value As String) As Boolean + + Dim lRC As Long + + SetValueString = False + + Value = Value & Chr(0) + + lRC = RegSetValueExString(hKey, Name, 0&, REG_SZ, Value, Len(Value)) + If lRC = ERROR_SUCCESS Then + SetValueString = True + Else + HandleError lRC, Name + End If +End Function + +Public Function SetValueLong(ByVal hKey As Long, _ + ByVal Name As String, _ + ByVal Value As Long) As Boolean + + Dim lRC As Long + + SetValueLong = False + + lRC = RegSetValueExLong(hKey, Name, 0&, REG_DWORD, Value, 4) + If lRC = ERROR_SUCCESS Then + SetValueLong = True + Else + HandleError lRC, Name + End If +End Function + +Public Function DeleteValue(ByVal hKey As Long, _ + ByVal Name As String) As Boolean + + Dim lRC As Long + + DeleteValue = False + + lRC = RegDeleteValue(hKey, Name) + If lRC = ERROR_SUCCESS Then + DeleteValue = True + Else + HandleError lRC, Name + End If +End Function +' +' +' +Public Function Check(ByVal WithSubKeys As Boolean, _ + ByVal WithValues As Boolean) As Boolean + + Dim oKey As Key + + Check = False + + For Each oKey In Keys + If Not oKey.Check(WithSubKeys, WithValues) Then + Exit Function + End If + Next + + Check = True +End Function + +Public Function Create(ByVal WithSubKeys As Boolean, _ + ByVal WithValues As Boolean) As Boolean + + Dim oKey As Key + + Create = False + + For Each oKey In Keys + If Not oKey.Create(WithSubKeys, WithValues) Then + Exit Function + End If + Next + + Create = True +End Function + +Public Function QueryValues(ByVal WithSubKeys As Boolean) As Boolean + + Dim oKey As Key + + QueryValues = False + + For Each oKey In Keys + If Not oKey.QueryValues(WithSubKeys) Then + Exit Function + End If + Next + + QueryValues = True +End Function + +Public Function SetValues(ByVal WithSubKeys As Boolean) As Boolean + + Dim oKey As Key + + SetValues = False + + For Each oKey In Keys + If Not oKey.SetValues(WithSubKeys) Then + Exit Function + End If + Next + + SetValues = True +End Function + +Public Function EnumKeys(ByVal WithSubKeys As Boolean, _ + ByVal WithValues As Boolean) As Boolean + + Dim oKey As Key + + EnumKeys = False + + For Each oKey In Keys + If Not oKey.EnumKeys(WithSubKeys, WithValues) Then + Exit Function + End If + Next + + EnumKeys = True +End Function + +Public Function FindKeyByPath(ByVal WithSubKeys As Boolean, _ + ByVal FindPath As String) As Key + Dim oKey As Key + + Set FindKeyByPath = Nothing + + For Each oKey In Keys + If FindPath = oKey.Path Then + Set FindKeyByPath = oKey + Exit Function + End If + If WithSubKeys Then + Set FindKeyByPath = oKey.FindKeyByPath(WithSubKeys, FindPath) + End If + Next +End Function + +Friend Sub HandleError(ByVal RC As Long, ByVal Text As String) + Dim sMsg As String + + If bShowErrors Then + sMsg = "Error: " & ErrorText(RC) & ". " & Text + MsgBox sMsg, vbExclamation + End If +End Sub +' +' Private Sub/Function +' +Private Sub Class_Initialize() + 'Debug.Print "INIT Registry" + Set oKeys = Nothing + bShowErrors = True + bRaiseErrors = False +End Sub + +Private Sub Class_Terminate() + 'Debug.Print "TERM Registry" +End Sub + +Private Function ErrorText(ByVal lRC As Long) As String + Dim s As String + Select Case lRC + Case ERROR_BADKEY: s = "Bad key" + Case ERROR_MORE_DATA: s = "More data" + Case ERROR_OUTOFMEMORY: s = "Out of memory" + Case ERROR_NO_MORE_ITEMS: s = "No more items" + Case Else: s = "RC=" & CStr(lRC) + End Select + ErrorText = s +End Function + diff --git a/projects/languages/vb6/validation.txt b/projects/languages/vb6/validation.txt new file mode 100644 index 00000000..cbf66174 --- /dev/null +++ b/projects/languages/vb6/validation.txt @@ -0,0 +1,8 @@ +start server + with plugin vb 2.1 +sonar-runner +verify org.sonarqube:vb-simple-sq-scanner + measure lines is 664 + measure ncloc is 453 + measure files is 3 +stop server diff --git a/projects/languages/vbnet/.gitignore b/projects/languages/vbnet/.gitignore new file mode 100644 index 00000000..356bd15a --- /dev/null +++ b/projects/languages/vbnet/.gitignore @@ -0,0 +1,20 @@ +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# NuGet +packages/ + +# Roslyn +*.sln.ide/ diff --git a/projects/languages/vbnet/ConsoleApplication1.sln b/projects/languages/vbnet/ConsoleApplication1.sln new file mode 100644 index 00000000..6e530397 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.vbproj", "{65E63AB4-1055-4104-B233-A9F7CF2233DA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {65E63AB4-1055-4104-B233-A9F7CF2233DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65E63AB4-1055-4104-B233-A9F7CF2233DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65E63AB4-1055-4104-B233-A9F7CF2233DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65E63AB4-1055-4104-B233-A9F7CF2233DA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/projects/languages/vbnet/ConsoleApplication1/App.config b/projects/languages/vbnet/ConsoleApplication1/App.config new file mode 100644 index 00000000..8e156463 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/projects/languages/vbnet/ConsoleApplication1/ConsoleApplication1.vbproj b/projects/languages/vbnet/ConsoleApplication1/ConsoleApplication1.vbproj new file mode 100644 index 00000000..669f7d88 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/ConsoleApplication1.vbproj @@ -0,0 +1,114 @@ + + + + + Debug + AnyCPU + {65E63AB4-1055-4104-B233-A9F7CF2233DA} + Exe + ConsoleApplication1.Module1 + ConsoleApplication1 + ConsoleApplication1 + 512 + Console + v4.5 + + + AnyCPU + true + full + true + true + bin\Debug\ + ConsoleApplication1.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + AnyCPU + pdbonly + false + true + true + bin\Release\ + ConsoleApplication1.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + + \ No newline at end of file diff --git a/projects/languages/vbnet/ConsoleApplication1/Module1.vb b/projects/languages/vbnet/ConsoleApplication1/Module1.vb new file mode 100644 index 00000000..5d7e3a34 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/Module1.vb @@ -0,0 +1,7 @@ +Module Module1 + + Sub Main() + + End Sub + +End Module diff --git a/projects/languages/vbnet/ConsoleApplication1/My Project/Application.Designer.vb b/projects/languages/vbnet/ConsoleApplication1/My Project/Application.Designer.vb new file mode 100644 index 00000000..88dd01c7 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/projects/languages/vbnet/ConsoleApplication1/My Project/Application.myapp b/projects/languages/vbnet/ConsoleApplication1/My Project/Application.myapp new file mode 100644 index 00000000..e62f1a53 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 2 + true + diff --git a/projects/languages/vbnet/ConsoleApplication1/My Project/AssemblyInfo.vb b/projects/languages/vbnet/ConsoleApplication1/My Project/AssemblyInfo.vb new file mode 100644 index 00000000..d1ad4666 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' General Information about an assembly is controlled through the following +' set of attributes. Change these attribute values to modify the information +' associated with an assembly. + +' Review the values of the assembly attributes + + + + + + + + + + +'The following GUID is for the ID of the typelib if this project is exposed to COM + + +' Version information for an assembly consists of the following four values: +' +' Major Version +' Minor Version +' Build Number +' Revision +' +' You can specify all the values or you can default the Build and Revision Numbers +' by using the '*' as shown below: +' + + + diff --git a/projects/languages/vbnet/ConsoleApplication1/My Project/Resources.Designer.vb b/projects/languages/vbnet/ConsoleApplication1/My Project/Resources.Designer.vb new file mode 100644 index 00000000..0f9ffbaa --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/My Project/Resources.Designer.vb @@ -0,0 +1,62 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("ConsoleApplication1.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set(ByVal value As Global.System.Globalization.CultureInfo) + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/projects/languages/vbnet/ConsoleApplication1/My Project/Resources.resx b/projects/languages/vbnet/ConsoleApplication1/My Project/Resources.resx new file mode 100644 index 00000000..af7dbebb --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/projects/languages/vbnet/ConsoleApplication1/My Project/Settings.Designer.vb b/projects/languages/vbnet/ConsoleApplication1/My Project/Settings.Designer.vb new file mode 100644 index 00000000..d4f93818 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.ConsoleApplication1.My.MySettings + Get + Return Global.ConsoleApplication1.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/projects/languages/vbnet/ConsoleApplication1/My Project/Settings.settings b/projects/languages/vbnet/ConsoleApplication1/My Project/Settings.settings new file mode 100644 index 00000000..85b890b3 --- /dev/null +++ b/projects/languages/vbnet/ConsoleApplication1/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/projects/languages/vbnet/README.md b/projects/languages/vbnet/README.md new file mode 100644 index 00000000..00d4b1ba --- /dev/null +++ b/projects/languages/vbnet/README.md @@ -0,0 +1,3 @@ +# Analyze this project with SonarQube + +See http://docs.sonarqube.org/x/DgEW for details on how to analyze this project using the MSBuild SonarQube Runner. diff --git a/projects/languages/web/web-sonar-runner/README.md b/projects/languages/web/web-sonar-runner/README.md new file mode 100644 index 00000000..9f9b47f7 --- /dev/null +++ b/projects/languages/web/web-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze Web projects with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube Web Plugin](http://docs.sonarqube.org/display/PLUG/Web+Plugin) 2.4+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/web/web-sonar-runner/sonar-project.properties b/projects/languages/web/web-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..2c423258 --- /dev/null +++ b/projects/languages/web/web-sonar-runner/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:web-sq-scanner +sonar.projectName=Web :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=web + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/web/web-sonar-runner/src/sample.xhtml b/projects/languages/web/web-sonar-runner/src/sample.xhtml new file mode 100644 index 00000000..f9507854 --- /dev/null +++ b/projects/languages/web/web-sonar-runner/src/sample.xhtml @@ -0,0 +1,51 @@ + + + + + + + + + + User list + + + + +
  • Apple
  • +
  • Strawberry
  • + + + + + + + User + + + + + + + + + + + + + + + + + + + + + + + +
    + \ No newline at end of file diff --git a/projects/languages/web/web-sonar-runner/validation.txt b/projects/languages/web/web-sonar-runner/validation.txt new file mode 100644 index 00000000..f4086fc8 --- /dev/null +++ b/projects/languages/web/web-sonar-runner/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin web 2.4 +sonar-runner +verify org.sonarqube:web-sq-scanner + measure lines is 51 + measure ncloc is 37 + measure files is 1 +verify org.sonarqube:web-sq-scanner:src/sample.xhtml + measure lines is 51 + measure ncloc is 37 +stop server diff --git a/projects/languages/xml/xml-sonar-runner-custom-schema/README.md b/projects/languages/xml/xml-sonar-runner-custom-schema/README.md new file mode 100644 index 00000000..d2abcf18 --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner-custom-schema/README.md @@ -0,0 +1,21 @@ +This example demonstrates how to analyze an XML project with the SonarQube Scanner. +File validation against a custom schema. + +Prerequisites +============= +* [SonarQube](http://www.sonarsource.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SONAR/Analyzing+with+SonarQube+Scanner) 2.4+ +* [SonarQube XML Plugin](http://docs.sonarqube.org/display/PLUG/XML+Plugin) 1.4.1+ + +Usage +===== +* Copy the 'XML Schema Check' rule: + * Name: Validation against custom schema + * Default Severity: Blocker + * filePattern: leave it empty + * schemas: schemas/shiporder.xsd + * Description: Validation against custom schema +* Activate the 'Validation against custom schema' rule +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/xml/xml-sonar-runner-custom-schema/schemas/shiporder.xsd b/projects/languages/xml/xml-sonar-runner-custom-schema/schemas/shiporder.xsd new file mode 100644 index 00000000..6d1c83ad --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner-custom-schema/schemas/shiporder.xsd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/languages/xml/xml-sonar-runner-custom-schema/sonar-project.properties b/projects/languages/xml/xml-sonar-runner-custom-schema/sonar-project.properties new file mode 100644 index 00000000..ccd98ca2 --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner-custom-schema/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:xml-custom-schema-sq-scanner +sonar.projectName=XML :: Custom Schema :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=xml + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/xml/xml-sonar-runner-custom-schema/src/shiporder1.xml b/projects/languages/xml/xml-sonar-runner-custom-schema/src/shiporder1.xml new file mode 100644 index 00000000..12a007ca --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner-custom-schema/src/shiporder1.xml @@ -0,0 +1,22 @@ + + + + + John Smith +
    Main Street
    + New York + United States +
    + + Book1 + 1 + 10.90 + + + Book2 + 3 + 20.00 + +
    \ No newline at end of file diff --git a/projects/languages/xml/xml-sonar-runner-custom-schema/src/shiporder2.xml b/projects/languages/xml/xml-sonar-runner-custom-schema/src/shiporder2.xml new file mode 100644 index 00000000..7a219ce5 --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner-custom-schema/src/shiporder2.xml @@ -0,0 +1,18 @@ + + + + + Jack +
    Second Street
    + New York + United States +
    + + Book1 + 1 + 10.90 + blabla... + +
    \ No newline at end of file diff --git a/projects/languages/xml/xml-sonar-runner-custom-schema/validation.txt b/projects/languages/xml/xml-sonar-runner-custom-schema/validation.txt new file mode 100644 index 00000000..18d3d553 --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner-custom-schema/validation.txt @@ -0,0 +1,14 @@ +start server + with plugin xml 1.4 +sonar-runner +verify org.sonarqube:xml-custom-schema-sq-scanner + measure lines is 40 + measure ncloc is 38 + measure files is 2 +verify org.sonarqube:xml-custom-schema-sq-scanner:src/shiporder1.xml + measure lines is 22 + measure ncloc is 21 +verify org.sonarqube:xml-custom-schema-sq-scanner:src/shiporder2.xml + measure lines is 18 + measure ncloc is 17 +stop server diff --git a/projects/languages/xml/xml-sonar-runner/README.md b/projects/languages/xml/xml-sonar-runner/README.md new file mode 100644 index 00000000..597353ae --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze XML projects with the SonarQube Scanner. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ +* [SonarQube XML Plugin](http://docs.sonarqube.org/display/PLUG/XML+Plugin) 1.4.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/languages/xml/xml-sonar-runner/sonar-project.properties b/projects/languages/xml/xml-sonar-runner/sonar-project.properties new file mode 100644 index 00000000..8366771b --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner/sonar-project.properties @@ -0,0 +1,13 @@ +# Required metadata +sonar.projectKey=org.sonarqube:xml-sq-scanner +sonar.projectName=XML :: SonarQube Scanner +sonar.projectVersion=1.0 + +# Comma-separated paths to directories with sources (required) +sonar.sources=src + +# Language +sonar.language=xml + +# Encoding of the source files +sonar.sourceEncoding=UTF-8 \ No newline at end of file diff --git a/projects/languages/xml/xml-sonar-runner/src/sonar_backup.xml b/projects/languages/xml/xml-sonar-runner/src/sonar_backup.xml new file mode 100644 index 00000000..76e4dd45 --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner/src/sonar_backup.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/languages/xml/xml-sonar-runner/validation.txt b/projects/languages/xml/xml-sonar-runner/validation.txt new file mode 100644 index 00000000..07a96790 --- /dev/null +++ b/projects/languages/xml/xml-sonar-runner/validation.txt @@ -0,0 +1,11 @@ +start server + with plugin xml 1.4 +sonar-runner +verify org.sonarqube:xml-sq-scanner + measure lines is 233 + measure ncloc is 233 + measure files is 1 +verify org.sonarqube:xml-sq-scanner:src/sonar_backup.xml + measure lines is 233 + measure ncloc is 233 +stop server diff --git a/projects/multi-module/ant/README.md b/projects/multi-module/ant/README.md new file mode 100644 index 00000000..6d0acc76 --- /dev/null +++ b/projects/multi-module/ant/README.md @@ -0,0 +1,4 @@ +The best way to understand how the SonarQube Ant Task 2.0+ works is to give a try to the examples following this order: +* /projects/languages/java/ant/java-ant-simple +* java-ant-modules-same-structure +* java-ant-modules-different-structures \ No newline at end of file diff --git a/projects/multi-module/ant/java-ant-modules-different-structures/Module 1/build.xml b/projects/multi-module/ant/java-ant-modules-different-structures/Module 1/build.xml new file mode 100644 index 00000000..7b8b399a --- /dev/null +++ b/projects/multi-module/ant/java-ant-modules-different-structures/Module 1/build.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/ant-modules/module-one/src/java/One.java b/projects/multi-module/ant/java-ant-modules-different-structures/Module 1/sources/java/One.java similarity index 100% rename from projects/ant-modules/module-one/src/java/One.java rename to projects/multi-module/ant/java-ant-modules-different-structures/Module 1/sources/java/One.java diff --git a/projects/multi-module/ant/java-ant-modules-different-structures/README.md b/projects/multi-module/ant/java-ant-modules-different-structures/README.md new file mode 100644 index 00000000..37e0a1f8 --- /dev/null +++ b/projects/multi-module/ant/java-ant-modules-different-structures/README.md @@ -0,0 +1,16 @@ +This example demonstrates how to analyze a multi-module Java project with Ant. +Modules have different structures. + +Prerequisites +============= +* [SonarQube](http://www.sonarsource.org/downloads/) 4.5+ +* [SonarQube Scanner for Ant](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Ant) 2.4.1+ +* [Ant](http://ant.apache.org/) 1.7.1 or higher + +Usage +===== +* Set the path to the SonarQube Ant Task in the build.xml file +* Set the sonar.jdbc.* properties in the build.xml file +* Run the following command: + + ant all diff --git a/projects/multi-module/ant/java-ant-modules-different-structures/build.xml b/projects/multi-module/ant/java-ant-modules-different-structures/build.xml new file mode 100644 index 00000000..bf03347c --- /dev/null +++ b/projects/multi-module/ant/java-ant-modules-different-structures/build.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/ant-modules/module-two/build.xml b/projects/multi-module/ant/java-ant-modules-different-structures/module-two/build.xml similarity index 53% rename from projects/ant-modules/module-two/build.xml rename to projects/multi-module/ant/java-ant-modules-different-structures/module-two/build.xml index 790eca04..86bdf84a 100644 --- a/projects/ant-modules/module-two/build.xml +++ b/projects/multi-module/ant/java-ant-modules-different-structures/module-two/build.xml @@ -1,27 +1,15 @@ - - - Module Two - - - - - - + + - + - @@ -31,11 +19,10 @@ - + - + diff --git a/projects/ant-modules/module-two/src/java/Two.java b/projects/multi-module/ant/java-ant-modules-different-structures/module-two/src/java/Two.java similarity index 100% rename from projects/ant-modules/module-two/src/java/Two.java rename to projects/multi-module/ant/java-ant-modules-different-structures/module-two/src/java/Two.java diff --git a/projects/multi-module/ant/java-ant-modules-same-structure/README.md b/projects/multi-module/ant/java-ant-modules-same-structure/README.md new file mode 100644 index 00000000..85f42e13 --- /dev/null +++ b/projects/multi-module/ant/java-ant-modules-same-structure/README.md @@ -0,0 +1,16 @@ +This example demonstrates how to analyze a multi-module Java project with Ant. +The structure is the same for every module. + +Prerequisites +============= +* [SonarQube](http://www.sonarsource.org/downloads/) 4.5+ +* [SonarQube Scanner for Ant](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Ant) 2.4.1+ +* [Ant](http://ant.apache.org/) 1.7.1 or higher + +Usage +===== +* Set the path to the SonarQube Ant Task in the build.xml file +* Set the sonar.jdbc.* properties in the build.xml file +* Run the following command: + + ant all diff --git a/projects/multi-module/ant/java-ant-modules-same-structure/build.xml b/projects/multi-module/ant/java-ant-modules-same-structure/build.xml new file mode 100644 index 00000000..5cb359e9 --- /dev/null +++ b/projects/multi-module/ant/java-ant-modules-same-structure/build.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/ant-modules/module-one/build.xml b/projects/multi-module/ant/java-ant-modules-same-structure/module-one/build.xml similarity index 53% rename from projects/ant-modules/module-one/build.xml rename to projects/multi-module/ant/java-ant-modules-same-structure/module-one/build.xml index f335acf3..f8c66c53 100644 --- a/projects/ant-modules/module-one/build.xml +++ b/projects/multi-module/ant/java-ant-modules-same-structure/module-one/build.xml @@ -1,28 +1,15 @@ - - - Module One - - - - - - - + + - + - @@ -32,11 +19,10 @@ - + - + diff --git a/projects/gradle-modules/module-one/src/main/java/One.java b/projects/multi-module/ant/java-ant-modules-same-structure/module-one/src/java/One.java similarity index 100% rename from projects/gradle-modules/module-one/src/main/java/One.java rename to projects/multi-module/ant/java-ant-modules-same-structure/module-one/src/java/One.java diff --git a/projects/multi-module/ant/java-ant-modules-same-structure/module-two/build.xml b/projects/multi-module/ant/java-ant-modules-same-structure/module-two/build.xml new file mode 100644 index 00000000..dff3e4e2 --- /dev/null +++ b/projects/multi-module/ant/java-ant-modules-same-structure/module-two/build.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/gradle-modules/module-two/src/main/java/Two.java b/projects/multi-module/ant/java-ant-modules-same-structure/module-two/src/java/Two.java similarity index 100% rename from projects/gradle-modules/module-two/src/main/java/Two.java rename to projects/multi-module/ant/java-ant-modules-same-structure/module-two/src/java/Two.java diff --git a/projects/multi-module/gradle/README.md b/projects/multi-module/gradle/README.md new file mode 100644 index 00000000..2a3b27c8 --- /dev/null +++ b/projects/multi-module/gradle/README.md @@ -0,0 +1 @@ +A simple gradle project (no modules) is available at ../../languages/java/gradle/java-gradle-simple diff --git a/projects/multi-module/gradle/java-gradle-modules/README.md b/projects/multi-module/gradle/java-gradle-modules/README.md new file mode 100644 index 00000000..a484590f --- /dev/null +++ b/projects/multi-module/gradle/java-gradle-modules/README.md @@ -0,0 +1,12 @@ +This example demonstrates how to analyze a multi-module Java project with Gradle. + +Prerequisites +============= +* [SonarQube](http://www.sonarsource.org/downloads/) 4.5+ +* [Gradle](http://www.gradle.org/) 1.12 or higher + +Usage +===== +* Analyze the project with SonarQube using Gradle: + + gradle sonarqube [-Dsonar.host.url=... -Dsonar.jdbc.url=... -Dsonar.jdbc.username=... -Dsonar.jdbc.password=...] diff --git a/projects/multi-module/gradle/java-gradle-modules/build.gradle b/projects/multi-module/gradle/java-gradle-modules/build.gradle new file mode 100644 index 00000000..f2cad3a1 --- /dev/null +++ b/projects/multi-module/gradle/java-gradle-modules/build.gradle @@ -0,0 +1,36 @@ +apply plugin: 'java' +apply plugin: 'org.sonarqube' + +allprojects { + ext.baseVersion = "0.1" + ext.snapshotVersion = true + + group = "org.sonarqube" + version = "$baseVersion" + (snapshotVersion ? "-SNAPSHOT" : "") +} + +sonarqube { + properties { + property "sonar.projectName", "Java :: MultiModules Project :: Gradle SonarQube Plugin" + property "sonar.projectKey", "org.sonarqube:java-gradle-multimodules" + } +} + +subprojects { + apply plugin: 'java' +} + +buildscript { + repositories { + maven { + url "http://repo1.maven.org/maven2/" + } + maven { + url "https://plugins.gradle.org/m2/" + } + mavenLocal() + } + dependencies { + classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:1.2' + } +} diff --git a/projects/multi-module/gradle/java-gradle-modules/module-one/src/main/java/One.java b/projects/multi-module/gradle/java-gradle-modules/module-one/src/main/java/One.java new file mode 100644 index 00000000..1a883cfc --- /dev/null +++ b/projects/multi-module/gradle/java-gradle-modules/module-one/src/main/java/One.java @@ -0,0 +1,8 @@ +public class One { + + public String message = ""; + + public String foo() { + return "foo"; + } +} diff --git a/projects/multi-module/gradle/java-gradle-modules/module-two/src/main/java/Two.java b/projects/multi-module/gradle/java-gradle-modules/module-two/src/main/java/Two.java new file mode 100644 index 00000000..dd6b972f --- /dev/null +++ b/projects/multi-module/gradle/java-gradle-modules/module-two/src/main/java/Two.java @@ -0,0 +1,5 @@ +public class Two { + public String foo() { + return "foo"; + } +} diff --git a/projects/gradle-modules/settings.gradle b/projects/multi-module/gradle/java-gradle-modules/settings.gradle similarity index 100% rename from projects/gradle-modules/settings.gradle rename to projects/multi-module/gradle/java-gradle-modules/settings.gradle diff --git a/projects/multi-module/sonar-runner/README.md b/projects/multi-module/sonar-runner/README.md new file mode 100644 index 00000000..69592117 --- /dev/null +++ b/projects/multi-module/sonar-runner/README.md @@ -0,0 +1,5 @@ +The best way to understand how SonarQube Runner 2.0+ works is to give a try to the examples following this order: +* /projects/languages/java/java-sonar-runner-simple +* java-sonar-runner-modules-same-structure +* java-sonar-runner-modules-different-structures +* java-sonar-runner-modules-own-configuration-file \ No newline at end of file diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/Module 2/sources/Helloworld2.java b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/Module 2/sources/Helloworld2.java new file mode 100644 index 00000000..31f17de6 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/Module 2/sources/Helloworld2.java @@ -0,0 +1,7 @@ +public class Helloworld2 { + + public void printHelloWorld2() { + System.out.println("Hello World 2!"); + } + +} diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/README.md b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/README.md new file mode 100644 index 00000000..f19ff1f4 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a multi-module Java project with the SonarQube Scanner. +Modules have different structures. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/module1/src/Helloworld1.java b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/module1/src/Helloworld1.java new file mode 100644 index 00000000..bbf16532 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/module1/src/Helloworld1.java @@ -0,0 +1,8 @@ +public class Helloworld1 { + + public void printHelloWorld1() { + System.out.println("Hello World 1!"); + } + +} + diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/sonar-project.properties b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/sonar-project.properties new file mode 100644 index 00000000..6029a138 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/sonar-project.properties @@ -0,0 +1,19 @@ +sonar.projectKey=java-sonar-runner-modules-different-structures +sonar.projectName=Multi-module Java project analyzed with the SonarQube Runner (modules have different structures) +sonar.projectVersion=1.0 + +# Set modules IDs +sonar.modules=module1,module2 + +# Modules inherit properties set at parent level +sonar.sources=src +sonar.sourceEncoding=UTF-8 +sonar.language=java + +# Default module base directory is / +# It has to be overriden for module2 +module2.sonar.projectBaseDir=Module 2 + +# Overrides some parent properties in module2 +module2.sonar.sources=sources +module2.sonar.projectName=Module #2 diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/validation.txt b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/validation.txt new file mode 100644 index 00000000..c0d56802 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-different-structures/validation.txt @@ -0,0 +1,25 @@ +start server + with plugin java 3.7.1 +sonar-runner +verify java-sonar-runner-modules-different-structures + measure lines is 17 + measure ncloc is 10 + measure files is 2 + measure classes is 2 +verify java-sonar-runner-modules-different-structures:module1 + measure lines is 9 + measure ncloc is 5 + measure files is 1 + measure classes is 1 +verify java-sonar-runner-modules-different-structures:module1:src/Helloworld1.java + measure lines is 9 + measure ncloc is 5 +verify java-sonar-runner-modules-different-structures:module2 + measure lines is 8 + measure ncloc is 5 + measure files is 1 + measure classes is 1 +verify java-sonar-runner-modules-different-structures:module2:sources/Helloworld2.java + measure lines is 8 + measure ncloc is 5 +stop server diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/Module 2/sonar-project.properties b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/Module 2/sonar-project.properties new file mode 100644 index 00000000..63ba27cf --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/Module 2/sonar-project.properties @@ -0,0 +1,2 @@ +sonar.projectName=Module #2 +sonar.sources=sources \ No newline at end of file diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/Module 2/sources/Helloworld2.java b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/Module 2/sources/Helloworld2.java new file mode 100644 index 00000000..31f17de6 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/Module 2/sources/Helloworld2.java @@ -0,0 +1,7 @@ +public class Helloworld2 { + + public void printHelloWorld2() { + System.out.println("Hello World 2!"); + } + +} diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/README.md b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/README.md new file mode 100644 index 00000000..036e6cb5 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/README.md @@ -0,0 +1,12 @@ +This example demonstrates how to analyze a multi-module Java project with the SonarQube Scanner. +Each module has its own configuration file (sonar-project.properties). + +Prerequisites +============= +./projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/README.md + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/module1/sonar-project.properties b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/module1/sonar-project.properties new file mode 100644 index 00000000..c7955df8 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/module1/sonar-project.properties @@ -0,0 +1 @@ +sonar.projectName=Module #1 \ No newline at end of file diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/module1/src/Helloworld1.java b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/module1/src/Helloworld1.java new file mode 100644 index 00000000..bbf16532 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/module1/src/Helloworld1.java @@ -0,0 +1,8 @@ +public class Helloworld1 { + + public void printHelloWorld1() { + System.out.println("Hello World 1!"); + } + +} + diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/sonar-project.properties b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/sonar-project.properties new file mode 100644 index 00000000..105629ba --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/sonar-project.properties @@ -0,0 +1,14 @@ +sonar.projectKey=java-sonar-runner-modules-own-configuration-file +sonar.projectName=Multi-module Java project analyzed with the SonarQube Runner (each module has its own configuration file) +sonar.projectVersion=1.0 + +# Set modules IDs +sonar.modules=module1,module2 + +# Modules inherit properties set at parent level +sonar.sources=src +sonar.sourceEncoding=UTF-8 +sonar.language=java + +# By default, the base directory for a module is /. +module2.sonar.projectBaseDir=Module 2 diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/validation.txt b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/validation.txt new file mode 100644 index 00000000..ca76513f --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-own-configuration-file/validation.txt @@ -0,0 +1,25 @@ +start server + with plugin java 3.7.1 +sonar-runner +verify java-sonar-runner-modules-own-configuration-file + measure lines is 17 + measure ncloc is 10 + measure files is 2 + measure classes is 2 +verify java-sonar-runner-modules-own-configuration-file:module1 + measure lines is 9 + measure ncloc is 5 + measure files is 1 + measure classes is 1 +verify java-sonar-runner-modules-own-configuration-file:module1:src/Helloworld1.java + measure lines is 9 + measure ncloc is 5 +verify java-sonar-runner-modules-own-configuration-file:module2 + measure lines is 8 + measure ncloc is 5 + measure files is 1 + measure classes is 1 +verify java-sonar-runner-modules-own-configuration-file:module2:sources/Helloworld2.java + measure lines is 8 + measure ncloc is 5 +stop server diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/README.md b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/README.md new file mode 100644 index 00000000..e3870ad0 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/README.md @@ -0,0 +1,13 @@ +This example demonstrates how to analyze a multi-module Java project with the SonarQube Scanner. +The structure is the same for every module. + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Scanner](http://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) 2.6.1+ + +Usage +===== +* Analyze the project with SonarQube using the SonarQube Scanner: + + sonar-scanner diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/module1/src/Helloworld1.java b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/module1/src/Helloworld1.java new file mode 100644 index 00000000..bbf16532 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/module1/src/Helloworld1.java @@ -0,0 +1,8 @@ +public class Helloworld1 { + + public void printHelloWorld1() { + System.out.println("Hello World 1!"); + } + +} + diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/module2/src/Helloworld2.java b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/module2/src/Helloworld2.java new file mode 100644 index 00000000..31f17de6 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/module2/src/Helloworld2.java @@ -0,0 +1,7 @@ +public class Helloworld2 { + + public void printHelloWorld2() { + System.out.println("Hello World 2!"); + } + +} diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/sonar-project.properties b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/sonar-project.properties new file mode 100644 index 00000000..bdff3d0a --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/sonar-project.properties @@ -0,0 +1,11 @@ +sonar.projectKey=java-sonar-runner-modules-same-structure +sonar.projectName=Multi-module Java project analyzed with the SonarQube Runner (same structure for every module) +sonar.projectVersion=1.0 + +# Set modules IDs +sonar.modules=module1,module2 + +# Modules inherit properties set at parent level +sonar.sources=src +sonar.sourceEncoding=UTF-8 +sonar.language=java \ No newline at end of file diff --git a/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/validation.txt b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/validation.txt new file mode 100644 index 00000000..224d5452 --- /dev/null +++ b/projects/multi-module/sonar-runner/java-sonar-runner-modules-same-structure/validation.txt @@ -0,0 +1,25 @@ +start server + with plugin java 3.7.1 +sonar-runner +verify java-sonar-runner-modules-same-structure + measure lines is 17 + measure ncloc is 10 + measure files is 2 + measure classes is 2 +verify java-sonar-runner-modules-same-structure:module1 + measure lines is 9 + measure ncloc is 5 + measure files is 1 + measure classes is 1 +verify java-sonar-runner-modules-same-structure:module1:src/Helloworld1.java + measure lines is 9 + measure ncloc is 5 +verify java-sonar-runner-modules-same-structure:module2 + measure lines is 8 + measure ncloc is 5 + measure files is 1 + measure classes is 1 +verify java-sonar-runner-modules-same-structure:module2:src/Helloworld2.java + measure lines is 8 + measure ncloc is 5 +stop server diff --git a/projects/tycho/README.md b/projects/tycho/README.md new file mode 100644 index 00000000..fdb55b14 --- /dev/null +++ b/projects/tycho/README.md @@ -0,0 +1,18 @@ +This example demonstrates how to collect code coverage by tests, which executed by [tycho-surefire-plugin](http://www.eclipse.org/tycho/). + +Prerequisites +============= +* [SonarQube](http://www.sonarqube.org/downloads/) 4.5+ +* [SonarQube Java Plugin](http://docs.sonarqube.org/display/PLUG/Java+Plugin) 3.13.1+ +* Maven 3.0.3+ + +Execution +========= + +1. Build project and execute all tests: + + mvn clean install + +2. Analyze with SonarQube: + + mvn sonar:sonar diff --git a/projects/tycho/plugin.tests/META-INF/MANIFEST.MF b/projects/tycho/plugin.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000..9cfe3a8c --- /dev/null +++ b/projects/tycho/plugin.tests/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Example Plug-in Tests +Bundle-SymbolicName: plugin.tests +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Require-Bundle: org.junit4;bundle-version="[4.0.0,5.0.0)", + plugin;bundle-version="1.0.0" diff --git a/projects/tycho/plugin.tests/build.properties b/projects/tycho/plugin.tests/build.properties new file mode 100644 index 00000000..56d77655 --- /dev/null +++ b/projects/tycho/plugin.tests/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/projects/tycho/plugin.tests/pom.xml b/projects/tycho/plugin.tests/pom.xml new file mode 100644 index 00000000..c99e7676 --- /dev/null +++ b/projects/tycho/plugin.tests/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + + org.example.tycho-example + parent + 1.0.0-SNAPSHOT + + + plugin.tests + eclipse-test-plugin + + JaCoCo Examples :: tycho-example :: plugin.tests + + + + + src + + + diff --git a/projects/tycho/plugin.tests/src/example/GreetingTest.java b/projects/tycho/plugin.tests/src/example/GreetingTest.java new file mode 100644 index 00000000..5ae738be --- /dev/null +++ b/projects/tycho/plugin.tests/src/example/GreetingTest.java @@ -0,0 +1,12 @@ +package example; + +import org.junit.Test; + +public class GreetingTest +{ + @Test + public void test() + { + new Greeting().coveredByTest(); + } +} diff --git a/projects/tycho/plugin/META-INF/MANIFEST.MF b/projects/tycho/plugin/META-INF/MANIFEST.MF new file mode 100644 index 00000000..ea1934e6 --- /dev/null +++ b/projects/tycho/plugin/META-INF/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Example Plug-in +Bundle-SymbolicName: plugin;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Export-Package: example diff --git a/projects/tycho/plugin/build.properties b/projects/tycho/plugin/build.properties new file mode 100644 index 00000000..56d77655 --- /dev/null +++ b/projects/tycho/plugin/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/projects/tycho/plugin/pom.xml b/projects/tycho/plugin/pom.xml new file mode 100644 index 00000000..d999146c --- /dev/null +++ b/projects/tycho/plugin/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + + org.example.tycho-example + parent + 1.0.0-SNAPSHOT + + + plugin + eclipse-plugin + + JaCoCo Examples :: tycho-example :: plugin + + diff --git a/projects/tycho/plugin/src/example/Greeting.java b/projects/tycho/plugin/src/example/Greeting.java new file mode 100644 index 00000000..170658dc --- /dev/null +++ b/projects/tycho/plugin/src/example/Greeting.java @@ -0,0 +1,9 @@ +package example; + +public class Greeting +{ + public void coveredByTest() + { + System.out.println("Hello, world."); + } +} diff --git a/projects/tycho/pom.xml b/projects/tycho/pom.xml new file mode 100644 index 00000000..c5ad9c37 --- /dev/null +++ b/projects/tycho/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + org.example.tycho-example + parent + pom + 1.0.0-SNAPSHOT + + JaCoCo Examples :: tycho-example :: parent + + + plugin + plugin.tests + + + + UTF-8 + UTF-8 + + + ${project.basedir}/../target/jacoco.exec + + + + + + org.eclipse.tycho + tycho-maven-plugin + 0.24.0 + true + + + org.jacoco + jacoco-maven-plugin + 0.7.5.201505241946 + + true + + example.* + + ${sonar.jacoco.reportPath} + + + + + prepare-agent + + + + + + + + + + eclipse-indigo + p2 + http://download.eclipse.org/releases/indigo + + + + diff --git a/scripts/database/mysql/create_database.sql b/scripts/database/mysql/create_database.sql new file mode 100644 index 00000000..554cfcf1 --- /dev/null +++ b/scripts/database/mysql/create_database.sql @@ -0,0 +1,11 @@ +# Create SonarQube database and user. +# +# Command: mysql -u root -p < create_database.sql +# + +CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci; + +CREATE USER 'sonar' IDENTIFIED BY 'sonar'; +GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar'; +GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar'; +FLUSH PRIVILEGES; diff --git a/scripts/database/mysql/drop_database.sql b/scripts/database/mysql/drop_database.sql new file mode 100644 index 00000000..de3beac9 --- /dev/null +++ b/scripts/database/mysql/drop_database.sql @@ -0,0 +1,8 @@ +# Drop SonarQube database and user. +# +# Command: mysql -u root -p < drop_database.sql +# + +DROP DATABASE IF EXISTS sonar; +DROP USER 'sonar'@'localhost'; +DROP USER 'sonar'@'%'; \ No newline at end of file diff --git a/ws/manual-measure-ws/README.md b/ws/manual-measure-ws/README.md new file mode 100644 index 00000000..dce85598 --- /dev/null +++ b/ws/manual-measure-ws/README.md @@ -0,0 +1,23 @@ +This example demonstrates how to use the SonarQube web service API (manual_measures). + +Documentation +============= +* http://docs.codehaus.org/x/iABuC + +Prerequisites +============= +* [SonarQube](http://www.sonarsource.org/downloads/) 3.5 or higher + +Usage +===== +* In src/main/java/sample/Sample.java, set the proper values to connect to your SonarQube server and project. +* Compile the project: + + mvn clean compile assembly:single + +* Call the web service: + + cd target + java -jar manual-measure-ws-1.0-SNAPSHOT-jar-with-dependencies.jar + +* Check the output diff --git a/ws/manual-measure-ws/pom.xml b/ws/manual-measure-ws/pom.xml new file mode 100644 index 00000000..207d59ff --- /dev/null +++ b/ws/manual-measure-ws/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + org.codehaus.sonar + manual-measure-ws + 1.0-SNAPSHOT + Example of Sonar manual measure web service call + + + + org.codehaus.sonar + sonar-ws-client + 3.7.4 + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + + + + + maven-assembly-plugin + + + + sample.Sample + + + + jar-with-dependencies + + + + + + + \ No newline at end of file diff --git a/ws/manual-measure-ws/src/main/java/sample/Sample.java b/ws/manual-measure-ws/src/main/java/sample/Sample.java new file mode 100644 index 00000000..9e9e37fa --- /dev/null +++ b/ws/manual-measure-ws/src/main/java/sample/Sample.java @@ -0,0 +1,26 @@ +package sample; + +import org.sonar.wsclient.Host; +import org.sonar.wsclient.Sonar; +import org.sonar.wsclient.connectors.HttpClient4Connector; +import org.sonar.wsclient.services.*; + +public class Sample { + + public static void main(String args[]) { + String url = "http://localhost:9000"; + String login = "admin"; + String password = "admin"; + Sonar sonar = new Sonar(new HttpClient4Connector(new Host(url, login, password))); + + String projectKey = "java-sonar-runner-simple"; + String manualMetricKey = "burned_budget"; + + sonar.create(ManualMeasureCreateQuery.create(projectKey, manualMetricKey).setValue(50.0)); + + for (ManualMeasure manualMeasure : sonar.findAll(ManualMeasureQuery.create(projectKey))) { + System.out.println("Manual measure on project: " + manualMeasure); + } + } + +}