├── .classpath ├── .gitignore ├── .gitlab-ci.yml ├── .project ├── .settings ├── org.eclipse.jdt.core.prefs ├── org.eclipse.jdt.ui.prefs ├── org.eclipse.m2e.core.prefs └── org.eclipse.wst.common.project.facet.core.xml ├── .travis.yml ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── logo.jpeg ├── pom.xml └── src ├── main ├── java │ └── fr │ │ └── univartois │ │ └── sonargo │ │ ├── SonarGoPlugin.java │ │ ├── core │ │ ├── Parser.java │ │ ├── ProjectExplorer.java │ │ ├── language │ │ │ ├── GoGrammar.java │ │ │ ├── GoLanguage.java │ │ │ ├── GoLexer.java │ │ │ ├── GoParser.java │ │ │ └── GoQualityProfile.java │ │ ├── metrics │ │ │ ├── GoLineMetrics.java │ │ │ └── GoMetricSensor.java │ │ ├── rules │ │ │ ├── GoError.java │ │ │ ├── GoKeyRule.java │ │ │ ├── GoLintIssueLoaderSensor.java │ │ │ └── GoLintRulesDefinition.java │ │ └── settings │ │ │ └── GoProperties.java │ │ ├── coverage │ │ ├── CoverageParser.java │ │ ├── CoverageSensor.java │ │ ├── FactoryLine.java │ │ ├── LineCoverage.java │ │ └── LinePredicate.java │ │ ├── gotest │ │ ├── FunctionFinder.java │ │ ├── GoJunitParser.java │ │ ├── GoTestCase.java │ │ ├── GoTestFile.java │ │ ├── GoTestReportSaver.java │ │ └── GoTestSensor.java │ │ ├── highlighter │ │ ├── Colorizer.java │ │ └── HighlighterSensor.java │ │ └── toolkit │ │ ├── GoColorizer.java │ │ └── GoToolkit.java └── resources │ ├── key.properties │ ├── profile.properties │ └── rules │ └── golint-rules.xml └── test ├── java └── fr │ └── univartois │ └── sonargo │ ├── AbstractSonarTest.java │ ├── AllTests.java │ ├── FunctionFinderTest.java │ ├── GoPluginTest.java │ ├── TestUtils.java │ ├── core │ ├── ProjectExplorerTest.java │ ├── language │ │ ├── GoGrammarTest.java │ │ ├── GoLanguageTest.java │ │ ├── GoLexerTest.java │ │ └── GoQualityProfileTest.java │ ├── metrics │ │ └── GoMetricSensorTest.java │ ├── rules │ │ ├── EvalTest.java │ │ ├── GoErrorTest.java │ │ ├── GoLintIssueLoaderSendorTest.java │ │ ├── GoLintRulesDefinitionTest.java │ │ ├── ReportEvalStoryTest.java │ │ └── expression.story │ └── settings │ │ └── GoPropertiesTest.java │ ├── coverage │ └── CoverageSensorTest.java │ ├── gotest │ └── FunctionFinderTest.java │ └── highlighter │ └── ColorizerTest.java └── resources ├── coverage ├── .ignoredfile ├── .sonar │ └── test ├── bug │ └── coverage.xml ├── issue60 │ └── a.go ├── issue61 │ ├── multilinecomment.go │ ├── simplelinecomment.go │ └── typestruct.go ├── mathutil │ ├── coverage.out │ ├── coverage.out.xml │ ├── coverage.xml │ ├── filewithnocoverage.go │ ├── mathutil.go │ └── mathutil_test.go ├── pixel │ ├── coverage.out │ ├── coverage.xml │ ├── pixel.go │ └── pixel_test.go ├── test ├── test.git │ └── test ├── util │ ├── cover.out │ ├── coverage.out.xml │ ├── coverage.xml │ ├── util.go │ ├── util2.go │ ├── util2_test.go │ └── util_test.go └── vendor │ └── fileexcludedinvendordirectory.txt ├── gotest ├── test1_test.go ├── test2_test.go └── test_test.go ├── grammar ├── constant_expressions.go ├── import_complex_definition.go ├── import_simple_definition.go ├── package_definition.go ├── var_definition.go └── var_fast_definition.go ├── highlighter ├── test.go └── testbug1.go ├── key.properties ├── profile.properties ├── project ├── package1.go ├── package1_test.go └── test.py └── rules └── golint-rules.xml /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /build/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | pom.xml.next 7 | release.properties 8 | dependency-reduced-pom.xml 9 | buildNumber.properties 10 | .mvn/timing.properties 11 | doc 12 | .sonar 13 | .idea/ 14 | *.iml 15 | !./src/test/resources/coverage/.sonar 16 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | 2 | 3 | artifact: 4 | script: "mvn clean install && mvn clean verify sonar:sonar" 5 | stage: build 6 | artifacts: 7 | paths: 8 | - target/*.jar 9 | tags: 10 | - maven -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | sonarqubego 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.xtext.ui.shared.xtextBuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.m2e.core.maven2Builder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.m2e.core.maven2Nature 31 | org.eclipse.wst.common.project.facet.core.nature 32 | org.eclipse.jdt.core.javanature 33 | org.eclipse.xtext.ui.shared.xtextNature 34 | 35 | 36 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true 3 | formatter_profile=_Java Conventions Artois 4 | formatter_settings_version=12 5 | org.eclipse.jdt.ui.exception.name=e 6 | org.eclipse.jdt.ui.gettersetter.use.is=true 7 | org.eclipse.jdt.ui.keywordthis=false 8 | org.eclipse.jdt.ui.overrideannotation=true 9 | sp_cleanup.add_default_serial_version_id=true 10 | sp_cleanup.add_generated_serial_version_id=false 11 | sp_cleanup.add_missing_annotations=true 12 | sp_cleanup.add_missing_deprecated_annotations=true 13 | sp_cleanup.add_missing_methods=false 14 | sp_cleanup.add_missing_nls_tags=false 15 | sp_cleanup.add_missing_override_annotations=true 16 | sp_cleanup.add_missing_override_annotations_interface_methods=true 17 | sp_cleanup.add_serial_version_id=false 18 | sp_cleanup.always_use_blocks=true 19 | sp_cleanup.always_use_parentheses_in_expressions=false 20 | sp_cleanup.always_use_this_for_non_static_field_access=false 21 | sp_cleanup.always_use_this_for_non_static_method_access=false 22 | sp_cleanup.convert_functional_interfaces=false 23 | sp_cleanup.convert_to_enhanced_for_loop=false 24 | sp_cleanup.correct_indentation=false 25 | sp_cleanup.format_source_code=true 26 | sp_cleanup.format_source_code_changes_only=false 27 | sp_cleanup.insert_inferred_type_arguments=false 28 | sp_cleanup.make_local_variable_final=true 29 | sp_cleanup.make_parameters_final=false 30 | sp_cleanup.make_private_fields_final=true 31 | sp_cleanup.make_type_abstract_if_missing_method=false 32 | sp_cleanup.make_variable_declarations_final=false 33 | sp_cleanup.never_use_blocks=false 34 | sp_cleanup.never_use_parentheses_in_expressions=true 35 | sp_cleanup.on_save_use_additional_actions=false 36 | sp_cleanup.organize_imports=true 37 | sp_cleanup.qualify_static_field_accesses_with_declaring_class=false 38 | sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true 39 | sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true 40 | sp_cleanup.qualify_static_member_accesses_with_declaring_class=false 41 | sp_cleanup.qualify_static_method_accesses_with_declaring_class=false 42 | sp_cleanup.remove_private_constructors=true 43 | sp_cleanup.remove_redundant_type_arguments=false 44 | sp_cleanup.remove_trailing_whitespaces=false 45 | sp_cleanup.remove_trailing_whitespaces_all=true 46 | sp_cleanup.remove_trailing_whitespaces_ignore_empty=false 47 | sp_cleanup.remove_unnecessary_casts=true 48 | sp_cleanup.remove_unnecessary_nls_tags=false 49 | sp_cleanup.remove_unused_imports=false 50 | sp_cleanup.remove_unused_local_variables=false 51 | sp_cleanup.remove_unused_private_fields=true 52 | sp_cleanup.remove_unused_private_members=false 53 | sp_cleanup.remove_unused_private_methods=true 54 | sp_cleanup.remove_unused_private_types=true 55 | sp_cleanup.sort_members=false 56 | sp_cleanup.sort_members_all=false 57 | sp_cleanup.use_anonymous_class_creation=false 58 | sp_cleanup.use_blocks=false 59 | sp_cleanup.use_blocks_only_for_return_and_throw=false 60 | sp_cleanup.use_lambda=true 61 | sp_cleanup.use_parentheses_in_expressions=false 62 | sp_cleanup.use_this_for_non_static_field_access=false 63 | sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true 64 | sp_cleanup.use_this_for_non_static_method_access=false 65 | sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true 66 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: java 3 | sudo: false 4 | install: true 5 | addons: 6 | sonarcloud: 7 | organization: thibaultfalque-github 8 | token: 9 | secure: "fmvXUI+OCn3UThPkooHMJ7c/iwLQ4e8ZPBEP4lKNnMPvnO8jox4V9jBPhTcBZNHAn+SlMgV0C2ttZ6LjpJI+6ZEYi+AVBIGQb7RNdjpEue3nLNG1WzUbl0Byy/xwgWiIG1ffVXTkPdEoD6d9WoDvYr9p3Ff3n0/Op6GN0J27OU/7yq5OEXpwwsmS32yw4aAltZISLRWUPhqRrnV7aopfFr1zRGe4ddBe2UFIVH8gnTgYtYNF1FTiWdtPKeVDea3dnW9R/kwF/IFiVEk/gOXPFTWSOulFssc3o1p89yCFmnS4JZ8kK5IOnY1TZCVZ7MhprXLLRjy9+MlKIcwjlzsvAKHHc17krRKDsY4wZBT9QUa7nOG926YForIa9DOigQ4F+oMhiu2LRo/5qe2p9GgzRLx5RXsJ4rgGHPn6IkuVaX9qpvoyMwnS2fOy1NU93C8JDF1WKM/9RRBAKDpdI3iQIXqkPA3v86Jj/fkNTAKijqOPSKNiZzl5/5uysXLDIlSOKGkDurjRZ+H5gibx47nBm5Vx9ufq23hRWH55g1oMvUDj3XAs39Ih+Hqn1CwOfnTOC4gy6TE3fy5beE2cz7GVrO90eaog9IlGF0umIwAHb1PaEDkcLSpg3uWbAP7jrkqhhceqBeJJi98Ly+Hn0Nfkme6oBwbE9YqN/v7mSNLBa/g=" 10 | branches: 11 | - maintenance 12 | jdk: 13 | - oraclejdk8 14 | script: 15 | - mvn clean install sonar:sonar 16 | cache: 17 | directories: 18 | - "$HOME/.m2/repository" 19 | - "$HOME/.sonar/cache" 20 | env: 21 | global: 22 | secure: euv9zwF2OjgTWHBFmLUhxVWIlLcHALm8nNIz2a+MzBloB8f5bmtWSzik9JkyRoJJs3G9R/IT9nkdqi6Kw/7WtNTKhG+ZEDrnzWnHyJwhX7aaJCLJHDvoeC9Pv7h5JMotXQm8g1YOlUzAcs2A/hEfdpUYdjEU43+RGQHniBnAvMeumkmtq9dYR5Ch3J1m/fC3wqvQQREeMw4XIpHb4X/Ih9VMnPcCmiBhMdHAYGrbNXcwONCgYRZbyDoQP5ndx9vrnJ4BV+Q/x5E13jC//PdgwsWtgSKvOP5LIEFI/xSg/hKTSue8f4jBny4FEZ7G6PjeU7urTvf1qo1GSpS7W2pLEdnGoMvi5XqhNpRVgbItVlKVqGoh8VdR9zQvaDYifuvtLclOLnw2Rlan5oVgRbUzJWT0r98BZkdEH8PiW/0qycgBY5T4mcoXGAYjdu7ZFWdsE9SINbWmoCzXJgSJ6lySQOtSDD0wS5X510flRrwHytBa/9de19IEkW0yxPBQDPrDvMB/SOrjlvLP5DBDK52KhXhIugL0I/yMLzaKzqqyUeLkifpVrfW8Sg3sYF1louSwL2gL3dC2jbwpHM2Yc3pyUa1Q0/rpo0+tFpbmSb9ig0zHFNqp1Ia5t+3y+qSwlpAV8GenFfr/km0tDnfjnH96fAKQ2W0JKfnqVaZoOpfxYCM= 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Golang SonarQube Plugin 2 | 3 | The following is a set of guidelines for contributing to Golang Plugin Sonarqube, which are hosted in the University Artois Organization on GitHub. These are just guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. 4 | 5 | 6 | #### Table Of Contents 7 | [What should I know before I get started?](#what-should-i-know-before-i-get-started) 8 | 9 | ## What should I know before I get started? 10 | 11 | ### Convention 12 | 13 | This project respect the [code convention of Java](http://www.oracle.com/technetwork/java/codeconvtoc-136057.html). So if you want contributing you must respect this convention. 14 | 15 | ## How Can I Contribute? 16 | 17 | ### Reporting Bugs 18 | 19 | This section guides you through submitting a bug report for Atom. Following these guidelines helps maintainers and the community understand your report :pencil:. 20 | 21 | Create an issue on that repository and provide the following information by filling in [the template](ISSUE_TEMPLATE.md). 22 | 23 | 24 | ### Add rule from new Linter 25 | 26 | Gometalinter use many linters. So if the plugin don't report the violation of a linter, you can add new violation without write any code. 27 | 28 | For a rule you have 3 files that you must modify. 29 | 30 | * [the xml file of violations](https://github.com/uartois/sonar-golang/blob/master/src/main/resources/rules/golint-rules.xml). This file define the rules. A rule is a xml tag, for exemple: 31 | 32 | ```xml 33 | 34 | AUniqueKey 35 | A name for the rule 36 | AUniqueKey 37 | A description: foo should be bar 38 | Additional information can be found at .... (an eventual link with more information) 39 | 40 | MINORcan be MAJOR, BLOCKER or CRITICAL 41 | SINGLE 42 | READY 43 | CODE_SMELLcan be Vulnerability, Bug 44 | bad-practice 45 | comments 46 | CONSTANT_ISSUE 47 | 10min 48 | 49 | More information here https://docs.sonarqube.org/display/DEV/Coding+Rule+Guidelines 50 | ``` 51 | * [the key properties](https://github.com/uartois/sonar-golang/blob/master/src/main/resources/key.properties) This file define a pattern that can be match with the description and define a link between the issue in the gometalinter report and the violation in the xml. 52 | 53 | * [the profile properties](https://github.com/uartois/sonar-golang/blob/master/src/main/resources/profile.properties) This file associate the key of the rule with a boolean. If it's true the rule is activated by default. 54 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | [Description of the issue] 4 | 5 | ### Steps to Reproduce 6 | 7 | 1. [First Step] 8 | 2. [Second Step] 9 | 3. [and so on...] 10 | 11 | ### Content of your sonar-project.properties 12 | 13 | *It will help us to check how you configured the plugin.* 14 | 15 | ### Log of sonar-scanner related to the plugin 16 | 17 | *The plugin logs major events, including which report files have been found and analyzed.* 18 | 19 | ### Versions 20 | 21 | Versions of your sonar installation (server, sonar-scanner), gometalinter, go and OS. 22 | 23 | ### Additional Information 24 | 25 | Sample reports may be necessary to reproduce the issue. Please attach if possible reports files (report.xml, coverage.xml, test.xml) corresponding to the feature which is not working as expected. 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Community SonarQube Plugin for the Go language 2 | 3 | [![Build Status](https://travis-ci.org/uartois/sonar-golang.svg?branch=master)](https://travis-ci.org/uartois/sonar-golang) ![Quality Gates](https://sonarcloud.io/api/project_badges/measure?project=fr.univartois%3Asonar-golang-plugin%3Amaintenance&metric=alert_status) 4 | 5 | ![Sonarque for GoLang Logo](logo.jpeg) 6 | 7 | **This is a community plugin for SonarQube to support the Go language started in April 2017 at Artois University. 8 | Since May 2018, Go is officially supported by SonarSource with [SonarGo](https://github.com/SonarSource/sonar-go).** 9 | 10 | It integrates [GoMetaLinter](https://github.com/alecthomas/gometalinter) reports 11 | within SonarQube dashboard. 12 | 13 | The user must generate a GoMetaLinter report for the code using the checkstyle 14 | format. The report is thus integrated to SonarQube using 15 | [sonar-scanner](https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner). 16 | 17 | Release 1.0 only provides golint support. Release 1.1 provides test coverage support. Upcoming releases will bring support 18 | for additional linters. 19 | 20 | 21 | # Authors 22 | 23 | + Thibault Falque 24 | + Daniel Le Berre 25 | 26 | 27 | # Installation 28 | 29 | * Download the latest version of the artifact 30 | * Stop sonarqube server 31 | * Put the jar file in `$SONAR_PATH/extensions/plugins` 32 | * Start sonarqube server 33 | 34 | # Enabling all latest rules 35 | 36 | If you have already installed the plugin and you want to enable the new rules provided by 37 | the new version of the plugin, follow those steps after the installation: 38 | 39 | * Go on the Quality Profiles page 40 | * Click on the arrow near the "Create" button 41 | * Click on "Restore Built-In Profiles" 42 | * Choose the language (Go) 43 | * Click on "Restore" 44 | 45 | 46 | # Using the plugin 47 | 48 | * create a `sonar-project.properties` file. 49 | 50 | ``` 51 | sonar.projectKey=yourprojectid 52 | sonar.projectName=name of project 53 | sonar.projectVersion=1.0 54 | # GoLint report path, default value is report.xml 55 | sonar.golint.reportPath=report.xml 56 | # Cobertura like coverage report path, default value is coverage.xml 57 | sonar.coverage.reportPath=coverage.xml 58 | # if you want disabled the DTD verification for a proxy problem for example, true by default 59 | sonar.coverage.dtdVerification=false 60 | # JUnit like test report, default value is test.xml 61 | sonar.test.reportPath=test.xml 62 | sonar.sources=./ 63 | sonar.tests=./ 64 | sonar.test.inclusions=**/**_test.go 65 | sonar.sources.inclusions=**/**.go 66 | ``` 67 | 68 | * start the analysis 69 | ```shell 70 | sonar-scanner 71 | ``` 72 | 73 | It is assumed that you have the sonar scanner executable on your path and 74 | to run it at the root of your go project. 75 | 76 | # GoMetaLinter support 77 | 78 | * install [gometalinter](https://github.com/alecthomas/gometalinter) 79 | ```shell 80 | go get -u gopkg.in/alecthomas/gometalinter.v1 81 | gometalinter.v1 --install 82 | ``` 83 | 84 | * Generate a gometalinter report using the checkstyle format: 85 | ```shell 86 | gometalinter.v1 --checkstyle > report.xml 87 | ``` 88 | 89 | # Coverage (since release 1.1) 90 | 91 | For coverage metrics you must have one or multiple `coverage.xml` (cobertura xml format) files. 92 | 93 | * First install the tools for converting a coverprofile in cobertura file: 94 | ```shell 95 | go get github.com/axw/gocov/... 96 | go get github.com/AlekSi/gocov-xml 97 | ``` 98 | 99 | * Then from the root of your project: 100 | ```shell 101 | gocov test ./... | gocov-xml > coverage.xml 102 | ``` 103 | 104 | Note that `gocov test ./...` internally calls `go test` with the `-coverprofile` flag for 105 | all folders and subfolders, and assembles the coverprofile accordingly by itself (this is 106 | necessary, as Golang [up to 1.9](https://tip.golang.org/doc/go1.10#test) does not support the 107 | combination `go test ./... -coverprofile=...`). 108 | 109 | If you want to invoke `go test` manually, you need to do this and the conversion for each 110 | package by yourself. For example: 111 | 112 | * For all packages execute those commands: 113 | ```shell 114 | go test -coverprofile=cover.out 115 | gocov convert cover.out | gocov-xml > coverage.xml 116 | ``` 117 | 118 | You then end-up with one coverage file per directory: 119 | ``` 120 | pkg1/coverage.xml 121 | pkg2/coverage.xml 122 | pkg3/coverage.xml 123 | ... 124 | ``` 125 | 126 | 127 | This is an example of script for create all coverage files for all packages in one time. 128 | 129 | 130 | ```bash 131 | for D in `find . -type d` 132 | do 133 | echo $D 134 | if [[ $D == ./.git/* ]]; then 135 | continue 136 | elif [[ $D == .. ]]; then 137 | continue 138 | elif [[ $D == . ]]; then 139 | continue 140 | fi 141 | 142 | cd $D 143 | go test -coverprofile=cover.out 144 | gocov convert cover.out | gocov-xml > coverage.xml 145 | cd .. 146 | done 147 | ``` 148 | or 149 | 150 | ```bash 151 | go list -f '{{if len .TestGoFiles}}"go test -coverprofile={{.Dir}}/cover.out {{.ImportPath}}"{{end}}' ./... | xargs -L 1 sh -c 152 | go list -f '{{if len .TestGoFiles}}"gocov convert {{.Dir}}/cover.out | gocov-xml > {{.Dir}}/coverage.xml"{{end}}' ./... | xargs -L 1 sh -c 153 | ``` 154 | 155 | > Note for docker users: by default, `gocov-xml` uses absolute paths which prevents this plugin to use 156 | > coverage files built on a different file system than the one used to run the plugin. 157 | > A workaround is to use a [patched version of gocov](https://github.com/Centny/gocov-xml.git) which provides 158 | > the `-pwd` option to use relative paths instead of absolute paths. See [#35](https://github.com/uartois/sonar-golang/issues/35) for details. 159 | 160 | # Tests (since release 1.1) 161 | 162 | For test metrics you must generate a junit report file. 163 | 164 | * install the tools: 165 | ```shell 166 | go get -u github.com/jstemmer/go-junit-report 167 | ``` 168 | 169 | * run the tests from the root of your project: 170 | ```shell 171 | go test -v ./... | go-junit-report > test.xml 172 | ``` 173 | -------------------------------------------------------------------------------- /logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/logo.jpeg -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 16 | 4.0.0 17 | fr.univartois 18 | 20 | sonar-golang-plugin 21 | 1.2.11 22 | 23 | Golang 24 | Golang Plugin for SonarQube: Golang, Golint 25 | 26 | University of Artois 27 | http://www.univ-artois.fr/ 28 | 29 | https://github.com/uartois/sonar-golang 30 | 31 | https://github.com/uartois/sonar-golang/issues 32 | 33 | 34 | 35 | GNU LGPL 3.0 36 | https://www.gnu.org/licenses/lgpl-3.0.en.html 37 | manual 38 | 39 | 40 | 41 | 42 | sonar-plugin 43 | 44 | 45 | 1.8 46 | 1.8 47 | https://sonarqube.com 48 | ${maven.compiler.source} 49 | 50 | 51 | 52 | 53 | junit 54 | junit 55 | 4.12 56 | test 57 | 58 | 59 | 60 | org.sonarsource.sonarqube 61 | sonar-plugin-api 62 | 64 | 6.0 65 | 66 | provided 67 | 68 | 69 | 70 | 71 | 72 | org.apache.commons 73 | commons-lang3 74 | 3.5 75 | 76 | 77 | 78 | 79 | 80 | org.mockito 81 | mockito-all 82 | 1.10.19 83 | 84 | 85 | 86 | org.mockito 87 | mockito-core 88 | 2.7.22 89 | 90 | 91 | 92 | org.jbehave 93 | jbehave-core 94 | 4.1 95 | 96 | 97 | 98 | de.codecentric 99 | jbehave-junit-runner 100 | 1.2.0 101 | 102 | 103 | 104 | 105 | org.sonarsource.sslr 106 | sslr-core 107 | 1.21 108 | 109 | 110 | 111 | org.sonarsource.sslr 112 | sslr-toolkit 113 | 1.21 114 | 115 | 116 | 117 | org.sonarsource.sslr 118 | sslr-testing-harness 119 | 1.21 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | org.sonarsource.sonar-packaging-maven-plugin 131 | sonar-packaging-maven-plugin 132 | 1.17 133 | true 134 | 135 | 136 | fr.univartois.sonargo.SonarGoPlugin 137 | Sonarqube Plugin for Golang 138 | 140 | true 141 | 142 | 143 | 144 | 145 | 146 | org.apache.maven.plugins 147 | maven-surefire-plugin 148 | 2.19.1 149 | 150 | true 151 | false 152 | 153 | **/*Test* 154 | 155 | 156 | **/GoGrammarTest.java 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | org.jacoco 168 | jacoco-maven-plugin 169 | 0.7.9 170 | 171 | 172 | 173 | process-test-classes 174 | 175 | prepare-agent 176 | 177 | 178 | ${basedir}/target/jacoco.exec 179 | 180 | 181 | 182 | 183 | 184 | org.jbehave 185 | jbehave-maven-plugin 186 | 187 | 188 | run-stories-as-embeddables 189 | integration-test 190 | 191 | run-stories-as-embeddables 192 | 193 | 194 | test 195 | 196 | **/*Scenarios.java 197 | 198 | true 199 | false 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | org.jacoco 212 | jacoco-maven-plugin 213 | 214 | 215 | 216 | report 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/SonarGoPlugin.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo; 23 | 24 | import org.sonar.api.Plugin; 25 | 26 | import fr.univartois.sonargo.core.language.GoLanguage; 27 | import fr.univartois.sonargo.core.language.GoQualityProfile; 28 | import fr.univartois.sonargo.core.metrics.GoMetricSensor; 29 | import fr.univartois.sonargo.core.rules.GoLintIssueLoaderSensor; 30 | import fr.univartois.sonargo.core.rules.GoLintRulesDefinition; 31 | import fr.univartois.sonargo.core.settings.GoProperties; 32 | import fr.univartois.sonargo.coverage.CoverageSensor; 33 | import fr.univartois.sonargo.gotest.GoTestSensor; 34 | import fr.univartois.sonargo.highlighter.HighlighterSensor; 35 | 36 | /** 37 | * This class is the entry point of the plugin 38 | * 39 | * 40 | * 41 | * @author thibault 42 | * 43 | */ 44 | public class SonarGoPlugin implements Plugin { 45 | 46 | @Override 47 | public void define(Context context) { 48 | context.addExtensions(GoProperties.getProperties()); 49 | context.addExtensions(GoLanguage.class, GoQualityProfile.class); 50 | context.addExtensions(GoLintRulesDefinition.class, GoLintIssueLoaderSensor.class); 51 | context.addExtension(CoverageSensor.class); 52 | context.addExtension(GoTestSensor.class); 53 | context.addExtension(HighlighterSensor.class); 54 | context.addExtension(GoMetricSensor.class); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/Parser.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core; 23 | 24 | import java.io.IOException; 25 | 26 | import javax.xml.parsers.ParserConfigurationException; 27 | 28 | import org.xml.sax.SAXException; 29 | 30 | public interface Parser { 31 | public void parse(String reportPath) throws ParserConfigurationException, SAXException, IOException; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/ProjectExplorer.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.sonar.api.batch.fs.FilePredicates; 7 | import org.sonar.api.batch.fs.FileSystem; 8 | import org.sonar.api.batch.fs.InputFile; 9 | import org.sonar.api.batch.sensor.SensorContext; 10 | 11 | import fr.univartois.sonargo.core.language.GoLanguage; 12 | 13 | public class ProjectExplorer { 14 | 15 | private ProjectExplorer() { 16 | // prevent the instantiation 17 | } 18 | 19 | public static List searchByType(final SensorContext context, final InputFile.Type type) { 20 | FileSystem system = context.fileSystem(); 21 | FilePredicates predicate = system.predicates(); 22 | Iterable iter = system 23 | .inputFiles(predicate.and(predicate.hasLanguage(GoLanguage.KEY), predicate.hasType(type))); 24 | 25 | final List listFiles = new ArrayList<>(); 26 | iter.forEach(listFiles::add); 27 | return listFiles; 28 | } 29 | 30 | public static List searchFileWithTypeMainOrTest(final SensorContext context) { 31 | FilePredicates predicate = context.fileSystem().predicates(); 32 | Iterable iter = context.fileSystem().inputFiles(predicate.and(predicate.hasLanguage(GoLanguage.KEY), 33 | predicate.or(predicate.hasType(InputFile.Type.MAIN), predicate.hasType(InputFile.Type.TEST)))); 34 | 35 | final List listFiles = new ArrayList<>(); 36 | iter.forEach(listFiles::add); 37 | return listFiles; 38 | } 39 | 40 | public static InputFile getByPath(final SensorContext context, final String filePath) { 41 | final FileSystem fileSystem = context.fileSystem(); 42 | final FilePredicates predicates = fileSystem.predicates(); 43 | return fileSystem.inputFile(predicates.hasPath(filePath)); 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/language/GoLanguage.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.language; 23 | 24 | import org.apache.commons.lang3.StringUtils; 25 | import org.sonar.api.resources.AbstractLanguage; 26 | 27 | /** 28 | * This class defines the Golang language 29 | * 30 | * @author thibault 31 | * 32 | */ 33 | public class GoLanguage extends AbstractLanguage { 34 | 35 | public static final String NAME = "GO"; 36 | public static final String KEY = "go"; 37 | 38 | private static final String[] DEFAULT_FILE_SUFFIXES = { "go" }; 39 | 40 | /** 41 | * Create the GoLangage 42 | */ 43 | public GoLanguage() { 44 | super(KEY, NAME); 45 | } 46 | 47 | /** 48 | * {@inheritDoc}} 49 | */ 50 | @Override 51 | public String[] getFileSuffixes() { 52 | return DEFAULT_FILE_SUFFIXES; 53 | } 54 | 55 | /** 56 | * Allows to know if the given file name has a valid suffix 57 | * 58 | * @param filename 59 | * String representing the file name 60 | * @return boolean true if the file name's suffix is known, 61 | * false any other way 62 | */ 63 | public boolean hasValidSuffixes(String filename) { 64 | for (String str : DEFAULT_FILE_SUFFIXES) { 65 | if (StringUtils.lowerCase(filename).endsWith("." + str)) { 66 | return true; 67 | } 68 | } 69 | return false; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/language/GoLexer.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core.language; 2 | 3 | import com.sonar.sslr.api.AstNode; 4 | import com.sonar.sslr.api.TokenType; 5 | import com.sonar.sslr.impl.Lexer; 6 | import com.sonar.sslr.impl.channel.BlackHoleChannel; 7 | import com.sonar.sslr.impl.channel.CommentRegexpChannel; 8 | import com.sonar.sslr.impl.channel.IdentifierAndKeywordChannel; 9 | import com.sonar.sslr.impl.channel.PunctuatorChannel; 10 | import com.sonar.sslr.impl.channel.RegexpChannel; 11 | 12 | public final class GoLexer { 13 | 14 | private static final String DECIMAL_DIGIT = "\\d"; 15 | private static final String DECIMAL_LIT = "[1-9]" + DECIMAL_DIGIT + "*"; 16 | private static final String HEXADECIMAL_LIT = "0(x|X)\\p{XDigit}(\\p{XDigit})*"; 17 | private static final String OCTAL_DIGIT = "[0-7]"; 18 | private static final String OCTAL_LIT = "0" + OCTAL_DIGIT + "*"; 19 | private static final String FLOAT_SEPARATOR = "\\."; 20 | private static final String DECIMALS = DECIMAL_DIGIT + "+"; 21 | private static final String EXPONENT = "[eE][+-]?+" + DECIMALS; 22 | private static final String FLOAT_LIT = "(" + DECIMALS + FLOAT_SEPARATOR + "(" + DECIMALS + ")*(" + EXPONENT 23 | + ")*)|(" + DECIMALS + EXPONENT + ")|(" + FLOAT_SEPARATOR + DECIMALS + "(" + EXPONENT + ")" + "?)"; 24 | 25 | private static final String UNICODE_CHAR = "^\\u000A"; 26 | private static final String NEWLINE = "\\u000A"; 27 | 28 | private static final String INTERPRETED_STRING_LIT = "\"(\\p{L}|\\p{N}|\\p{Z}|\\p{Punct})*\""; 29 | private static final String RAW_STRING_LIT = "`" + UNICODE_CHAR + "|" + NEWLINE + "`"; 30 | private static final String STRING_LIT = RAW_STRING_LIT + "|" + INTERPRETED_STRING_LIT; 31 | 32 | private GoLexer() { 33 | } 34 | 35 | public enum Literals implements TokenType { 36 | 37 | INTEGER(DECIMAL_LIT + "|" + HEXADECIMAL_LIT + "|" + OCTAL_LIT), 38 | FLOAT(FLOAT_LIT), 39 | STRING(STRING_LIT); 40 | private final String regexp; 41 | 42 | private Literals(String regexp) { 43 | this.regexp = regexp; 44 | } 45 | 46 | @Override 47 | public String getName() { 48 | return name(); 49 | } 50 | 51 | @Override 52 | public String getValue() { 53 | return regexp; 54 | } 55 | 56 | @Override 57 | public boolean hasToBeSkippedFromAst(AstNode node) { 58 | return false; 59 | } 60 | 61 | } 62 | 63 | public enum Keyword implements TokenType { 64 | BREAK("break"), 65 | DEFAULT("default"), 66 | FUNC("func"), 67 | INTERFACE("interface"), 68 | SELECT("select"), 69 | CASE("case"), 70 | DEFER("defer"), 71 | GO("go"), 72 | MAP("map"), 73 | STRUCT("struct"), 74 | CHAN("chan"), 75 | ELSE("else"), 76 | GOTO("goto"), 77 | PACKAGE("package"), 78 | SWITCH("switch"), 79 | CONST("const"), 80 | FALLTHROUGH("fallthrough"), 81 | IF("if"), 82 | RANGE("range"), 83 | TYPE("type"), 84 | CONTINUE("continue"), 85 | FOR("for"), 86 | IMPORT("import"), 87 | RETURN("return"), 88 | VAR("var"), 89 | UINT8("uint8"), 90 | UINT16("uint16"), 91 | UINT32("uint32"), 92 | UINT64("uint64"), 93 | INT("int"), 94 | INT8("int8"), 95 | INT16("int16"), 96 | INT32("int32"), 97 | INT64("int64"), 98 | FLOAT32("float32"), 99 | FLOAT64("float64"), 100 | COMPLEX64("complex64"), 101 | COMPLEX128("complex128"), 102 | BYTE("byte"), 103 | RUNE("rune"), 104 | BOOL("bool"), 105 | UINTPTR("uintptr"), 106 | STRING("string"); 107 | 108 | private final String value; 109 | 110 | private Keyword(String value) { 111 | this.value = value; 112 | } 113 | 114 | @Override 115 | public String getName() { 116 | return name(); 117 | } 118 | 119 | @Override 120 | public String getValue() { 121 | return value; 122 | } 123 | 124 | @Override 125 | public boolean hasToBeSkippedFromAst(AstNode arg0) { 126 | return false; 127 | } 128 | 129 | public static String[] keywordValues() { 130 | final Keyword[] keywordsEnum = Keyword.values(); 131 | final String[] keywords = new String[keywordsEnum.length]; 132 | for (int i = 0; i < keywords.length; i++) { 133 | keywords[i] = keywordsEnum[i].getValue(); 134 | } 135 | return keywords; 136 | } 137 | 138 | } 139 | 140 | public static final String COMMENT_SYMBOL = "//"; 141 | 142 | public enum Punctuators implements TokenType { 143 | 144 | PAREN_L("("), 145 | PAREN_R(")"), 146 | BRACE_L("{"), 147 | BRACE_R("}"), 148 | EQ("="), 149 | EQ2(":="), 150 | COMMA(","), 151 | SEMICOLON(";"), 152 | ADD("+"), 153 | SUB("-"), 154 | MUL("*"), 155 | DIV("/"), 156 | EQEQ("=="), 157 | NE("!="), 158 | LT("<"), 159 | LTE("<="), 160 | GT(">"), 161 | GTE(">="), 162 | INC("++"), 163 | DEC("--"), 164 | DOT("."), 165 | OR("||"), 166 | AND("&&"), 167 | PERCENT("%"), 168 | LEFT_SHIFT("<<"), 169 | RIGHT_SHIFT(">>"), 170 | AND_BITBIT("&"), 171 | OR_BITBIT("|"), 172 | AND_NOT_BITBIT("&^"), 173 | XOR("&"), 174 | NOT("!"), 175 | LEFT("<-"), 176 | SQUARE_BRACKET_LEFT("]"), 177 | SQUARE_BRACKET_RIGHT("["), 178 | COLON(":"), 179 | DOT3("..."); 180 | 181 | private final String value; 182 | 183 | private Punctuators(String value) { 184 | this.value = value; 185 | } 186 | 187 | @Override 188 | public String getName() { 189 | return name(); 190 | } 191 | 192 | @Override 193 | public String getValue() { 194 | return value; 195 | } 196 | 197 | @Override 198 | public boolean hasToBeSkippedFromAst(AstNode node) { 199 | return false; 200 | } 201 | 202 | } 203 | 204 | public static Lexer create() { 205 | return Lexer.builder().withFailIfNoChannelToConsumeOneCharacter(false) 206 | .withChannel(new IdentifierAndKeywordChannel("\\p{L}(\\p{L}|\\p{N}|_)*", true, Keyword.values())) 207 | .withChannel(new RegexpChannel(Literals.FLOAT, Literals.FLOAT.regexp)) 208 | .withChannel(new RegexpChannel(Literals.INTEGER, Literals.INTEGER.regexp)) 209 | .withChannel(new RegexpChannel(Literals.STRING, Literals.STRING.regexp)) 210 | .withChannel(new CommentRegexpChannel("^//.*")).withChannel(new PunctuatorChannel(Punctuators.values())) 211 | .withChannel(new BlackHoleChannel("[ \t\r\n]+")).build(); 212 | } 213 | 214 | } 215 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/language/GoParser.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core.language; 2 | 3 | import java.io.File; 4 | 5 | import org.apache.commons.io.FileUtils; 6 | 7 | import com.sonar.sslr.api.AstNode; 8 | import com.sonar.sslr.api.Grammar; 9 | import com.sonar.sslr.impl.Parser; 10 | 11 | public final class GoParser { 12 | 13 | private static final Parser P = GoParser.create(); 14 | 15 | private GoParser() { 16 | } 17 | 18 | public static Parser create() { 19 | return Parser.builder(GoGrammar.create()).withLexer(GoLexer.create()).build(); 20 | } 21 | 22 | public static AstNode parseFile(String filePath) { 23 | final File file = FileUtils.toFile(GoParser.class.getResource(filePath)); 24 | if (file == null || !file.exists()) { 25 | throw new AssertionError("The file \"" + filePath + "\" does not exist."); 26 | } 27 | 28 | return P.parse(file); 29 | } 30 | 31 | public static AstNode parseString(String source) { 32 | return P.parse(source); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/language/GoQualityProfile.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.language; 23 | 24 | import static fr.univartois.sonargo.core.rules.GoLintRulesDefinition.REPO_KEY; 25 | import static fr.univartois.sonargo.core.rules.GoLintRulesDefinition.REPO_NAME; 26 | 27 | import java.io.IOException; 28 | import java.util.Map.Entry; 29 | import java.util.Properties; 30 | 31 | import org.sonar.api.profiles.ProfileDefinition; 32 | import org.sonar.api.profiles.RulesProfile; 33 | import org.sonar.api.rules.Rule; 34 | import org.sonar.api.utils.ValidationMessages; 35 | import org.sonar.api.utils.log.Logger; 36 | import org.sonar.api.utils.log.Loggers; 37 | 38 | import fr.univartois.sonargo.core.rules.GoLintRulesDefinition; 39 | 40 | /** 41 | * The class define all rules that will detect by the sensor, it's not the same 42 | * of {@link GoLintRulesDefinition} 43 | * 44 | * @author thibault 45 | * 46 | */ 47 | public final class GoQualityProfile extends ProfileDefinition { 48 | private static final Logger LOGGER = Loggers.get(GoQualityProfile.class); 49 | public static final String PROFILE_PATH = "/profile.properties"; 50 | 51 | /** 52 | * {@inheritDoc} 53 | */ 54 | @Override 55 | public RulesProfile createProfile(ValidationMessages validation) { 56 | 57 | LOGGER.info("GoMetaLinter Quality profile"); 58 | RulesProfile profile = RulesProfile.create("Golint Rules", GoLanguage.KEY); 59 | profile.setDefaultProfile(Boolean.TRUE); 60 | 61 | Properties prop = new Properties(); 62 | 63 | try { 64 | prop.load(GoQualityProfile.class.getResourceAsStream(GoQualityProfile.PROFILE_PATH)); 65 | 66 | for (Entry e : prop.entrySet()) { 67 | if (Boolean.TRUE.equals(Boolean.valueOf((String) e.getValue()))) { 68 | profile.activateRule(Rule.create(REPO_KEY, (String) e.getKey(), REPO_NAME), null); 69 | } 70 | } 71 | 72 | } catch (IOException e) { 73 | LOGGER.error((new StringBuilder()).append("Unable to load ").append(PROFILE_PATH).toString(), e); 74 | } 75 | 76 | LOGGER.debug((new StringBuilder()).append("Profil generate: ").append(profile.getActiveRules()).toString()); 77 | 78 | return profile; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/metrics/GoLineMetrics.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core.metrics; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.nio.charset.StandardCharsets; 9 | 10 | import org.sonar.api.batch.fs.InputFile; 11 | import org.sonar.api.utils.log.Logger; 12 | import org.sonar.api.utils.log.Loggers; 13 | 14 | public class GoLineMetrics { 15 | private static final Logger LOGGER = Loggers.get(GoLineMetrics.class); 16 | 17 | private int numberLineOfCode = 0; 18 | private int numberLineComment = 0; 19 | private final InputFile file; 20 | 21 | public GoLineMetrics(InputFile f) { 22 | file = f; 23 | } 24 | 25 | public void analyseFile() { 26 | 27 | final File f = file.file(); 28 | 29 | try (final BufferedReader br = new BufferedReader( 30 | new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8))) { 31 | 32 | String line; 33 | while ((line = br.readLine()) != null) { 34 | if (!line.startsWith("//")) { 35 | numberLineOfCode++; 36 | } else { 37 | numberLineComment++; 38 | } 39 | } 40 | } catch (final IOException e) { 41 | LOGGER.error("IO Exception", e); 42 | } 43 | } 44 | 45 | public int getNumberLineOfCode() { 46 | return numberLineOfCode; 47 | } 48 | 49 | public int getNumberLineComment() { 50 | return numberLineComment; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/metrics/GoMetricSensor.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core.metrics; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.stream.Stream; 10 | 11 | import org.sonar.api.batch.fs.FilePredicates; 12 | import org.sonar.api.batch.fs.FileSystem; 13 | import org.sonar.api.batch.fs.InputFile; 14 | import org.sonar.api.batch.fs.InputFile.Type; 15 | import org.sonar.api.batch.sensor.Sensor; 16 | import org.sonar.api.batch.sensor.SensorContext; 17 | import org.sonar.api.batch.sensor.SensorDescriptor; 18 | import org.sonar.api.measures.CoreMetrics; 19 | import org.sonar.api.measures.Metric; 20 | 21 | import fr.univartois.sonargo.core.language.GoLanguage; 22 | 23 | public class GoMetricSensor implements Sensor { 24 | private Map, Integer> measures; 25 | 26 | public GoMetricSensor() { 27 | measures = new HashMap<>(); 28 | } 29 | 30 | public Stream createStream(SensorContext context) throws IOException { 31 | return Files.walk(Paths.get(context.fileSystem().baseDir().getPath())) 32 | .filter(p -> !p.getFileName().toString().endsWith(".go")); 33 | } 34 | 35 | @Override 36 | public void describe(SensorDescriptor descriptor) { 37 | descriptor.name("Go Metrics Sensor"); 38 | 39 | } 40 | 41 | @Override 42 | public void execute(SensorContext context) { 43 | final FileSystem fileSystem = context.fileSystem(); 44 | final FilePredicates predicates = fileSystem.predicates(); 45 | final Iterable files = fileSystem 46 | .inputFiles(predicates.and(predicates.hasLanguage(GoLanguage.KEY), predicates.hasType(Type.MAIN))); 47 | files.forEach(i -> { 48 | final GoLineMetrics goline = new GoLineMetrics(i); 49 | goline.analyseFile(); 50 | saveMetrics(context, i, CoreMetrics.NCLOC, goline.getNumberLineOfCode()); 51 | saveMetrics(context, i, CoreMetrics.COMMENT_LINES, goline.getNumberLineComment()); 52 | }); 53 | } 54 | 55 | public void saveMetrics(SensorContext context, InputFile inputFile, Metric metric, Integer value) { 56 | context.newMeasure().withValue(value).forMetric(metric).on(inputFile).save(); 57 | measures.put(metric, value); 58 | } 59 | 60 | public Map, Integer> getMeasures() { 61 | return measures; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/rules/GoError.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | /** 25 | * GoError Represents an Error from a gometalinter checkstyle report 26 | * 27 | * This is an example of gometalinter checkstyle report This class have a field 28 | * for all attribute of error tag except the attribute "source" {@code 29 | * 30 | 31 | 32 | * 35 | * 37 | * 40 | * 42 | * 44 | * 46 | * 48 | * 50 | * } 51 | * 52 | * @author thibault 53 | */ 54 | public class GoError { 55 | private final int line; 56 | private final String message; 57 | private final String severity; 58 | private final String filePath; 59 | 60 | /** 61 | * Create a GoError 62 | * 63 | * @param line 64 | * The line where there is the problem 65 | * @param message 66 | * The message for the error 67 | * @param severity 68 | * The severity for the message, this is the severity by the 69 | * linter it's not directly the severity of SonarQube 70 | * @param filePath 71 | * The file where there is the error 72 | */ 73 | public GoError(int line, String message, String severity, String filePath) { 74 | super(); 75 | this.line = line; 76 | this.message = message; 77 | this.severity = severity; 78 | this.filePath = filePath; 79 | } 80 | 81 | /** 82 | * Get the line where there is the problem 83 | * 84 | * @return The line attribute 85 | */ 86 | public int getLine() { 87 | return line; 88 | } 89 | 90 | /** 91 | * Get the message where there is the problem 92 | * 93 | * @return The message attribute 94 | */ 95 | public String getMessage() { 96 | return message; 97 | } 98 | 99 | /** 100 | * Get the severity where there is the problem 101 | * 102 | * @return The severity attribute 103 | */ 104 | public String getSeverity() { 105 | return severity; 106 | } 107 | 108 | /** 109 | * Get the filePath of file where there is the problem 110 | * 111 | * @return The filePath attribute 112 | */ 113 | public String getFilePath() { 114 | return filePath; 115 | } 116 | 117 | @Override 118 | public int hashCode() { 119 | final int prime = 31; 120 | int result = 1; 121 | result = prime * result + ((filePath == null) ? 0 : filePath.hashCode()); 122 | result = prime * result + line; 123 | result = prime * result + ((message == null) ? 0 : message.hashCode()); 124 | return prime * result + ((severity == null) ? 0 : severity.hashCode()); 125 | 126 | } 127 | 128 | @Override 129 | public boolean equals(Object obj) { 130 | if (this == obj) 131 | return true; 132 | if (obj == null) 133 | return false; 134 | if (getClass() != obj.getClass()) 135 | return false; 136 | GoError other = (GoError) obj; 137 | if (filePath == null) { 138 | if (other.filePath != null) 139 | return false; 140 | } else if (!filePath.equals(other.filePath)) 141 | return false; 142 | if (line != other.line) 143 | return false; 144 | if (message == null) { 145 | if (other.message != null) 146 | return false; 147 | } else if (!message.equals(other.message)) 148 | return false; 149 | if (severity == null) { 150 | if (other.severity != null) 151 | return false; 152 | } else if (!severity.equals(other.severity)) 153 | return false; 154 | return true; 155 | } 156 | 157 | @Override 158 | public String toString() { 159 | return "GoError [line=" + line + ", message=" + message + ", severity=" + severity + ", filePath=" + filePath 160 | + "]"; 161 | } 162 | 163 | } -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/rules/GoKeyRule.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | import java.io.FileNotFoundException; 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.util.Map.Entry; 28 | import java.util.Properties; 29 | import java.util.regex.Matcher; 30 | import java.util.regex.Pattern; 31 | 32 | import org.sonar.api.utils.log.Logger; 33 | import org.sonar.api.utils.log.Loggers; 34 | 35 | /** 36 | * This class load the file key.properties where there is a map that can 37 | * correspond lint a internal key with a Pattern for match with the message of 38 | * the report 39 | * 40 | * @author thibault 41 | * 42 | */ 43 | public class GoKeyRule { 44 | public static final String PATH_FILE = "/key.properties"; 45 | private static final Logger LOGGER = Loggers.get(GoKeyRule.class); 46 | private static Properties prop; 47 | 48 | private GoKeyRule() { 49 | throw new IllegalAccessError("Utility class"); 50 | } 51 | 52 | /** 53 | * Allow to load the key.properties file where there is a map that can 54 | * correspond lint a internal key with a Pattern for match with the message 55 | * of the report 56 | */ 57 | public static synchronized void init() { 58 | if (prop == null) { 59 | prop = new Properties(); 60 | try { 61 | LOGGER.info("Load " + PATH_FILE); 62 | 63 | InputStream input = GoKeyRule.class.getResourceAsStream(PATH_FILE); 64 | 65 | if (input == null) { 66 | throw new FileNotFoundException(PATH_FILE); 67 | } 68 | 69 | prop.load(input); 70 | 71 | LOGGER.info("loaded " + prop.keySet().size()); 72 | } catch (IOException e) { 73 | LOGGER.error("Unable to load the config file", e); 74 | } 75 | } 76 | } 77 | 78 | public static Properties getProp() { 79 | return prop; 80 | } 81 | 82 | /** 83 | * Allow to get the corresponding key of the message of the error 84 | * 85 | * @param error 86 | * @return 87 | */ 88 | public static String getKeyFromError(GoError error) { 89 | Pattern pattern; 90 | Matcher matcher; 91 | 92 | for (Entry e : prop.entrySet()) { 93 | 94 | pattern = Pattern.compile((String) e.getValue()); 95 | matcher = pattern.matcher(error.getMessage()); 96 | if (!matcher.matches()) 97 | continue; 98 | return (String) e.getKey(); 99 | } 100 | 101 | LOGGER.debug("This description \"" + error.getMessage() + "\" is not usable"); 102 | return null; 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/rules/GoLintRulesDefinition.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | import java.io.InputStream; 25 | import java.nio.charset.StandardCharsets; 26 | 27 | import org.sonar.api.server.rule.RulesDefinition; 28 | import org.sonar.api.server.rule.RulesDefinitionXmlLoader; 29 | import org.sonar.api.utils.log.Logger; 30 | import org.sonar.api.utils.log.Loggers; 31 | 32 | import fr.univartois.sonargo.core.language.GoLanguage; 33 | 34 | /** 35 | * This class read the "/rules/golint-rules.xml" file and create all the rule 36 | * than can detect by the Sensor 37 | * 38 | * @author thibault 39 | * 40 | */ 41 | public class GoLintRulesDefinition implements RulesDefinition { 42 | private static final String PATH_TO_RULES_XML = "/rules/golint-rules.xml"; 43 | private static final Logger LOGGER = Loggers.get(GoLintRulesDefinition.class); 44 | protected static final String KEY = "go"; 45 | protected static final String NAME = "Go"; 46 | 47 | public static final String REPO_KEY = GoLanguage.KEY + "-" + KEY; 48 | public static final String REPO_NAME = GoLanguage.KEY + "-" + NAME; 49 | 50 | protected String rulesDefinitionFilePath() { 51 | return PATH_TO_RULES_XML; 52 | } 53 | 54 | private void defineRulesForLanguage(Context context, String repositoryKey, String repositoryName, 55 | String languageKey) { 56 | NewRepository repository = context.createRepository(repositoryKey, languageKey).setName(repositoryName); 57 | 58 | LOGGER.debug("Repository " + repositoryName + " created with the key " + repositoryKey + " " + repository); 59 | 60 | InputStream rulesXml = this.getClass().getResourceAsStream(rulesDefinitionFilePath()); 61 | if (rulesXml != null) { 62 | RulesDefinitionXmlLoader rulesLoader = new RulesDefinitionXmlLoader(); 63 | rulesLoader.load(repository, rulesXml, StandardCharsets.UTF_8.name()); 64 | } else { 65 | LOGGER.warn("Cannot load the rules file " + PATH_TO_RULES_XML); 66 | } 67 | 68 | repository.done(); 69 | 70 | LOGGER.debug("Repository " + repositoryName + " done: " + repository.rules() + " " + repository.rules().size()); 71 | 72 | } 73 | 74 | @Override 75 | public void define(Context context) { 76 | defineRulesForLanguage(context, REPO_KEY, REPO_NAME, GoLanguage.KEY); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/core/settings/GoProperties.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.settings; 23 | 24 | import static java.util.Arrays.asList; 25 | 26 | import java.util.List; 27 | 28 | import org.sonar.api.config.PropertyDefinition; 29 | 30 | public class GoProperties { 31 | public static final String REPORT_PATH_KEY = "sonar.golint.reportPath"; 32 | public static final String REPORT_PATH_DEFAULT = "report.xml"; 33 | 34 | public static final String COVERAGE_REPORT_PATH_KEY = "sonar.coverage.reportPath"; 35 | public static final String COVERAGE_REPORT_PATH_DEFAULT = "coverage.xml"; 36 | 37 | public static final String JUNIT_REPORT_PATH_KEY = "sonar.test.reportPath"; 38 | public static final String JUNIT_REPORT_PATH_DEFAULT = "test.xml"; 39 | 40 | public static final String DTD_VERIFICATION_KEY = "sonar.coverage.dtdVerification"; 41 | public static final String DTD_VERIFICATION_DEFAULT = "true"; 42 | 43 | public static final String HIGHLIGHTING_KEY = "sonar.highlighting"; 44 | public static final String HIGHLIGHTING_DEFAULT = "true"; 45 | 46 | private GoProperties() { 47 | 48 | } 49 | 50 | public static List getProperties() { 51 | return asList( 52 | PropertyDefinition.builder(REPORT_PATH_KEY).defaultValue(REPORT_PATH_DEFAULT).category("Go") 53 | .name("Report path of Golint").description("relative path for golint report").build(), 54 | PropertyDefinition.builder(COVERAGE_REPORT_PATH_KEY).defaultValue(COVERAGE_REPORT_PATH_DEFAULT) 55 | .category("Go").name("Report path of coverage report") 56 | .description("relative path for coverage report").build(), 57 | PropertyDefinition.builder(JUNIT_REPORT_PATH_KEY).defaultValue(JUNIT_REPORT_PATH_DEFAULT).category("Go") 58 | .name("Report path of JUnit report").description("relative path for JUnit report").build(), 59 | PropertyDefinition.builder(DTD_VERIFICATION_KEY).defaultValue(DTD_VERIFICATION_DEFAULT).category("Go") 60 | .name("Boolean for DTD verification") 61 | .description("false if you want disabled the DTD verification for coverage file").build(), 62 | PropertyDefinition.builder(HIGHLIGHTING_KEY).defaultValue(HIGHLIGHTING_DEFAULT).category("Go") 63 | .name("Boolean for highlighting verification") 64 | .description("false if you want disabled the highlighting").build()); 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/coverage/CoverageParser.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.coverage; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | import java.io.StringReader; 27 | import java.util.ArrayList; 28 | import java.util.HashMap; 29 | import java.util.List; 30 | import java.util.Map; 31 | 32 | import javax.xml.parsers.DocumentBuilder; 33 | import javax.xml.parsers.DocumentBuilderFactory; 34 | import javax.xml.parsers.ParserConfigurationException; 35 | 36 | import org.sonar.api.batch.sensor.SensorContext; 37 | import org.sonar.api.utils.log.Logger; 38 | import org.sonar.api.utils.log.Loggers; 39 | import org.w3c.dom.Document; 40 | import org.w3c.dom.Element; 41 | import org.w3c.dom.Node; 42 | import org.w3c.dom.NodeList; 43 | import org.xml.sax.InputSource; 44 | import org.xml.sax.SAXException; 45 | 46 | import fr.univartois.sonargo.core.Parser; 47 | import fr.univartois.sonargo.core.settings.GoProperties; 48 | 49 | public class CoverageParser implements Parser { 50 | 51 | private final Map> coverageByFile = new HashMap<>(); 52 | private static final String FILE_NAME_ATTR = "filename"; 53 | private static final String LINE_NUMBER_ATTR = "number"; 54 | private static final String HITS_ATTR = "hits"; 55 | private static final String METHOD_TAG = "method"; 56 | private static final String CLASS_TAG = "class"; 57 | private static final String LINE_TAG = "line"; 58 | private static final Logger LOGGER = Loggers.get(CoverageParser.class); 59 | 60 | private final boolean checkDtd; 61 | 62 | public CoverageParser(SensorContext context) { 63 | checkDtd = context.settings().getBoolean(GoProperties.DTD_VERIFICATION_KEY); 64 | } 65 | 66 | private DocumentBuilder constructDocumentBuilder() throws ParserConfigurationException { 67 | final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 68 | 69 | final DocumentBuilder db = dbf.newDocumentBuilder(); 70 | 71 | if (!checkDtd) { 72 | db.setEntityResolver((publicId, systemId) -> { 73 | if (systemId.contains("http://cobertura.sourceforge.net/xml/coverage-03.dtd")) { 74 | return new InputSource(new StringReader("")); 75 | } else { 76 | return null; 77 | } 78 | }); 79 | } 80 | 81 | return db; 82 | } 83 | 84 | /** 85 | * {@link http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work} 86 | * 87 | * @param reportPath 88 | * @throws ParserConfigurationException 89 | * @throws SAXException 90 | * @throws IOException 91 | */ 92 | @Override 93 | public void parse(String reportPath) throws IOException, ParserConfigurationException { 94 | final DocumentBuilder db = constructDocumentBuilder(); 95 | Document doc; 96 | try { 97 | doc = db.parse(new File(reportPath)); 98 | doc.getDocumentElement().normalize(); 99 | 100 | final NodeList classList = doc.getElementsByTagName(CLASS_TAG); 101 | 102 | for (int i = 0; i < classList.getLength(); i++) { 103 | final Node nNode = classList.item(i); 104 | if (nNode.getNodeType() == Node.ELEMENT_NODE) { 105 | 106 | final Element eElement = (Element) nNode; 107 | final String filepath = eElement.getAttribute(FILE_NAME_ATTR); 108 | LOGGER.debug("filepath from coverage file " + filepath); 109 | parseMethodTag(eElement.getElementsByTagName(METHOD_TAG), getListForFile(filepath)); 110 | } 111 | } 112 | 113 | } catch (SAXException e) { 114 | LOGGER.error("A SAX error on file " + reportPath, e); 115 | } 116 | 117 | } 118 | 119 | public Map> getCoveragePerFile() { 120 | for (Map.Entry> entry : coverageByFile.entrySet()) { 121 | String fileName = entry.getKey(); 122 | List list = entry.getValue(); 123 | LOGGER.debug(list.size() + "line coverage for file " + fileName); 124 | } 125 | return coverageByFile; 126 | } 127 | 128 | private List getListForFile(String filepath) { 129 | return coverageByFile.computeIfAbsent(filepath, k -> new ArrayList<>()); 130 | } 131 | 132 | private void parseMethodTag(NodeList methodsList, List listOfCoverage) { 133 | for (int j = 0; j < methodsList.getLength(); j++) { 134 | final Node nNode = methodsList.item(j); 135 | if (nNode.getNodeType() == Node.ELEMENT_NODE) { 136 | final Element eElement = (Element) nNode; 137 | parseLineTag(eElement.getElementsByTagName(LINE_TAG), listOfCoverage); 138 | } 139 | } 140 | } 141 | 142 | private void parseLineTag(NodeList lineList, List listOfCoverage) { 143 | for (int j = 0; j < lineList.getLength(); j++) { 144 | final Node nNode = lineList.item(j); 145 | if (nNode.getNodeType() == Node.ELEMENT_NODE) { 146 | final Element eElement = (Element) nNode; 147 | listOfCoverage.add(new LineCoverage(Integer.parseInt(eElement.getAttribute(LINE_NUMBER_ATTR)), 148 | Integer.parseInt(eElement.getAttribute(HITS_ATTR)))); 149 | } 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/coverage/CoverageSensor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.coverage; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | import java.nio.file.Files; 27 | import java.nio.file.Path; 28 | import java.nio.file.PathMatcher; 29 | import java.nio.file.Paths; 30 | import java.util.ArrayList; 31 | import java.util.Arrays; 32 | import java.util.HashSet; 33 | import java.util.List; 34 | import java.util.Map; 35 | import java.util.Set; 36 | import java.util.stream.Stream; 37 | 38 | import javax.xml.parsers.ParserConfigurationException; 39 | 40 | import org.sonar.api.CoreProperties; 41 | import org.sonar.api.batch.fs.InputFile; 42 | import org.sonar.api.batch.sensor.Sensor; 43 | import org.sonar.api.batch.sensor.SensorContext; 44 | import org.sonar.api.batch.sensor.SensorDescriptor; 45 | import org.sonar.api.batch.sensor.coverage.CoverageType; 46 | import org.sonar.api.batch.sensor.coverage.NewCoverage; 47 | import org.sonar.api.utils.log.Logger; 48 | import org.sonar.api.utils.log.Loggers; 49 | 50 | import fr.univartois.sonargo.core.ProjectExplorer; 51 | import fr.univartois.sonargo.core.language.GoLanguage; 52 | import fr.univartois.sonargo.core.settings.GoProperties; 53 | 54 | public class CoverageSensor implements Sensor { 55 | 56 | private static final Logger LOGGER = Loggers.get(CoverageSensor.class); 57 | private Set inputFileWithCoverage = new HashSet<>(); 58 | 59 | @Override 60 | public void describe(SensorDescriptor descriptor) { 61 | descriptor.name("Go Coverage").onlyOnFileType(InputFile.Type.MAIN).onlyOnLanguage(GoLanguage.KEY); 62 | } 63 | 64 | private List getExcludedPath(SensorContext context) { 65 | 66 | String globalExcludedPath = context.settings().getString(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY); 67 | 68 | if (globalExcludedPath == null) { 69 | return new ArrayList<>(); 70 | } 71 | 72 | return Arrays.asList(globalExcludedPath.split(",")); 73 | } 74 | 75 | public boolean isAnExcludedPath(Path candidatePath, SensorContext context) { 76 | List listExcludedPath = getExcludedPath(context); 77 | 78 | for (String s : listExcludedPath) { 79 | Path pathAbsolute = candidatePath.toAbsolutePath(); 80 | Path pathBase = context.fileSystem().baseDir().toPath(); 81 | Path pathRelative = pathBase.relativize(pathAbsolute); 82 | if (s.contains("*")) { 83 | PathMatcher pathMatcher = java.nio.file.FileSystems.getDefault().getPathMatcher("glob:" + s); 84 | if (pathMatcher.matches(pathRelative)) { 85 | return true; 86 | } 87 | } 88 | 89 | if ((candidatePath.isAbsolute() && candidatePath.endsWith(s)) 90 | || (candidatePath.getFileName().toFile().getName().equals(s))) { 91 | return true; 92 | } 93 | } 94 | return false; 95 | 96 | } 97 | 98 | public Stream createStream(SensorContext context) throws IOException { 99 | final String fullPath = context.fileSystem().baseDir().getPath(); 100 | LOGGER.info(fullPath); 101 | return Files.walk(Paths.get(fullPath)) 102 | .filter(p -> !p.getParent().toString().equals(".git") && !p.getParent().toString().contains(".sonar") 103 | && !p.getParent().toString().contains(".scannerwork") 104 | && !p.getFileName().toString().startsWith(".") && !isAnExcludedPath(p, context)); 105 | 106 | } 107 | 108 | @Override 109 | public void execute(SensorContext context) { 110 | try (Stream paths = createStream(context)) { 111 | paths.forEach(filePath -> { 112 | 113 | LOGGER.debug("Path in stream" + filePath.toFile().getAbsolutePath()); 114 | 115 | if (filePath.toFile().isDirectory()) { 116 | final String reportPath = context.settings().getString(GoProperties.COVERAGE_REPORT_PATH_KEY); 117 | final File f = new File(filePath + File.separator + reportPath); 118 | if (f.exists()) { 119 | LOGGER.info("Analyse for " + f.getPath()); 120 | 121 | final CoverageParser coverParser = new CoverageParser(context); 122 | 123 | try { 124 | coverParser.parse(f.getPath()); 125 | save(context, coverParser.getCoveragePerFile()); 126 | } catch (ParserConfigurationException | IOException e) { 127 | LOGGER.error("Exception: ", e); 128 | } 129 | 130 | } else { 131 | LOGGER.info("no coverage file in package " + f.getPath()); 132 | } 133 | } 134 | }); 135 | 136 | ProjectExplorer.searchByType(context, InputFile.Type.MAIN).stream() 137 | .filter(i -> !inputFileWithCoverage.contains(i)).forEach(i -> saveForAllLine(context, i)); 138 | 139 | } catch (final IOException e) { 140 | LOGGER.error("IO Exception " + context.fileSystem().baseDir().getPath()); 141 | } 142 | } 143 | 144 | public void saveForAllLine(final SensorContext context, final InputFile i) { 145 | final NewCoverage coverage = context.newCoverage().onFile(i); 146 | try (Stream fileLine = Files.lines(i.path())) { 147 | FactoryLine.init(); 148 | LinePredicate.init(); 149 | fileLine.map(FactoryLine::create).filter(LinePredicate::filterLine) 150 | .forEach(l -> coverage.lineHits(l.getLineNumber(), l.getHits())); 151 | 152 | coverage.ofType(CoverageType.UNIT); 153 | coverage.save(); 154 | } catch (IOException e) { 155 | LOGGER.warn("IO Exception" + e); 156 | } 157 | 158 | } 159 | 160 | public void save(SensorContext context, Map> coveragePerFile) { 161 | for (Map.Entry> entry : coveragePerFile.entrySet()) { 162 | final String filePath = entry.getKey(); 163 | final List lines = entry.getValue(); 164 | final InputFile inputFile = ProjectExplorer.getByPath(context, filePath); 165 | inputFileWithCoverage.add(inputFile); 166 | if (inputFile == null) { 167 | LOGGER.warn("unable to create InputFile object: " + filePath); 168 | return; 169 | } 170 | 171 | final NewCoverage coverage = context.newCoverage().onFile(inputFile); 172 | 173 | for (final LineCoverage line : lines) { 174 | try { 175 | coverage.lineHits(line.getLineNumber(), line.getHits()); 176 | } catch (final Exception ex) { 177 | LOGGER.error(ex.getMessage() + line); 178 | } 179 | } 180 | coverage.ofType(CoverageType.UNIT); 181 | coverage.save(); 182 | } 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/coverage/FactoryLine.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.coverage; 2 | 3 | public class FactoryLine { 4 | private static int line = 1; 5 | 6 | private FactoryLine() { 7 | throw new IllegalStateException("Utility class"); 8 | } 9 | 10 | public static void init() { 11 | line = 1; 12 | } 13 | 14 | public static LineCoverage create(String l) { 15 | return new LineCoverage(line++, 0, l); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/coverage/LineCoverage.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.coverage; 23 | 24 | public class LineCoverage { 25 | private int lineNumber; 26 | private int hits; 27 | private String line; 28 | 29 | public LineCoverage(int lineNumber, int hits) { 30 | super(); 31 | this.lineNumber = lineNumber; 32 | this.hits = hits; 33 | this.line = null; 34 | } 35 | 36 | public LineCoverage(int lineNumber, int hits, String line) { 37 | this(lineNumber, hits); 38 | this.line = line; 39 | } 40 | 41 | public int getLineNumber() { 42 | return lineNumber; 43 | } 44 | 45 | public int getHits() { 46 | return hits; 47 | } 48 | 49 | public String getLine() { 50 | return line; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "LineCoverage [lineNumber=" + lineNumber + ", hits=" + hits + "]"; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/coverage/LinePredicate.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.coverage; 2 | 3 | public class LinePredicate { 4 | private static boolean funcFound = false; 5 | private static boolean commentFound = false; 6 | private static boolean typeFound = false; 7 | 8 | private LinePredicate() { 9 | throw new IllegalStateException("Utility class"); 10 | } 11 | 12 | public static void init() { 13 | funcFound = false; 14 | commentFound = false; 15 | typeFound = false; 16 | } 17 | 18 | public static boolean filterLine(LineCoverage l) { 19 | String s = l.getLine().trim(); 20 | if (s.matches("^func.*")) { 21 | funcFound = true; 22 | return false; 23 | } 24 | if (s.matches("^//.*")) { 25 | return false; 26 | } 27 | 28 | if (s.matches("^/\\*.*")) { 29 | commentFound = true; 30 | return false; 31 | } 32 | 33 | if (s.matches("^\\*/.*")) { 34 | commentFound = false; 35 | return false; 36 | } 37 | 38 | if (s.matches("^type.*") || s.matches("^interface.*") || s.matches("^struct.*")) { 39 | typeFound = true; 40 | return false; 41 | } 42 | 43 | if (s.matches("}.*") && typeFound) { 44 | typeFound = true; 45 | return false; 46 | } 47 | 48 | return funcFound && !commentFound && !typeFound && !s.isEmpty() && !"}".equals(s) && !s.matches("^type.*") 49 | && !s.matches("^func.*") && !s.matches("^import.*") && !s.matches("^package.*"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/gotest/FunctionFinder.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.gotest; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.nio.ByteBuffer; 6 | import java.nio.CharBuffer; 7 | import java.nio.channels.FileChannel; 8 | import java.nio.charset.Charset; 9 | import java.nio.file.Path; 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.regex.Matcher; 15 | import java.util.regex.Pattern; 16 | 17 | import org.sonar.api.batch.fs.InputFile; 18 | import org.sonar.api.batch.sensor.SensorContext; 19 | import org.sonar.api.utils.log.Logger; 20 | import org.sonar.api.utils.log.Loggers; 21 | 22 | import fr.univartois.sonargo.core.ProjectExplorer; 23 | 24 | public class FunctionFinder { 25 | private static final Logger LOGGER = Loggers.get(FunctionFinder.class); 26 | 27 | private HashMap result = new HashMap<>(); 28 | private String baseDir; 29 | private List paths; 30 | 31 | private static final Pattern MATCH_FUNC_NAME = Pattern.compile( 32 | "func\\s+(\\(suite\\s+[a-zA-Z0-9\\*\\._-]*\\)\\s+)?(?Test[^\\s]+)\\s*\\([a-zA-Z0-9\\*\\s\\.\\,_-]*\\)\\s*\\{"); 33 | 34 | public FunctionFinder(SensorContext context) { 35 | this.baseDir = context.fileSystem().baseDir().getPath(); 36 | 37 | LOGGER.info("base dir " + baseDir); 38 | 39 | paths = new ArrayList<>(); 40 | ProjectExplorer.searchByType(context, InputFile.Type.TEST).forEach(i -> paths.add(i.file().toPath())); 41 | 42 | } 43 | 44 | public Map searchFunction() { 45 | 46 | paths.forEach(p -> { 47 | LOGGER.info("search test function in " + p.toFile().getAbsolutePath()); 48 | searchFunctionInFile(p); 49 | }); 50 | LOGGER.debug(result.toString()); 51 | return result; 52 | } 53 | 54 | private CharBuffer getFileAsBufferFromPath(Path p) { 55 | try (FileInputStream input = new FileInputStream(p.toString())) { 56 | FileChannel channel = input.getChannel(); 57 | ByteBuffer bbuf = channel.map(FileChannel.MapMode.READ_ONLY, 0, (int) channel.size()); 58 | return Charset.forName("utf8").newDecoder().decode(bbuf); 59 | } catch (IOException e) { 60 | LOGGER.warn("IO Exception caught -", e); 61 | } 62 | return null; 63 | } 64 | 65 | public void searchFunctionInFile(Path p) { 66 | String absolutePath = p.toFile().getAbsolutePath(); 67 | Matcher matcher = MATCH_FUNC_NAME.matcher(getFileAsBufferFromPath(p)); 68 | while (matcher.find()) { 69 | String func = matcher.group("functionName"); 70 | LOGGER.debug("Found function " + func + " at path " + absolutePath); 71 | if (func != null && absolutePath != null) { 72 | result.put(func, absolutePath); 73 | } 74 | } 75 | } 76 | 77 | public Map getResult() { 78 | return result; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/gotest/GoJunitParser.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.gotest; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | import java.util.ArrayList; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | import javax.xml.parsers.DocumentBuilder; 32 | import javax.xml.parsers.DocumentBuilderFactory; 33 | import javax.xml.parsers.ParserConfigurationException; 34 | 35 | import org.sonar.api.utils.log.Logger; 36 | import org.sonar.api.utils.log.Loggers; 37 | import org.w3c.dom.Document; 38 | import org.w3c.dom.Element; 39 | import org.w3c.dom.Node; 40 | import org.w3c.dom.NodeList; 41 | import org.xml.sax.SAXException; 42 | 43 | import fr.univartois.sonargo.core.Parser; 44 | 45 | public class GoJunitParser implements Parser { 46 | private static final String TEST_SUITE_TAG = "testsuite"; 47 | private static final String TEST_SKIPPED_TAG = "skipped"; 48 | private static final String NAME_TEST_ATTR = "name"; 49 | private static final String TIME_TEST_ATTR = "time"; 50 | private static final String FAILURE_TAG = "failure"; 51 | private static final String TEST_CASE_TAG = "testcase"; 52 | 53 | private static final Logger LOGGER = Loggers.get(GoJunitParser.class); 54 | 55 | private final List> listTestSuiteByPackage = new ArrayList<>(); 56 | 57 | private Map functionFileName; 58 | 59 | public GoJunitParser(Map functionFileName) { 60 | this.functionFileName = functionFileName; 61 | } 62 | 63 | @Override 64 | public void parse(String reportPath) throws ParserConfigurationException, SAXException, IOException { 65 | listTestSuiteByPackage.clear(); 66 | final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 67 | final DocumentBuilder db = dbf.newDocumentBuilder(); 68 | final Document doc = db.parse(new File(reportPath)); 69 | 70 | doc.getDocumentElement().normalize(); 71 | 72 | final NodeList testSuiteList = doc.getElementsByTagName(TEST_SUITE_TAG); 73 | for (int i = 0; i < testSuiteList.getLength(); i++) { 74 | final Node nNode = testSuiteList.item(i); 75 | if (nNode.getNodeType() == Node.ELEMENT_NODE) { 76 | final Element eElement = (Element) nNode; 77 | 78 | listTestSuiteByPackage.add(groupTestCaseByFile(eElement)); 79 | } 80 | } 81 | 82 | } 83 | 84 | private HashMap groupTestCaseByFile(Element testSuite) { 85 | final NodeList testCaseList = testSuite.getElementsByTagName(TEST_CASE_TAG); 86 | HashMap mapResult = new HashMap<>(); 87 | for (int i = 0; i < testCaseList.getLength(); i++) { 88 | final Node nNode = testCaseList.item(i); 89 | if (nNode.getNodeType() == Node.ELEMENT_NODE) { 90 | final Element testCase = (Element) nNode; 91 | String functionName = testCase.getAttribute(NAME_TEST_ATTR); 92 | String fileName = functionFileName.get(functionName); 93 | GoTestFile goTest = null; 94 | if (mapResult.containsKey(fileName)) { 95 | goTest = mapResult.get(fileName); 96 | } else if (fileName != null) { 97 | goTest = new GoTestFile(); 98 | goTest.setFile(fileName); 99 | } else { 100 | LOGGER.warn("The key is null"); 101 | continue; 102 | } 103 | 104 | goTest.addTestCase(new GoTestCase(testCase.getElementsByTagName(FAILURE_TAG).getLength() > 0, 105 | testCase.getElementsByTagName(TEST_SKIPPED_TAG).getLength() > 0, 106 | Double.parseDouble(testCase.getAttribute(TIME_TEST_ATTR)))); 107 | mapResult.put(fileName, goTest); 108 | } 109 | 110 | } 111 | return mapResult; 112 | 113 | } 114 | 115 | public List> getListTestSuite() { 116 | return listTestSuiteByPackage; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/gotest/GoTestCase.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.gotest; 23 | 24 | public class GoTestCase { 25 | private boolean fail; 26 | private boolean skipped; 27 | private Double time; 28 | 29 | public GoTestCase(boolean fail, boolean skipped, Double time) { 30 | super(); 31 | this.fail = fail; 32 | this.skipped = skipped; 33 | this.time = time; 34 | } 35 | 36 | public boolean isFail() { 37 | return fail; 38 | } 39 | 40 | public void setFail(boolean fail) { 41 | this.fail = fail; 42 | } 43 | 44 | public boolean isSkipped() { 45 | return skipped; 46 | } 47 | 48 | public void setSkipped(boolean skipped) { 49 | this.skipped = skipped; 50 | } 51 | 52 | public Double getTime() { 53 | return time; 54 | } 55 | 56 | public void setTime(Double time) { 57 | this.time = time; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/gotest/GoTestFile.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.gotest; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class GoTestFile { 6 | private ArrayList list; 7 | private String file; 8 | 9 | public GoTestFile() { 10 | super(); 11 | list = new ArrayList<>(); 12 | } 13 | 14 | public int getNbTotalTest() { 15 | return list.size(); 16 | } 17 | 18 | public void addTestCase(GoTestCase t) { 19 | list.add(t); 20 | } 21 | 22 | public int getNbFailureTest() { 23 | int nbFailure = 0; 24 | for (GoTestCase tc : list) { 25 | if (tc.isFail()) 26 | nbFailure++; 27 | } 28 | return nbFailure; 29 | } 30 | 31 | public int getSkipped() { 32 | int nbSkipped = 0; 33 | for (GoTestCase tc : list) { 34 | if (tc.isSkipped()) 35 | nbSkipped++; 36 | } 37 | return nbSkipped; 38 | } 39 | 40 | public String getFile() { 41 | return file; 42 | } 43 | 44 | public void setFile(String file) { 45 | this.file = file; 46 | } 47 | 48 | public long getTime() { 49 | double time = 0.0; 50 | for (GoTestCase tc : list) { 51 | time += tc.getTime(); 52 | } 53 | return (long) (time * 1000); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/gotest/GoTestReportSaver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.gotest; 23 | 24 | import java.io.Serializable; 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | import org.sonar.api.batch.fs.FilePredicates; 29 | import org.sonar.api.batch.fs.InputFile; 30 | import org.sonar.api.batch.sensor.SensorContext; 31 | import org.sonar.api.measures.CoreMetrics; 32 | import org.sonar.api.measures.Metric; 33 | import org.sonar.api.utils.log.Logger; 34 | import org.sonar.api.utils.log.Loggers; 35 | 36 | public class GoTestReportSaver { 37 | private static final Logger LOGGER = Loggers.get(GoTestReportSaver.class); 38 | 39 | private GoTestReportSaver() { 40 | throw new IllegalStateException("Utility class"); 41 | } 42 | 43 | public static void save(SensorContext context, List> list) { 44 | FilePredicates predicates = context.fileSystem().predicates(); 45 | for (Map map : list) { 46 | for (Map.Entry entry : map.entrySet()) { 47 | String key = entry.getKey(); 48 | GoTestFile value = entry.getValue(); 49 | if (value == null) { 50 | LOGGER.warn("Value for " + key + " is null"); 51 | continue; 52 | } 53 | if (value.getFile() == null) { 54 | LOGGER.debug("saving measures for file " + value.getFile()); 55 | LOGGER.warn("No file could be determined from " + value.getFile()); 56 | continue; 57 | } 58 | InputFile file = context.fileSystem().inputFile(predicates.hasAbsolutePath(value.getFile())); 59 | if (file == null) { 60 | LOGGER.warn("File not found " + value.getFile()); 61 | continue; 62 | } 63 | try { 64 | saveMeasure(value, context, file); 65 | } catch (Exception e) { // yes, I know this is naughty... 66 | LOGGER.warn(e.getMessage()); 67 | } 68 | } 69 | } 70 | 71 | } 72 | 73 | private static void saveMeasure(GoTestFile t, SensorContext context, InputFile file) { 74 | saveMeasure(context, file, CoreMetrics.SKIPPED_TESTS, t.getSkipped()); 75 | saveMeasure(context, file, CoreMetrics.TESTS, t.getNbTotalTest()); 76 | saveMeasure(context, file, CoreMetrics.TEST_FAILURES, t.getNbFailureTest()); 77 | saveMeasure(context, file, CoreMetrics.TEST_EXECUTION_TIME, t.getTime()); 78 | } 79 | 80 | private static void saveMeasure(SensorContext context, InputFile inputFile, 81 | Metric metric, T value) { 82 | LOGGER.warn(inputFile.absolutePath()); 83 | LOGGER.warn(metric.toString()); 84 | context.newMeasure().forMetric(metric).on(inputFile).withValue(value).save(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/gotest/GoTestSensor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.gotest; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | import java.util.Map; 27 | 28 | import javax.xml.parsers.ParserConfigurationException; 29 | 30 | import org.sonar.api.batch.sensor.Sensor; 31 | import org.sonar.api.batch.sensor.SensorContext; 32 | import org.sonar.api.batch.sensor.SensorDescriptor; 33 | import org.sonar.api.utils.log.Logger; 34 | import org.sonar.api.utils.log.Loggers; 35 | import org.xml.sax.SAXException; 36 | 37 | import fr.univartois.sonargo.core.language.GoLanguage; 38 | import fr.univartois.sonargo.core.settings.GoProperties; 39 | 40 | public class GoTestSensor implements Sensor { 41 | private static final Logger LOGGER = Loggers.get(GoTestSensor.class); 42 | 43 | @Override 44 | public void describe(SensorDescriptor descriptor) { 45 | descriptor.onlyOnLanguage(GoLanguage.KEY).name("Go test JUnit loader sensor"); 46 | 47 | } 48 | 49 | @Override 50 | public void execute(SensorContext context) { 51 | String reportPath = context.settings().getString(GoProperties.JUNIT_REPORT_PATH_KEY); 52 | 53 | if (reportPath == null || !(new File(reportPath)).exists()) { 54 | LOGGER.info("no junit report"); 55 | return; 56 | } 57 | FunctionFinder ff; 58 | try { 59 | ff = new FunctionFinder(context); 60 | 61 | Map nameFunction = ff.searchFunction(); 62 | 63 | LOGGER.debug(nameFunction.toString()); 64 | 65 | GoJunitParser junitParser = new GoJunitParser(nameFunction); 66 | 67 | junitParser.parse(reportPath); 68 | 69 | GoTestReportSaver.save(context, junitParser.getListTestSuite()); 70 | 71 | } catch (ParserConfigurationException | SAXException | IOException e) { 72 | LOGGER.error("Parse exception ", e); 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/highlighter/Colorizer.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.highlighter; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.nio.charset.StandardCharsets; 9 | 10 | import org.sonar.api.batch.fs.InputFile; 11 | import org.sonar.api.batch.sensor.SensorContext; 12 | import org.sonar.api.batch.sensor.highlighting.NewHighlighting; 13 | import org.sonar.api.batch.sensor.highlighting.TypeOfText; 14 | import org.sonar.api.utils.log.Logger; 15 | import org.sonar.api.utils.log.Loggers; 16 | 17 | import fr.univartois.sonargo.core.language.GoLexer; 18 | 19 | public class Colorizer { 20 | 21 | private static final Logger LOGGER = Loggers.get(Colorizer.class); 22 | private final NewHighlighting highlighting; 23 | 24 | public Colorizer(SensorContext context) { 25 | super(); 26 | 27 | highlighting = context.newHighlighting(); 28 | } 29 | 30 | public void colorize(InputFile i) { 31 | final File f = i.file(); 32 | LOGGER.debug("Coloring the file: " + f.getPath()); 33 | highlighting.onFile(i); 34 | try (final BufferedReader br = new BufferedReader( 35 | new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8))) { 36 | 37 | String line; 38 | int lineNumber = 1; 39 | while ((line = br.readLine()) != null) { 40 | searchAndColor(line, lineNumber); 41 | lineNumber++; 42 | } 43 | } catch (final IOException e) { 44 | LOGGER.error("IO Exception", e); 45 | } 46 | try { 47 | highlighting.save(); 48 | } catch (Exception ex) { 49 | LOGGER.error("Highlighting problem on save", ex.getMessage()); 50 | } 51 | 52 | } 53 | 54 | private boolean haveString(String s) { 55 | return s.chars().filter(i -> i == '"').count() > 0; 56 | } 57 | 58 | private void highlightingComment(int lineNumber, int end) { 59 | highlighting.highlight(lineNumber, 0, lineNumber, end, TypeOfText.COMMENT); 60 | 61 | } 62 | 63 | private int searchNextOccurrenceOfDoubleQuote(String line, int start) { 64 | int index = line.indexOf('"', start); 65 | LOGGER.debug(line + " " + index); 66 | while (index > 0 && line.charAt(index - 1) == '\\') { 67 | index = line.indexOf('"', index + 1); 68 | LOGGER.debug(line + " " + index); 69 | } 70 | return index; 71 | } 72 | 73 | private void highlightingStringInLine(String line, int lineNumber) { 74 | if (!haveString(line)) { 75 | return; 76 | } 77 | int start = 0; 78 | int index = searchNextOccurrenceOfDoubleQuote(line, start); 79 | int indexEnd = searchNextOccurrenceOfDoubleQuote(line, index + 1); 80 | 81 | int lastIndex = 0; 82 | int lastIndexEnd = 0; 83 | 84 | while (index != -1 && indexEnd != -1 && lastIndex != index && lastIndexEnd != indexEnd) { 85 | LOGGER.debug("index " + index + " indexEnd " + indexEnd); 86 | try { 87 | highlighting.highlight(lineNumber, index, lineNumber, indexEnd + 1, TypeOfText.STRING); 88 | } catch (Exception ex) { 89 | LOGGER.error("String highlighting problem", ex); 90 | } 91 | start = indexEnd + 1; 92 | lastIndex = index; 93 | lastIndexEnd = indexEnd; 94 | index = searchNextOccurrenceOfDoubleQuote(line, start); 95 | indexEnd = searchNextOccurrenceOfDoubleQuote(line, index + 1); 96 | } 97 | 98 | } 99 | 100 | private boolean isAString(String line, int index) { 101 | return line.substring(0, index).chars().filter(i -> i == '"').count() % 2 != 0; 102 | 103 | } 104 | 105 | private void highlightingKeyWord(String line, int lineNumber) { 106 | for (final GoLexer.Keyword k : GoLexer.Keyword.values()) { 107 | final String key = k.getValue(); 108 | int index = 0; 109 | while ((index = line.indexOf(key, index)) != -1 && !isAString(line, index)) { 110 | 111 | LOGGER.debug("Line number " + lineNumber + " index start: " + index + " index end: " 112 | + (index + key.length())); 113 | try { 114 | highlighting.highlight(lineNumber, index, lineNumber, index + key.length(), TypeOfText.KEYWORD); 115 | } catch (Exception ex) { 116 | LOGGER.error("Keyword highlighting problem", ex); 117 | } 118 | index = index + key.length(); 119 | } 120 | } 121 | } 122 | 123 | private void searchAndColor(String s, int lineNumber) { 124 | if (s.trim().startsWith(GoLexer.COMMENT_SYMBOL)) { 125 | highlightingComment(lineNumber, s.length()); 126 | } else { 127 | highlightingStringInLine(s, lineNumber); 128 | highlightingKeyWord(s, lineNumber); 129 | } 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/highlighter/HighlighterSensor.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.highlighter; 2 | 3 | import java.util.List; 4 | 5 | import org.sonar.api.batch.fs.InputFile; 6 | import org.sonar.api.batch.sensor.Sensor; 7 | import org.sonar.api.batch.sensor.SensorContext; 8 | import org.sonar.api.batch.sensor.SensorDescriptor; 9 | import org.sonar.api.utils.log.Logger; 10 | import org.sonar.api.utils.log.Loggers; 11 | 12 | import fr.univartois.sonargo.core.ProjectExplorer; 13 | import fr.univartois.sonargo.core.settings.GoProperties; 14 | 15 | public class HighlighterSensor implements Sensor { 16 | private static final Logger LOGGER = Loggers.get(HighlighterSensor.class); 17 | 18 | @Override 19 | public void describe(SensorDescriptor descriptor) { 20 | descriptor.name("Go Highlighter Sensor"); 21 | 22 | } 23 | 24 | @Override 25 | public void execute(SensorContext context) { 26 | 27 | if (!context.settings().getBoolean(GoProperties.HIGHLIGHTING_KEY)) { 28 | LOGGER.info("highlighting disabled"); 29 | return; 30 | } 31 | 32 | final List listFiles = ProjectExplorer.searchFileWithTypeMainOrTest(context); 33 | listFiles.forEach(i -> new Colorizer(context).colorize(i)); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/toolkit/GoColorizer.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.toolkit; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.sonar.colorizer.CDocTokenizer; 7 | import org.sonar.colorizer.CppDocTokenizer; 8 | import org.sonar.colorizer.KeywordsTokenizer; 9 | import org.sonar.colorizer.Tokenizer; 10 | 11 | import fr.univartois.sonargo.core.language.GoLexer; 12 | 13 | public final class GoColorizer { 14 | 15 | private GoColorizer() { 16 | } 17 | 18 | public static List getTokenizers() { 19 | return Arrays.asList(new CDocTokenizer("", ""), 20 | new CppDocTokenizer("", ""), 21 | new KeywordsTokenizer("", "", GoLexer.Keyword.keywordValues())); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/fr/univartois/sonargo/toolkit/GoToolkit.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.toolkit; 2 | 3 | import java.nio.charset.Charset; 4 | import java.nio.charset.IllegalCharsetNameException; 5 | import java.nio.charset.UnsupportedCharsetException; 6 | import java.util.List; 7 | 8 | import org.sonar.api.internal.google.common.collect.ImmutableList; 9 | import org.sonar.colorizer.Tokenizer; 10 | import org.sonar.sslr.toolkit.AbstractConfigurationModel; 11 | import org.sonar.sslr.toolkit.ConfigurationProperty; 12 | import org.sonar.sslr.toolkit.Toolkit; 13 | 14 | import com.sonar.sslr.api.Grammar; 15 | import com.sonar.sslr.impl.Parser; 16 | 17 | import fr.univartois.sonargo.core.language.GoParser; 18 | 19 | public final class GoToolkit { 20 | 21 | private GoToolkit() { 22 | } 23 | 24 | public static void main(String[] args) { 25 | final Toolkit toolkit = new Toolkit("SonarSource : Go : Toolkit", new GoConfigurationModel()); 26 | toolkit.run(); 27 | } 28 | 29 | static class GoConfigurationModel extends AbstractConfigurationModel { 30 | 31 | private final ConfigurationProperty charsetProperty = new ConfigurationProperty("Charset", 32 | "Charset used when opening files.", "UTF-8", newValueCandidate -> { 33 | try { 34 | Charset.forName(newValueCandidate); 35 | return ""; 36 | } catch (final IllegalCharsetNameException e1) { 37 | return "Illegal charset name: " + newValueCandidate; 38 | } catch (final UnsupportedCharsetException e2) { 39 | return "Unsupported charset: " + newValueCandidate; 40 | } 41 | }); 42 | 43 | @Override 44 | public List getProperties() { 45 | return ImmutableList.of(charsetProperty); 46 | } 47 | 48 | @Override 49 | public Charset getCharset() { 50 | return Charset.forName(charsetProperty.getValue()); 51 | } 52 | 53 | @Override 54 | public Parser doGetParser() { 55 | updateConfiguration(); 56 | return GoParser.create(); 57 | } 58 | 59 | @Override 60 | public List doGetTokenizers() { 61 | updateConfiguration(); 62 | return GoColorizer.getTokenizers(); 63 | } 64 | 65 | private static void updateConfiguration() { 66 | /* Construct a parser configuration object from the properties */ 67 | } 68 | 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /src/main/resources/key.properties: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2017 - Université d'Artois 3 | # 4 | # This file is part of SonarQube Golang plugin (sonar-golang). 5 | # 6 | # Sonar-golang is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Sonar-golang is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with Sonar-golang. If not, see . 18 | # 19 | # Contributors: 20 | # Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | ############################################################################### 22 | #golint\:ExportedType=exported type [a-zA-Z0-9]+ should have comment or be unexported 23 | golint\:FormComment=comment on exported [a-zA-Z0-9]+ [a-zA-Z0-9\.]+ should be of the form "[a-zA-Z\.]+ *\t*..." 24 | golint\:AllCaps=don't use ALL_CAPS in Go names; use CamelCase 25 | golint\:UnderscoreInPackageName=don't use an underscore in package name 26 | golint\:LeadingK=don't use leading k in Go names; [a-zA-Z0-9]+ [a-zA-Z0-9]+ should be [a-zA-Z0-9]+ 27 | golint\:UnderscoreInGoName=don't use underscores in Go names; [a-zA-Z0-9]+ [a-zA-Z0-9_]+ should be [a-zA-Z0-9]+ 28 | golint\:ErrorLastReturn=error should be the last type when returning multiple items 29 | golint\:ErrorEndString=error strings should not be capitalized or end with punctuation or a newline 30 | golint\:ErrorVarName=error var [a-zA-Z0-9]+ should have name of the form [a-zA-Z0-9]+ 31 | golint\:AnnoyingUseExportedType=exported [a-zA-Z0-9]+ [a-zA-Z0-9]+ returns unexported type [a-zA-Z0-9]+, which can be annoying to use 32 | golint\:IfBlockReturn=if block ends with a return statement, so drop this else and outdent its block 33 | golint\:PackageCommentForm=package comment should be of the form \"[a-zA-Z0-9]+...\" 34 | golint\:PackageCommentSpace=package comment should not have leading space 35 | golint\:ReceiverNameConsistent=receiver name [a-zA-Z0-9]+ should be consistent with previous receiver name [a-zA-Z0-9]+ for [a-zA-Z0-9]+ 36 | golint\:ReceiverNameReflection=receiver name should be a reflection of its identity; don't use generic names such as \"this\" or \"self\" 37 | golint\:ReceiverNameNotUnderscore=receiver name should not be an underscore 38 | golint\:DropAssignment=should drop = [a-zA-Z0-9]+ from declaration of var [a-zA-Z0-9]+; it is the zero value 39 | golint\:HavePackageComment=should have a package comment, unless it's in another file for this package 40 | golint\:NotUseBasicType=should not use basic type [a-zA-Z0-9]+ as key in context.WithValue 41 | golint\:NotUseDotImport=should not use dot imports 42 | golint\:Omit2ndValueFromRange=should omit 2nd value from range; this loop is equivalent to `for [a-zA-Z0-9]+ := range ...` 43 | golint\:OmitType=should omit type [a-zA-Z0-9]+ from declaration of var [a-zA-Z0-9]+; it will be inferred from the right-hand side 44 | golint\:ReplaceLintIncDec=should replace [a-zA-Z0-9\-\+=]+ with [a-zA-Z0-9\-\+]+ 45 | golint\:ReplaceSprintf=should replace [a-zA-Z0-9\.]+\\(fmt.Sprintf\\(...\\)\\) with [a-zA-Z0-9]+.Errorf\\(...\\) 46 | golint\:Initialisms=[a-zA-Z0-9]+ [a-zA-Z0-9]+ should be [a-zA-Z0-9]+ 47 | golint\:PackageNames=[a-zA-Z0-9]+ name will be used as [a-zA-Z0-9]+.[a-zA-Z0-9]+ by other packages, and that stutters; consider calling this [a-zA-Z0-9]+ 48 | golint\:BlankImport=a blank import should be only in a main or test package, or have a comment justifying it 49 | golint\:CommentExportedType=comment on exported type [a-zA-Z0-9]+ should be of the form "[a-zA-Z0-9]+ ..." \\(with optional leading article\\) 50 | golint\:ContextContextFirstArg=context.Context should be the first parameter of a function 51 | golint\:ExportedHaveComment=exported [a-zA-Z0-9]+ [a-zA-Z0-9\.]+ should have comment or be unexported 52 | golint\:ExportedHaveComment2=exported [a-zA-Z0-9\.]+ [a-zA-Z0-9\.]+ should have comment[\(\) a-zA-Z0-9]+ or be unexported 53 | golint\:ExportedDeclaration=exported [a-zA-Z0-9]+ [a-zA-Z0-9]+ should have its own declaration 54 | golint\:SpecificSuffix=var [a-zA-Z0-9]+ is of type [a-zA-Z0-9\.]+; don't use unit-specific suffix [a-zA-Z0-9]+ 55 | golint\:StructFieldInitialisms=struct field [a-zA-Z0-9]+ should be [a-zA-Z0-9]+ 56 | gocyclo\:CyclomaticComplexity=cyclomatic complexity [0-9]+ of function (\\(([a-zA-Z0-9]+ )?\\*?[a-zA-Z0-9]+\\)\\.)?[a-zA-Z0-9]+\\(\\) is high \\(> [0-9]+\\) 57 | errcheck\:ValueNotChecked=error return value not checked .* 58 | unconvert\:UnnecessaryConversion=unnecessary conversion 59 | structcheck\:UnusedStructField=unused struct field \\w+[\\w\\.]* 60 | gosimple\:ChannelInsteadSelect= 61 | ineffassign\:IneffectualAssignment=ineffectual assignment to [a-zA-Z0-9]+ 62 | gas\:UnhandledErrors=Errors unhandled\.,LOW,HIGH 63 | goimports\:FileNotImported=file is not goimported 64 | vet\:Unreachable=unreachable code 65 | vet\:Shadow=declaration of "[A-Za-z0-9\\.]+" shadows declaration at [A-Za-z0-9_\\-/]+.go:[0-9]+ 66 | vet\:Misuse=possible misuse of unsafe.Pointer 67 | gas\:SQLFormatting=SQL string formatting,MEDIUM,HIGH 68 | gas\:SQLConcatenation=SQL string concatenation,MEDIUM,HIGH 69 | gas\:RSAKeyLength=RSA keys should be at least 2048 bits,MEDIUM,HIGH 70 | gas\:UnsafeCall=Use of unsafe calls should be audited,LOW,HIGH 71 | gas\:UnescapedHTMLTemplates=this method will not auto-escape HTML\. Verify data is well formed\.,MEDIUM,LOW 72 | gas\:WeakCrypto=Use of weak cryptographic primitive,HIGH,HIGH 73 | vet\:Lock=[A-Za-z0-9\.]+ passes lock by value: [A-Za-z0-9\.]+ contains [A-Za-z0-9\.]+ 74 | vet\:FormatingPrintfFamily=possible formatting directive in [A-Za-z0-9\.]+ call 75 | -------------------------------------------------------------------------------- /src/main/resources/profile.properties: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2017 - Université d'Artois 3 | # 4 | # This file is part of SonarQube Golang plugin (sonar-golang). 5 | # 6 | # Sonar-golang is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Sonar-golang is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with Sonar-golang. If not, see . 18 | # 19 | # Contributors: 20 | # Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | ############################################################################### 22 | #golint\:ExportedType=true 23 | golint\:FormComment=true 24 | golint\:AllCaps=true 25 | golint\:UnderscoreInPackageName=true 26 | golint\:LeadingK=true 27 | golint\:UnderscoreInGoName=true 28 | golint\:ErrorLastReturn=true 29 | golint\:ErrorEndString=true 30 | golint\:ErrorVarName=true 31 | golint\:AnnoyingUseExportedType=true 32 | golint\:IfBlockReturn=true 33 | golint\:PackageCommentForm=true 34 | golint\:PackageCommentSpace=true 35 | golint\:ReceiverNameConsistent=true 36 | golint\:ReceiverNameReflection=true 37 | golint\:ReceiverNameNotUnderscore=true 38 | golint\:DropAssignment=true 39 | golint\:HavePackageComment=true 40 | golint\:NotUseBasicType=true 41 | golint\:NotUseDotImport=true 42 | golint\:Omit2ndValueFromRange=true 43 | golint\:OmitType=true 44 | golint\:ReplaceLintIncDec=true 45 | golint\:ReplaceSprintf=true 46 | golint\:Initialisms=true 47 | golint\:PackageNames=true 48 | golint\:BlankImport=true 49 | golint\:CommentExportedType=true 50 | golint\:ContextContextFirstArg=true 51 | golint\:ExportedHaveComment=true 52 | golint\:ExportedHaveComment2=true 53 | golint\:ExportedDeclaration=true 54 | golint\:SpecificSuffix=true 55 | golint\:StructFieldInitialisms=true 56 | gocyclo\:CyclomaticComplexity=true 57 | errcheck\:ValueNotChecked=true 58 | unconvert\:UnnecessaryConversion=true 59 | structcheck\:UnusedStructField=true 60 | gosimple\:ChannelInsteadSelect=true 61 | ineffassign\:IneffectualAssignment=true 62 | gas\:UnhandledErrors=true 63 | goimports\:FileNotImported=true 64 | gas\:SQLFormatting=true 65 | vet\:Shadow=true 66 | gas\:SQLConcatenation=true 67 | gas\:RSAKeyLength=true 68 | gas\:UnsafeCall=true 69 | gas\:UnescapedHTMLTemplates=true 70 | gas\:WeakCrypto=true 71 | vet\:Unreachable=true 72 | vet\:Misuse=true 73 | vet\:Lock=true 74 | vet\:FormatingPrintfFamily=true -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/AbstractSonarTest.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo; 2 | 3 | import org.sonar.api.CoreProperties; 4 | import org.sonar.api.batch.fs.internal.DefaultFileSystem; 5 | import org.sonar.api.batch.sensor.internal.SensorContextTester; 6 | 7 | import fr.univartois.sonargo.core.settings.GoProperties; 8 | 9 | public abstract class AbstractSonarTest { 10 | protected DefaultFileSystem fileSystem; 11 | protected SensorContextTester testerContext; 12 | 13 | public void init() { 14 | init(TestUtils.getDefaultFileSystem()); 15 | } 16 | 17 | public void init(DefaultFileSystem fileSystem) { 18 | this.fileSystem = fileSystem; 19 | 20 | testerContext = SensorContextTester.create(fileSystem.baseDir()); 21 | 22 | testerContext.settings().appendProperty(GoProperties.COVERAGE_REPORT_PATH_KEY, 23 | GoProperties.COVERAGE_REPORT_PATH_DEFAULT); 24 | testerContext.settings().appendProperty(GoProperties.REPORT_PATH_KEY, GoProperties.REPORT_PATH_DEFAULT); 25 | testerContext.settings().appendProperty(GoProperties.JUNIT_REPORT_PATH_KEY, 26 | GoProperties.JUNIT_REPORT_PATH_DEFAULT); 27 | 28 | testerContext.settings().appendProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "vendor/**,.git/**"); 29 | testerContext.settings().appendProperty(CoreProperties.PROJECT_TEST_INCLUSIONS_PROPERTY, "**/**_test.go"); 30 | testerContext.settings().appendProperty(CoreProperties.PROJECT_INCLUSIONS_PROPERTY, "**/**.go"); 31 | testerContext.settings().appendProperty("sonar.sources", "./"); 32 | testerContext.settings().appendProperty("sonar.tests", "./"); 33 | 34 | testerContext.setFileSystem(fileSystem); 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/AllTests.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo; 23 | 24 | import org.junit.runner.RunWith; 25 | import org.junit.runners.Suite; 26 | import org.junit.runners.Suite.SuiteClasses; 27 | 28 | import fr.univartois.sonargo.core.ProjectExplorerTest; 29 | import fr.univartois.sonargo.core.language.GoLanguageTest; 30 | import fr.univartois.sonargo.core.language.GoLexerTest; 31 | import fr.univartois.sonargo.core.language.GoQualityProfileTest; 32 | import fr.univartois.sonargo.core.rules.EvalTest; 33 | import fr.univartois.sonargo.core.rules.GoErrorTest; 34 | import fr.univartois.sonargo.core.rules.GoLintIssueLoaderSendorTest; 35 | import fr.univartois.sonargo.core.rules.GoLintRulesDefinitionTest; 36 | import fr.univartois.sonargo.core.settings.GoPropertiesTest; 37 | import fr.univartois.sonargo.coverage.CoverageSensorTest; 38 | import fr.univartois.sonargo.gotest.FunctionFinderTest; 39 | 40 | @RunWith(Suite.class) 41 | @SuiteClasses({ EvalTest.class, GoErrorTest.class, GoLanguageTest.class, GoQualityProfileTest.class, 42 | GoLintIssueLoaderSendorTest.class, GoLintRulesDefinitionTest.class, GoPluginTest.class, GoPropertiesTest.class, 43 | CoverageSensorTest.class, GoLexerTest.class, FunctionFinderTest.class, ProjectExplorerTest.class }) 44 | public class AllTests { 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/FunctionFinderTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package fr.univartois.sonargo; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | import java.io.File; 9 | import java.nio.file.Paths; 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | import org.junit.Before; 14 | import org.junit.Ignore; 15 | import org.junit.Test; 16 | 17 | import fr.univartois.sonargo.gotest.FunctionFinder; 18 | 19 | /** 20 | * @author thibault 21 | * 22 | */ 23 | @Ignore 24 | public class FunctionFinderTest extends AbstractSonarTest { 25 | @Before 26 | @Override 27 | public void init() { 28 | init(TestUtils.getDefaultFileSystem()); 29 | } 30 | 31 | @Test 32 | public void testSearchInFile() { 33 | String path = new File(testerContext.fileSystem().baseDir(), "test_test.go").getPath(); 34 | 35 | FunctionFinder f = new FunctionFinder(testerContext); 36 | f.searchFunctionInFile(Paths.get(path)); 37 | Map result = f.getResult(); 38 | Set expected = new java.util.HashSet(); 39 | expected.add("TestEasyDef"); 40 | expected.add("TestSpaceDef"); 41 | expected.add("TestNoSpaceDef"); 42 | expected.add("TestTwoLines1"); 43 | expected.add("TestTwoLines2"); 44 | expected.add("TestNested"); 45 | expected.add("TestSuite"); 46 | assertEquals(expected, result.keySet()); 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/GoPluginTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | 26 | import org.junit.Test; 27 | import org.sonar.api.Plugin; 28 | import org.sonar.api.SonarRuntime; 29 | import org.sonar.api.internal.SonarRuntimeImpl; 30 | import org.sonar.api.utils.Version; 31 | 32 | public class GoPluginTest { 33 | private final SonarGoPlugin javaPlugin = new SonarGoPlugin(); 34 | private static final Version VERSION_6_0 = Version.create(6, 0); 35 | 36 | @Test 37 | public void test() { 38 | final SonarRuntime runtime = SonarRuntimeImpl.forSonarLint(VERSION_6_0); 39 | final Plugin.Context context = new Plugin.Context(runtime); 40 | 41 | javaPlugin.define(context); 42 | 43 | assertEquals(13, context.getExtensions().size()); 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/TestUtils.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo; 23 | 24 | import java.io.File; 25 | 26 | import org.sonar.api.batch.fs.InputFile; 27 | import org.sonar.api.batch.fs.internal.DefaultFileSystem; 28 | import org.sonar.api.batch.fs.internal.DefaultInputFile; 29 | 30 | import fr.univartois.sonargo.core.language.GoLanguage; 31 | 32 | public class TestUtils { 33 | private static final String TEST_RESSOURCES = "src/test/resources"; 34 | private static final String COVERAGE_REPORT_PATH = "coverage"; 35 | private static final String TEST_PATH = "gotest"; 36 | private static final String HIGLIGHTER_CODE_PATH = "highlighter"; 37 | private static final String PROJECT_CODE_PATH = "project"; 38 | 39 | public static DefaultFileSystem getDefaultFileSystem() { 40 | return new DefaultFileSystem(getModuleBaseDir()); 41 | } 42 | 43 | public static DefaultFileSystem getTestBaseDir() { 44 | DefaultFileSystem fs = new DefaultFileSystem( 45 | (new File(TEST_RESSOURCES + File.separator + TEST_PATH)).getAbsoluteFile()); 46 | 47 | DefaultInputFile f1 = new DefaultInputFile("module", "test1_test.go"); 48 | f1 = f1.setType(InputFile.Type.TEST); 49 | f1 = f1.setLanguage(GoLanguage.KEY); 50 | 51 | DefaultInputFile f2 = new DefaultInputFile("module", "test_test.go"); 52 | f2 = f2.setType(InputFile.Type.TEST); 53 | f2 = f2.setLanguage(GoLanguage.KEY); 54 | 55 | fs = fs.add(f1); 56 | fs = fs.add(f2); 57 | 58 | return fs; 59 | } 60 | 61 | public static DefaultFileSystem getCoverageBaseDir() { 62 | return new DefaultFileSystem(new File(TEST_RESSOURCES + File.separator + COVERAGE_REPORT_PATH)); 63 | } 64 | 65 | public static DefaultFileSystem getProjectDir() { 66 | DefaultFileSystem fs = new DefaultFileSystem(new File(TEST_RESSOURCES + File.separator + PROJECT_CODE_PATH)); 67 | DefaultInputFile f = new DefaultInputFile("module", "package1.go"); 68 | f = f.setType(InputFile.Type.MAIN); 69 | f = f.setLanguage(GoLanguage.KEY); 70 | 71 | DefaultInputFile f2 = new DefaultInputFile("module", "package1_test.go"); 72 | f2 = f2.setType(InputFile.Type.TEST); 73 | f2 = f2.setLanguage(GoLanguage.KEY); 74 | 75 | DefaultInputFile f3 = new DefaultInputFile("module", "test.py"); 76 | f3 = f3.setType(InputFile.Type.MAIN); 77 | f3 = f3.setLanguage("python"); 78 | 79 | fs = fs.add(f); 80 | fs = fs.add(f2); 81 | fs = fs.add(f3); 82 | 83 | return fs; 84 | } 85 | 86 | public static DefaultFileSystem getColorizeDir() { 87 | return new DefaultFileSystem(new File(TEST_RESSOURCES + File.separator + HIGLIGHTER_CODE_PATH)); 88 | } 89 | 90 | public static File getModuleBaseDir() { 91 | return new File(TEST_RESSOURCES); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/ProjectExplorerTest.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertFalse; 5 | import static org.junit.Assert.assertNotNull; 6 | 7 | import java.util.List; 8 | 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.sonar.api.batch.fs.InputFile; 12 | 13 | import fr.univartois.sonargo.AbstractSonarTest; 14 | import fr.univartois.sonargo.TestUtils; 15 | import fr.univartois.sonargo.core.language.GoLanguage; 16 | 17 | public class ProjectExplorerTest extends AbstractSonarTest { 18 | 19 | @Before 20 | @Override 21 | public void init() { 22 | init(TestUtils.getProjectDir()); 23 | } 24 | 25 | @Test 26 | public void testSearchByType() { 27 | 28 | List list = ProjectExplorer.searchByType(testerContext, InputFile.Type.MAIN); 29 | assertFalse(list.isEmpty()); 30 | assertEquals(1, list.size()); 31 | } 32 | 33 | @Test 34 | public void testSearchFileWithTypeMainOrTest() { 35 | List list = ProjectExplorer.searchFileWithTypeMainOrTest(testerContext); 36 | assertFalse(list.isEmpty()); 37 | assertEquals(2, list.size()); 38 | } 39 | 40 | @Test 41 | public void testGetByPath() { 42 | assertNotNull(ProjectExplorer.getByPath(testerContext, "package1.go")); 43 | assertNotNull(ProjectExplorer.getByPath(testerContext, "package1.go").language()); 44 | assertEquals(GoLanguage.KEY, ProjectExplorer.getByPath(testerContext, "package1.go").language()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/language/GoGrammarTest.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core.language; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | import java.util.ArrayList; 9 | 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import org.sonar.sslr.tests.ParserAssert; 13 | 14 | import com.sonar.sslr.api.Grammar; 15 | import com.sonar.sslr.api.Rule; 16 | import com.sonar.sslr.impl.Lexer; 17 | import com.sonar.sslr.impl.Parser; 18 | import com.sonar.sslr.impl.matcher.RuleDefinition; 19 | 20 | import fr.univartois.sonargo.coverage.CoverageSensor; 21 | 22 | public class GoGrammarTest { 23 | private Rule rule; 24 | private Parser parser; 25 | private ArrayList goCodes; 26 | 27 | @Before 28 | public void init() { 29 | Lexer lexer = GoLexer.create(); 30 | rule = new RuleDefinition("ruleName").is("foo"); 31 | Grammar grammar = GoGrammar.create(); 32 | parser = Parser.builder(grammar).withLexer(lexer).build(); 33 | goCodes = new ArrayList<>(); 34 | try { 35 | parseGoCode(); 36 | } catch (IOException e) { 37 | // TODO Auto-generated catch block 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | public void parseGoCode() throws IOException { 43 | Files.list(new File(CoverageSensor.class.getResource("/grammar").getFile()).toPath()).forEach(path -> { 44 | try { 45 | BufferedReader reader = new BufferedReader(new FileReader(path.toFile())); 46 | String sCurrentLine; 47 | StringBuilder sb = new StringBuilder(); 48 | while ((sCurrentLine = reader.readLine()) != null) { 49 | sb.append(sCurrentLine + "\n"); 50 | } 51 | goCodes.add(sb.toString()); 52 | } catch (IOException e) { 53 | // TODO Auto-generated catch block 54 | e.printStackTrace(); 55 | } 56 | }); 57 | 58 | } 59 | 60 | @Test 61 | public void ok() { 62 | for (String s : goCodes) { 63 | System.out.println(s); 64 | new ParserAssert(parser).matches(s); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/language/GoLanguageTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.language; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.junit.Assert.assertFalse; 26 | import static org.junit.Assert.assertTrue; 27 | 28 | import java.util.Arrays; 29 | 30 | import org.junit.Test; 31 | 32 | import fr.univartois.sonargo.core.language.GoLanguage; 33 | 34 | public class GoLanguageTest { 35 | 36 | @Test 37 | public void test() { 38 | GoLanguage go = new GoLanguage(); 39 | assertTrue(go.hasValidSuffixes("test.go")); 40 | assertFalse(go.hasValidSuffixes("test.xml")); 41 | String[] def = { "go" }; 42 | 43 | assertEquals(Arrays.asList(def), Arrays.asList(go.getFileSuffixes())); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/language/GoLexerTest.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core.language; 2 | 3 | import static com.sonar.sslr.api.GenericTokenType.IDENTIFIER; 4 | import static com.sonar.sslr.test.lexer.LexerMatchers.hasToken; 5 | import static fr.univartois.sonargo.core.language.GoLexer.Literals.FLOAT; 6 | import static fr.univartois.sonargo.core.language.GoLexer.Literals.INTEGER; 7 | import static org.junit.Assert.assertThat; 8 | import static org.junit.Assert.assertTrue; 9 | 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | import org.junit.Test; 14 | 15 | import com.sonar.sslr.impl.Lexer; 16 | 17 | public class GoLexerTest { 18 | Lexer lexer = GoLexer.create(); 19 | private Pattern pattern; 20 | private Matcher matcher; 21 | 22 | @Test 23 | public void lexIdentifiers() { 24 | assertThat(lexer.lex("abc"), hasToken("abc", IDENTIFIER)); 25 | assertThat(lexer.lex("abc0"), hasToken("abc0", IDENTIFIER)); 26 | assertThat(lexer.lex("abc_0"), hasToken("abc_0", IDENTIFIER)); 27 | assertThat(lexer.lex("i"), hasToken("i", IDENTIFIER)); 28 | } 29 | 30 | @Test 31 | public void lexKeyword() { 32 | assertThat(lexer.lex("int"), hasToken("int", GoLexer.Keyword.INT)); 33 | assertThat(lexer.lex("int32"), hasToken("int32", GoLexer.Keyword.INT32)); 34 | assertThat(lexer.lex("int64"), hasToken("int64", GoLexer.Keyword.INT64)); 35 | } 36 | 37 | @Test 38 | public void lexIntegers() { 39 | 40 | assertThat(lexer.lex("01"), hasToken("01", INTEGER)); 41 | assertThat(lexer.lex("1"), hasToken("1", INTEGER)); 42 | assertThat(lexer.lex("0x1F"), hasToken("0x1F", INTEGER)); 43 | assertThat(lexer.lex("0x1e"), hasToken("0x1e", INTEGER)); 44 | } 45 | 46 | @Test 47 | public void lexFloat() { 48 | 49 | final String[] array = { "0.", "72.40", "072.40", "2.71828", "1.e+0", "6.67428e-11", "1E6", ".25", ".12345E+5" 50 | 51 | }; 52 | 53 | pattern = Pattern.compile(GoLexer.Literals.FLOAT.getValue()); 54 | matcher = pattern.matcher("1.1"); 55 | assertTrue(matcher.matches()); 56 | matcher = pattern.matcher("1.0"); 57 | assertTrue(matcher.matches()); 58 | matcher = pattern.matcher("1.0e+10"); 59 | assertTrue(matcher.matches()); 60 | matcher = pattern.matcher("1.0e-10"); 61 | assertTrue(matcher.matches()); 62 | matcher = pattern.matcher("1.0E-10"); 63 | assertTrue(matcher.matches()); 64 | matcher = pattern.matcher("1.0E+10"); 65 | assertTrue(matcher.matches()); 66 | matcher = pattern.matcher("1e-10"); 67 | assertTrue(matcher.matches()); 68 | matcher = pattern.matcher("1e+10"); 69 | assertTrue(matcher.matches()); 70 | matcher = pattern.matcher(".1e+10"); 71 | assertTrue(matcher.matches()); 72 | matcher = pattern.matcher(".1e-10"); 73 | assertTrue(matcher.matches()); 74 | matcher = pattern.matcher(".1"); 75 | assertTrue(matcher.matches()); 76 | 77 | for (final String s : array) { 78 | matcher = pattern.matcher(s); 79 | assertTrue(matcher.matches()); 80 | } 81 | 82 | assertThat(lexer.lex("1.0"), hasToken("1.0", FLOAT)); 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/language/GoQualityProfileTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.language; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.junit.Assert.assertFalse; 26 | import static org.junit.Assert.assertTrue; 27 | 28 | import java.io.IOException; 29 | import java.util.Properties; 30 | import java.util.function.Predicate; 31 | 32 | import org.junit.Test; 33 | import org.sonar.api.profiles.RulesProfile; 34 | import org.sonar.api.rules.ActiveRule; 35 | import org.sonar.api.utils.ValidationMessages; 36 | 37 | import fr.univartois.sonargo.core.language.GoQualityProfile; 38 | 39 | public class GoQualityProfileTest { 40 | private GoQualityProfile goprofile = new GoQualityProfile(); 41 | 42 | @Test 43 | public void testLoadingQualityProfile() { 44 | 45 | RulesProfile rule = goprofile.createProfile(ValidationMessages.create()); 46 | assertFalse(rule.getActiveRules().isEmpty()); 47 | Properties prop = new Properties(); 48 | 49 | try { 50 | prop.load(GoQualityProfileTest.class.getResourceAsStream(GoQualityProfile.PROFILE_PATH)); 51 | Predicate predicate = s -> Boolean.TRUE.equals(Boolean.parseBoolean((String) s)); 52 | assertEquals(prop.values().stream().filter(predicate).count(), rule.getActiveRules().size()); 53 | 54 | for (ActiveRule r : rule.getActiveRules()) { 55 | assertTrue(r.isEnabled()); 56 | assertTrue(r.getRule().isEnabled()); 57 | } 58 | 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | } 62 | 63 | assertTrue(rule.getDefaultProfile()); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/metrics/GoMetricSensorTest.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.core.metrics; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | 6 | import java.util.Map; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.sonar.api.measures.CoreMetrics; 11 | import org.sonar.api.measures.Metric; 12 | 13 | import fr.univartois.sonargo.AbstractSonarTest; 14 | import fr.univartois.sonargo.TestUtils; 15 | 16 | public class GoMetricSensorTest extends AbstractSonarTest { 17 | @Before 18 | @Override 19 | public void init() { 20 | init(TestUtils.getProjectDir()); 21 | } 22 | 23 | @Test 24 | public void testExecute() { 25 | GoMetricSensor sensor = new GoMetricSensor(); 26 | sensor.execute(testerContext); 27 | Map, Integer> measures = sensor.getMeasures(); 28 | assertNotNull(measures); 29 | assertEquals(new Integer(7), measures.get(CoreMetrics.NCLOC)); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/rules/EvalTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; 25 | 26 | import java.util.List; 27 | 28 | import org.jbehave.core.configuration.Configuration; 29 | import org.jbehave.core.configuration.MostUsefulConfiguration; 30 | import org.jbehave.core.io.StoryFinder; 31 | import org.jbehave.core.junit.JUnitStories; 32 | import org.jbehave.core.reporters.Format; 33 | import org.jbehave.core.reporters.StoryReporterBuilder; 34 | import org.jbehave.core.steps.InjectableStepsFactory; 35 | import org.jbehave.core.steps.InstanceStepsFactory; 36 | import org.junit.runner.RunWith; 37 | 38 | import de.codecentric.jbehave.junit.monitoring.JUnitReportingRunner; 39 | 40 | @RunWith(JUnitReportingRunner.class) 41 | public class EvalTest extends JUnitStories { 42 | 43 | public EvalTest() { 44 | configuredEmbedder().embedderControls().doGenerateViewAfterStories(false).doIgnoreFailureInStories(false) 45 | .doIgnoreFailureInView(false).doVerboseFailures(true); 46 | } 47 | 48 | @Override 49 | public Configuration configuration() { 50 | return new MostUsefulConfiguration() 51 | // CONSOLE reporting 52 | .useStoryReporterBuilder(new StoryReporterBuilder().withDefaultFormats().withFormats(Format.CONSOLE)); 53 | } 54 | 55 | // Here we specify the steps classes 56 | @Override 57 | public InjectableStepsFactory stepsFactory() { 58 | // varargs, can have more that one steps classes 59 | return new InstanceStepsFactory(configuration(), new ReportEvalStoryTest()); 60 | } 61 | 62 | @Override 63 | protected List storyPaths() { 64 | return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), "**/*.story", "**/excluded*.story"); 65 | } 66 | } -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/rules/GoErrorTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.junit.Assert.assertFalse; 26 | import static org.junit.Assert.assertTrue; 27 | 28 | import org.junit.Test; 29 | 30 | import fr.univartois.sonargo.core.rules.GoError; 31 | 32 | public class GoErrorTest { 33 | 34 | @Test 35 | public void testInitAndEqualityGoError() { 36 | GoError error = new GoError(10, "un message", "warning", "test.go"); 37 | GoError error2 = new GoError(10, "un message", "warning", "test.go"); 38 | GoError error3 = new GoError(10, "un message 2", "warning", "test.go"); 39 | assertEquals(error.hashCode(), error2.hashCode()); 40 | assertTrue(error.equals(error2)); 41 | assertFalse(error.equals(error3)); 42 | assertEquals(10, error.getLine()); 43 | assertEquals("un message", error.getMessage()); 44 | assertEquals("warning", error.getSeverity()); 45 | assertEquals("test.go", error.getFilePath()); 46 | 47 | assertEquals("GoError [line=10, message=un message, severity=warning, filePath=test.go]", error.toString()); 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/rules/GoLintIssueLoaderSendorTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | import static org.junit.Assert.assertNotNull; 25 | import static org.mockito.Mockito.mock; 26 | 27 | import java.io.File; 28 | 29 | import org.junit.Before; 30 | import org.junit.Test; 31 | import org.sonar.api.batch.fs.internal.DefaultFileSystem; 32 | import org.sonar.api.batch.sensor.SensorDescriptor; 33 | import org.sonar.api.config.Settings; 34 | 35 | import fr.univartois.sonargo.core.rules.GoLintIssueLoaderSensor; 36 | 37 | public class GoLintIssueLoaderSendorTest { 38 | private DefaultFileSystem fileSystem; 39 | private GoLintIssueLoaderSensor sensor; 40 | 41 | @Before 42 | public void setUp() { 43 | fileSystem = new DefaultFileSystem((File) null); 44 | sensor = new GoLintIssueLoaderSensor(new Settings(), fileSystem); 45 | } 46 | 47 | @Test 48 | public void describe() { 49 | SensorDescriptor sensorDescriptor = mock(SensorDescriptor.class); 50 | 51 | assertNotNull(sensorDescriptor); 52 | assertNotNull(sensor); 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/rules/GoLintRulesDefinitionTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.junit.Assert.assertNotNull; 26 | 27 | import org.junit.Test; 28 | import org.sonar.api.server.rule.RulesDefinition; 29 | 30 | import fr.univartois.sonargo.core.language.GoLanguage; 31 | 32 | public class GoLintRulesDefinitionTest { 33 | @Test 34 | public void testForVersion6() { 35 | GoLintRulesDefinition definition = new GoLintRulesDefinition(); 36 | RulesDefinition.Context context = new RulesDefinition.Context(); 37 | definition.define(context); 38 | RulesDefinition.Repository repository = context.repository(GoLintRulesDefinition.REPO_KEY); 39 | 40 | assertEquals(GoLintRulesDefinition.REPO_NAME, repository.name()); 41 | assertEquals(GoLanguage.KEY, repository.language()); 42 | GoKeyRule.init(); 43 | assertEquals(GoKeyRule.getProp().size(), repository.rules().size()); 44 | 45 | for (Object key : GoKeyRule.getProp().keySet()) { 46 | assertNotNull(repository.rule((String) key)); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/rules/ReportEvalStoryTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.rules; 23 | 24 | import static org.hamcrest.CoreMatchers.equalTo; 25 | import static org.junit.Assert.assertThat; 26 | 27 | import org.jbehave.core.annotations.Given; 28 | import org.jbehave.core.annotations.Then; 29 | import org.jbehave.core.annotations.When; 30 | 31 | import fr.univartois.sonargo.core.rules.GoError; 32 | import fr.univartois.sonargo.core.rules.GoKeyRule; 33 | 34 | public class ReportEvalStoryTest { 35 | private String eval; 36 | 37 | @Given("Given a Key finder") 38 | public void newInterpreter() { 39 | GoKeyRule.init(); 40 | } 41 | 42 | @When("the expression entered is $expression") 43 | public void eval(String expression) { 44 | eval = GoKeyRule.getKeyFromError(new GoError(10, expression, null, null)); 45 | 46 | } 47 | 48 | @Then("the result should be $expectedValue") 49 | public void checkValue(String expectedValue) { 50 | assertThat(String.valueOf(eval), equalTo(expectedValue)); 51 | System.out.println(String.valueOf(eval)); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/rules/expression.story: -------------------------------------------------------------------------------- 1 | Some expression violation 2 | 3 | Narrative: 4 | Our plugin should be able to 5 | find a key for message. 6 | 7 | Scenario: find key of message 8 | 9 | Given Given a Key finder 10 | 11 | When the expression entered is 12 | Then the result should be 13 | 14 | Examples: 15 | 16 | |expression |result| 17 | |exported type Foo should have comment or be unexported|golint:ExportedHaveComment| 18 | |comment on exported type Foo should be of the form "Foo ..."|golint:FormComment| 19 | |comment on exported type Foo should be of the form "Foo..."|golint:FormComment| 20 | |comment on exported method Foo.Bar should be of the form "Foo.Bar ..."|golint:FormComment| 21 | |don't use ALL_CAPS in Go names; use CamelCase|golint:AllCaps| 22 | |don't use an underscore in package name|golint:UnderscoreInPackageName| 23 | |don't use leading k in Go names; var kFoo should be Foo|golint:LeadingK| 24 | |don't use underscores in Go names; var foo_bar should be fooBar|golint:UnderscoreInGoName| 25 | |error should be the last type when returning multiple items|golint:ErrorLastReturn| 26 | |error strings should not be capitalized or end with punctuation or a newline|golint:ErrorEndString| 27 | |error var err should have name of the form errFo|golint:ErrorVarName| 28 | |exported method FooMethod returns unexported type unexportedType, which can be annoying to use|golint:AnnoyingUseExportedType| 29 | |if block ends with a return statement, so drop this else and outdent its block|golint:IfBlockReturn| 30 | |package comment should be of the form "Package..."|golint:PackageCommentForm| 31 | |package comment should not have leading space|golint:PackageCommentSpace| 32 | |receiver name a should be consistent with previous receiver name b for bar|golint:ReceiverNameConsistent| 33 | |receiver name should be a reflection of its identity; don't use generic names such as "this" or "self"|golint:ReceiverNameReflection| 34 | |receiver name should not be an underscore|golint:ReceiverNameNotUnderscore| 35 | |should drop = 0 from declaration of var myZeroInt; it is the zero value|golint:DropAssignment| 36 | |should drop = nil from declaration of var myPtr; it is the zero value|golint:DropAssignment| 37 | |should have a package comment, unless it's in another file for this package|golint:HavePackageComment| 38 | |should not use basic type int8 as key in context.WithValue|golint:NotUseBasicType| 39 | |should not use basic type int16 as key in context.WithValue|golint:NotUseBasicType| 40 | |should not use basic type int32 as key in context.WithValue|golint:NotUseBasicType| 41 | |should not use basic type uint8 as key in context.WithValue|golint:NotUseBasicType| 42 | |should not use basic type uintptr as key in context.WithValue|golint:NotUseBasicType| 43 | |should not use dot imports|golint:NotUseDotImport| 44 | |should omit 2nd value from range; this loop is equivalent to `for x := range ...`|golint:Omit2ndValueFromRange| 45 | |should omit type int from declaration of var myZeroInt; it will be inferred from the right-hand side|golint:OmitType| 46 | |should replace x=x+1 with x++|golint:ReplaceLintIncDec| 47 | |should replace t.Errorf(fmt.Sprintf(...)) with t.Errorf(...)|golint:ReplaceSprintf| 48 | |var Serverhttp should be ServerHTTP|golint:Initialisms| 49 | |func name will be used as foo.FooMulti by other packages, and that stutters; consider calling this Multi|golint:PackageNames| 50 | |a blank import should be only in a main or test package, or have a comment justifying it|golint:BlankImport| 51 | |comment on exported type Foo should be of the form "Foo ..." (with optional leading article)|golint:CommentExportedType| 52 | |context.Context should be the first parameter of a function|golint:ContextContextFirstArg| 53 | |exported method FooMethod should have comment or be unexported|golint:ExportedHaveComment| 54 | |exported const FooType should have comment (or a comment on this block) or be unexported|golint:ExportedHaveComment2| 55 | |exported const Hello4 should have its own declaration|golint:ExportedDeclaration|//more info https://github.com/go-lang-plugin-org/go-lang-idea-plugin/issues/2049 56 | |var timeoutSecs is of type time.Second; don't use unit-specific suffix Secs|golint:SpecificSuffix| 57 | |cyclomatic complexity 11 of function main() is high (> 10)|gocyclo:CyclomaticComplexity| 58 | |error return value not checked (os.MkdirAll("./tmp/build", os.FileMode(0755)))|errcheck:ValueNotChecked| 59 | |error return value not checked (util.Save(jpegimage.(*image.NRGBA), "png_"+nameWithoutExtension+".png"))|errcheck:ValueNotChecked| 60 | |error return value not checked (route(r))|errcheck:ValueNotChecked| 61 | |error return value not checked (core.NewConfiguration(ConfigName, ConfigPath).ReadInConfig())|errcheck:ValueNotChecked| 62 | |unnecessary conversion|unconvert:UnnecessaryConversion| 63 | |unused struct field projectblackwhitego.ImageService.req|structcheck:UnusedStructField| 64 | |exported method BaseGS1.CodingSet should have comment or be unexported|golint:ExportedHaveComment| 65 | |exported method Rule.CodingSet should have comment or be unexported|golint:ExportedHaveComment| 66 | |struct field Id should be ID|golint:StructFieldInitialisms| 67 | |unreachable code|vet:Unreachable| 68 | |declaration of "configuration" shadows declaration at line.go:142|vet:Shadow| 69 | |declaration of "err" shadows declaration at tcp_client_test.go:155|vet:Shadow| 70 | |possible misuse of unsafe.Pointer|vet:Misuse| 71 | |NotificationEventsHandler passes lock by value: sync.WaitGroup contains sync.noCopy|vet:Lock| 72 | |a message error not found|null| -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/core/settings/GoPropertiesTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2017 - Université d'Artois 3 | * 4 | * This file is part of SonarQube Golang plugin (sonar-golang). 5 | * 6 | * Sonar-golang is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Sonar-golang is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with Sonar-golang. If not, see . 18 | * 19 | * Contributors: 20 | * Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | *******************************************************************************/ 22 | package fr.univartois.sonargo.core.settings; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | 26 | import java.util.List; 27 | 28 | import org.junit.Test; 29 | import org.sonar.api.config.PropertyDefinition; 30 | 31 | public class GoPropertiesTest { 32 | 33 | @Test 34 | public void test() { 35 | List l = GoProperties.getProperties(); 36 | assertEquals(5, l.size()); 37 | assertEquals(GoProperties.REPORT_PATH_DEFAULT, l.get(0).defaultValue()); 38 | assertEquals(GoProperties.COVERAGE_REPORT_PATH_DEFAULT, l.get(1).defaultValue()); 39 | assertEquals(GoProperties.JUNIT_REPORT_PATH_DEFAULT, l.get(2).defaultValue()); 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/coverage/CoverageSensorTest.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.coverage; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.File; 9 | import java.io.FileNotFoundException; 10 | import java.io.FileReader; 11 | import java.io.IOException; 12 | import java.nio.file.Path; 13 | import java.nio.file.Paths; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | import java.util.stream.Stream; 17 | 18 | import org.junit.Before; 19 | import org.junit.Test; 20 | import org.sonar.api.batch.fs.internal.DefaultInputFile; 21 | import org.sonar.api.batch.sensor.coverage.CoverageType; 22 | import org.sonar.api.utils.log.Logger; 23 | import org.sonar.api.utils.log.Loggers; 24 | 25 | import com.google.common.collect.ImmutableMap; 26 | 27 | import fr.univartois.sonargo.AbstractSonarTest; 28 | import fr.univartois.sonargo.TestUtils; 29 | import fr.univartois.sonargo.core.language.GoLanguage; 30 | 31 | public class CoverageSensorTest extends AbstractSonarTest { 32 | private static final Logger LOGGER = Loggers.get(CoverageSensorTest.class); 33 | 34 | @Before 35 | @Override 36 | public void init() { 37 | init(TestUtils.getCoverageBaseDir()); 38 | } 39 | 40 | @Test 41 | public void testCreateStream() { 42 | final CoverageSensor sensor = new CoverageSensor(); 43 | try (Stream paths = sensor.createStream(testerContext)) { 44 | 45 | assertNotNull(paths); 46 | 47 | } catch (final IOException e) { 48 | // TODO Auto-generated catch block 49 | e.printStackTrace(); 50 | } 51 | } 52 | 53 | @Test 54 | public void testExcludedPathProperty() { 55 | final CoverageSensor sensor = new CoverageSensor(); 56 | boolean check = sensor.isAnExcludedPath(Paths.get(fileSystem.baseDir().getAbsolutePath(), "vendor/test"), 57 | testerContext); 58 | assertTrue(check); 59 | } 60 | 61 | @Test 62 | public void testIgnoreFileStream() { 63 | final CoverageSensor sensor = new CoverageSensor(); 64 | Stream paths; 65 | try { 66 | paths = sensor.createStream(testerContext); 67 | assertEquals(33, paths.count()); 68 | 69 | } catch (IOException e) { 70 | // TODO Auto-generated catch block 71 | e.printStackTrace(); 72 | } 73 | 74 | } 75 | 76 | private void initFile() { 77 | String[] listFile = { "util/util.go", "mathutil/mathutil.go", "pixel/pixel.go", 78 | "mathutil/filewithnocoverage.go", "issue60/a.go", "issue61/simplelinecomment.go", 79 | "issue61/multilinecomment.go", "issue61/typestruct.go" }; 80 | 81 | BufferedReader reader; 82 | try { 83 | 84 | for (int i = 0; i < listFile.length; i++) { 85 | System.out.println(listFile[i]); 86 | reader = new BufferedReader(new FileReader( 87 | new File(CoverageSensor.class.getResource("/coverage/" + listFile[i]).getFile()))); 88 | 89 | String sCurrentLine; 90 | 91 | StringBuilder sb = new StringBuilder(); 92 | while ((sCurrentLine = reader.readLine()) != null) { 93 | sb.append(sCurrentLine + "\n"); 94 | } 95 | 96 | testerContext.fileSystem().add(new DefaultInputFile("myProjectKey", listFile[i]) 97 | .setLanguage(GoLanguage.KEY).initMetadata(sb.toString())); 98 | 99 | } 100 | 101 | } catch (FileNotFoundException e) { 102 | // TODO Auto-generated catch block 103 | e.printStackTrace(); 104 | } catch (IOException e) { 105 | // TODO Auto-generated catch block 106 | e.printStackTrace(); 107 | } 108 | } 109 | 110 | @Test 111 | public void testExecution() { 112 | final CoverageSensor sensor = new CoverageSensor(); 113 | initFile(); 114 | sensor.execute(testerContext); 115 | 116 | Map> map = new HashMap<>(); 117 | map.put("myProjectKey:mathutil/mathutil.go", ImmutableMap.of(7, 1)); 118 | map.put("myProjectKey:pixel/pixel.go", ImmutableMap.of(21, 0, 37, 0)); 119 | 120 | Map testValuesMap = new HashMap<>(); 121 | 122 | testValuesMap.put(3, null); 123 | testValuesMap.put(1, null); 124 | testValuesMap.put(4, null); 125 | testValuesMap.put(8, 0); 126 | testValuesMap.put(12, 0); 127 | 128 | map.put("myProjectKey:mathutil/filewithnocoverage.go", testValuesMap); 129 | map.put("myProjectKey:issue60/a.go", ImmutableMap.of(8, 0, 9, 0)); 130 | Map testValuesMap2 = new HashMap<>(); 131 | testValuesMap2.put(1, null); 132 | testValuesMap2.put(2, null); 133 | testValuesMap2.put(3, null); 134 | testValuesMap2.put(4, null); 135 | testValuesMap2.put(5, null); 136 | testValuesMap2.put(6, null); 137 | testValuesMap2.put(8, 0); 138 | testValuesMap2.put(9, 0); 139 | testValuesMap2.put(11, null); 140 | map.put("myProjectKey:issue61/simplelinecomment.go", testValuesMap2); 141 | 142 | Map testValuesMap3 = new HashMap<>(); 143 | 144 | for (int i = 1; i <= 20; i++) { 145 | testValuesMap3.put(i, null); 146 | } 147 | testValuesMap3.put(26, null); 148 | testValuesMap3.put(27, null); 149 | testValuesMap3.put(28, null); 150 | testValuesMap3.put(30, 0); 151 | testValuesMap3.put(31, 0); 152 | 153 | map.put("myProjectKey:issue61/multilinecomment.go", testValuesMap3); 154 | 155 | Map testValuesMap4 = new HashMap<>(); 156 | for (int i = 6; i <= 48; i++) { 157 | testValuesMap4.put(i, null); 158 | } 159 | map.put("myProjectKey:issue61/typestruct.go", testValuesMap4); 160 | map.forEach((key, mapValue) -> { 161 | mapValue.forEach((line, value) -> { 162 | assertEquals("line " + line + " " + key, value, testerContext.lineHits(key, CoverageType.UNIT, line)); 163 | }); 164 | }); 165 | 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/gotest/FunctionFinderTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package fr.univartois.sonargo.gotest; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | import java.io.File; 10 | import java.nio.file.Paths; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | import org.sonar.api.utils.log.Logger; 17 | import org.sonar.api.utils.log.Loggers; 18 | 19 | import fr.univartois.sonargo.AbstractSonarTest; 20 | import fr.univartois.sonargo.TestUtils; 21 | 22 | /** 23 | * @author thibault 24 | * 25 | */ 26 | public class FunctionFinderTest extends AbstractSonarTest { 27 | private static final Logger LOGGER = Loggers.get(FunctionFinderTest.class); 28 | 29 | @Before 30 | @Override 31 | public void init() { 32 | init(TestUtils.getTestBaseDir()); 33 | } 34 | 35 | @Test 36 | public void testSearchInFile() { 37 | String path = new File(TestUtils.getTestBaseDir().baseDir(), "test_test.go").getAbsolutePath(); 38 | LOGGER.info("testSearchInFile " + path); 39 | FunctionFinder f = new FunctionFinder(testerContext); 40 | f.searchFunctionInFile(Paths.get(path)); 41 | Map result = f.getResult(); 42 | Set expected = new java.util.HashSet(); 43 | expected.add("TestEasyDef"); 44 | expected.add("TestSpaceDef"); 45 | expected.add("TestNoSpaceDef"); 46 | expected.add("TestTwoLines1"); 47 | expected.add("TestTwoLines2"); 48 | expected.add("TestNested"); 49 | expected.add("TestSuite"); 50 | assertEquals(expected, result.keySet()); 51 | 52 | } 53 | 54 | @Test 55 | public void testSearchFunction() { 56 | LOGGER.info("testSearchFunction " + testerContext.fileSystem().baseDir()); 57 | FunctionFinder f = new FunctionFinder(testerContext); 58 | Map nameFunction = f.searchFunction(); 59 | 60 | assertTrue(nameFunction.containsKey("TestAverage")); 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/fr/univartois/sonargo/highlighter/ColorizerTest.java: -------------------------------------------------------------------------------- 1 | package fr.univartois.sonargo.highlighter; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertFalse; 5 | 6 | import java.io.File; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.List; 9 | 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import org.sonar.api.batch.fs.internal.DefaultInputFile; 13 | import org.sonar.api.batch.fs.internal.FileMetadata; 14 | import org.sonar.api.batch.sensor.highlighting.TypeOfText; 15 | 16 | import fr.univartois.sonargo.AbstractSonarTest; 17 | import fr.univartois.sonargo.TestUtils; 18 | 19 | public class ColorizerTest extends AbstractSonarTest { 20 | private File file; 21 | private DefaultInputFile inputFile; 22 | 23 | @Override 24 | @Before 25 | public void init() { 26 | init(TestUtils.getColorizeDir()); 27 | 28 | file = new File(testerContext.fileSystem().baseDir(), "/test.go"); 29 | inputFile = new DefaultInputFile("moduleKey", file.getName()) 30 | .initMetadata(new FileMetadata().readMetadata(file, StandardCharsets.UTF_8)); 31 | 32 | testerContext.fileSystem().add(inputFile); 33 | } 34 | 35 | @Test 36 | public void testColorize() { 37 | 38 | file = new File(testerContext.fileSystem().baseDir(), "/test.go"); 39 | inputFile = new DefaultInputFile("moduleKey", file.getName()) 40 | .initMetadata(new FileMetadata().readMetadata(file, StandardCharsets.UTF_8)); 41 | 42 | testerContext.fileSystem().add(inputFile); 43 | 44 | final Colorizer c = new Colorizer(testerContext); 45 | c.colorize(inputFile); 46 | final String componentKey = "moduleKey:" + file.getName(); 47 | 48 | assertEquals(TypeOfText.KEYWORD, testerContext.highlightingTypeAt(componentKey, 1, 1).get(0)); 49 | assertEquals(TypeOfText.KEYWORD, testerContext.highlightingTypeAt(componentKey, 3, 3).get(0)); 50 | } 51 | 52 | @Test 53 | public void testBug1() { 54 | 55 | file = new File(testerContext.fileSystem().baseDir(), "/testbug1.go"); 56 | inputFile = new DefaultInputFile("moduleKey", file.getName()) 57 | .initMetadata(new FileMetadata().readMetadata(file, StandardCharsets.UTF_8)); 58 | 59 | testerContext.fileSystem().add(inputFile); 60 | 61 | final Colorizer c = new Colorizer(testerContext); 62 | c.colorize(inputFile); 63 | 64 | checkOnRange(1, 0, 3, TypeOfText.KEYWORD); // var 65 | checkOnRange(1, 13, 6, TypeOfText.KEYWORD); // string 66 | checkOnRange(1, 23, 12, TypeOfText.STRING); // "test\"other" 67 | 68 | } 69 | 70 | private void checkOnRange(int line, int start, int length, TypeOfText typeOfText) { 71 | final String componentKey = "moduleKey:" + file.getName(); 72 | 73 | List found; 74 | 75 | for (int column = start; column < start + length; column++) { 76 | System.out.println(line + " " + column); 77 | found = testerContext.highlightingTypeAt(componentKey, line, column); 78 | assertFalse(found.isEmpty()); 79 | assertEquals(typeOfText, found.get(0)); 80 | } 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/resources/coverage/.ignoredfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/coverage/.ignoredfile -------------------------------------------------------------------------------- /src/test/resources/coverage/.sonar/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/coverage/.sonar/test -------------------------------------------------------------------------------- /src/test/resources/coverage/issue60/a.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | foo() 9 | fmt.Println("vim-go") 10 | } -------------------------------------------------------------------------------- /src/test/resources/coverage/issue61/multilinecomment.go: -------------------------------------------------------------------------------- 1 | /* 2 | Exemple from: https://golang.org/doc/effective_go.html#commentary 3 | Package regexp implements a simple library for regular expressions. 4 | 5 | The syntax of the regular expressions accepted is: 6 | 7 | regexp: 8 | concatenation { '|' concatenation } 9 | concatenation: 10 | { closure } 11 | closure: 12 | term [ '*' | '+' | '?' ] 13 | term: 14 | '^' 15 | '$' 16 | '.' 17 | character 18 | '[' [ '^' ] character-ranges ']' 19 | '(' regexp ')' 20 | */ 21 | package regexp 22 | 23 | import ( 24 | "fmt" 25 | ) 26 | /* Compile parses a regular expression and returns, if successful, 27 | a Regexp that can be used to match against text. 28 | */ 29 | func Compile(str string) (*Regexp, error) {func main() { 30 | foo() 31 | fmt.Println("vim-go") 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/test/resources/coverage/issue61/simplelinecomment.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | //a simle line comment 7 | func main() { 8 | foo() 9 | fmt.Println("vim-go") 10 | } 11 | //a simle line comment 12 | func secondFunction(){ 13 | test(); 14 | } -------------------------------------------------------------------------------- /src/test/resources/coverage/issue61/typestruct.go: -------------------------------------------------------------------------------- 1 | package issue61 2 | 3 | func main(){ 4 | 5 | } 6 | // An empty struct. 7 | struct {} 8 | 9 | // A struct with 6 fields. 10 | struct { 11 | x, y int 12 | u float32 13 | _ float32 // padding 14 | A *[]int 15 | F func() 16 | } 17 | 18 | interface { 19 | Read(b Buffer) bool 20 | Write(b Buffer) bool 21 | Close() 22 | } 23 | 24 | // A struct with 6 fields. 25 | type test struct { 26 | x, y int 27 | u float32 28 | _ float32 // padding 29 | A *[]int 30 | } 31 | 32 | 33 | type ReadWriter interface { 34 | Read(b Buffer) bool 35 | Write(b Buffer) bool 36 | } 37 | 38 | type File interface { 39 | ReadWriter // same as adding the methods of ReadWriter 40 | Locker // same as adding the methods of Locker 41 | Close() 42 | } 43 | 44 | type LockedFile interface { 45 | Locker 46 | File // illegal: Lock, Unlock not unique 47 | Lock() // illegal: Lock not unique 48 | } -------------------------------------------------------------------------------- /src/test/resources/coverage/mathutil/coverage.out: -------------------------------------------------------------------------------- 1 | mode: set 2 | projectblackwhitego/mathutil/mathutil.go:6.34,8.2 1 1 3 | -------------------------------------------------------------------------------- /src/test/resources/coverage/mathutil/coverage.out.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/coverage/mathutil/coverage.out.xml -------------------------------------------------------------------------------- /src/test/resources/coverage/mathutil/coverage.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/resources/coverage/mathutil/filewithnocoverage.go: -------------------------------------------------------------------------------- 1 | package mathutil 2 | 3 | 4 | import "math" 5 | 6 | 7 | func function(){ 8 | return 1; 9 | } 10 | 11 | func SqrtUint32(x uint32) uint32 { 12 | return uint32(math.Ceil(math.Sqrt(float64(x)))) 13 | } -------------------------------------------------------------------------------- /src/test/resources/coverage/mathutil/mathutil.go: -------------------------------------------------------------------------------- 1 | package mathutil 2 | 3 | import "math" 4 | 5 | //SqrtUint32 Permet de faire une racine carré sur un uint32 6 | func SqrtUint32(x uint32) uint32 { 7 | return uint32(math.Ceil(math.Sqrt(float64(x)))) 8 | } 9 | -------------------------------------------------------------------------------- /src/test/resources/coverage/mathutil/mathutil_test.go: -------------------------------------------------------------------------------- 1 | package mathutil 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | ) 7 | 8 | func TestSqrtUint32(t *testing.T) { 9 | result1 := SqrtUint32(4) 10 | result2 := math.Sqrt(4.0) 11 | 12 | if uint32(result2) != result1 { 13 | t.Error( 14 | "For 4 and 4.0", 15 | "expected ", 2, 16 | "got", result1, 17 | ) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/resources/coverage/pixel/coverage.out: -------------------------------------------------------------------------------- 1 | mode: set 2 | projectblackwhitego/pixel/pixel.go:20.41,22.2 1 0 3 | projectblackwhitego/pixel/pixel.go:23.56,26.2 2 0 4 | projectblackwhitego/pixel/pixel.go:27.49,34.2 1 0 5 | projectblackwhitego/pixel/pixel.go:36.47,38.2 1 0 6 | -------------------------------------------------------------------------------- /src/test/resources/coverage/pixel/coverage.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/test/resources/coverage/pixel/pixel.go: -------------------------------------------------------------------------------- 1 | package pixel 2 | 3 | import ( 4 | "image" 5 | "image/color" 6 | "projectblackwhitego/util" 7 | ) 8 | 9 | type Pixel struct { 10 | R uint32 11 | G uint32 12 | B uint32 13 | A uint32 14 | } 15 | 16 | type PixelImage struct { 17 | imageRGBA *image.Image 18 | } 19 | 20 | func NewPixel(r, g, b, a uint32) *Pixel { 21 | return &Pixel{r, g, b, a} 22 | } 23 | func NewPixelImage(bounds image.Rectangle) *PixelImage { 24 | img := image.Image(image.NewNRGBA(bounds)) 25 | return &PixelImage{&img} 26 | } 27 | func (pi *PixelImage) Set(x, y int, pix *Pixel) { 28 | (*pi.imageRGBA).(*image.NRGBA).Set(x, y, color.NRGBA{ 29 | util.Uint32toUint8(pix.R), 30 | util.Uint32toUint8(pix.G), 31 | util.Uint32toUint8(pix.B), 32 | util.Uint32toUint8(pix.A), 33 | }) 34 | } 35 | 36 | func (pi *PixelImage) GetImage() *image.Image { 37 | return pi.imageRGBA 38 | } 39 | -------------------------------------------------------------------------------- /src/test/resources/coverage/pixel/pixel_test.go: -------------------------------------------------------------------------------- 1 | package pixel 2 | -------------------------------------------------------------------------------- /src/test/resources/coverage/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/coverage/test -------------------------------------------------------------------------------- /src/test/resources/coverage/test.git/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/coverage/test.git/test -------------------------------------------------------------------------------- /src/test/resources/coverage/util/cover.out: -------------------------------------------------------------------------------- 1 | mode: set 2 | projectblackwhitego/util/util.go:30.33,31.11 1 0 3 | projectblackwhitego/util/util.go:32.2,33.16 1 0 4 | projectblackwhitego/util/util.go:34.2,35.15 1 0 5 | projectblackwhitego/util/util.go:36.2,37.15 1 0 6 | projectblackwhitego/util/util.go:38.2,39.16 1 0 7 | projectblackwhitego/util/util.go:40.2,41.15 1 0 8 | projectblackwhitego/util/util.go:42.2,43.23 1 0 9 | projectblackwhitego/util/util.go:53.24,54.11 1 1 10 | projectblackwhitego/util/util.go:57.2,57.10 1 0 11 | projectblackwhitego/util/util.go:54.11,56.3 1 1 12 | projectblackwhitego/util/util.go:61.24,62.11 1 1 13 | projectblackwhitego/util/util.go:65.2,65.10 1 1 14 | projectblackwhitego/util/util.go:62.11,64.3 1 0 15 | projectblackwhitego/util/util.go:68.38,70.2 1 0 16 | projectblackwhitego/util/util.go:73.61,75.32 1 1 17 | projectblackwhitego/util/util.go:79.2,82.25 4 1 18 | projectblackwhitego/util/util.go:91.2,91.14 1 1 19 | projectblackwhitego/util/util.go:75.32,77.3 1 0 20 | projectblackwhitego/util/util.go:82.25,83.26 1 1 21 | projectblackwhitego/util/util.go:83.26,86.37 3 1 22 | projectblackwhitego/util/util.go:86.37,88.5 1 0 23 | projectblackwhitego/util/util.go:95.49,97.16 2 1 24 | projectblackwhitego/util/util.go:100.2,101.17 2 1 25 | projectblackwhitego/util/util.go:105.2,105.17 1 1 26 | projectblackwhitego/util/util.go:97.16,99.3 1 0 27 | projectblackwhitego/util/util.go:101.17,103.3 1 0 28 | projectblackwhitego/util/util.go:108.54,110.2 1 0 29 | projectblackwhitego/util/util.go:131.68,133.16 2 0 30 | projectblackwhitego/util/util.go:162.2,162.12 1 0 31 | projectblackwhitego/util/util.go:134.2,136.42 2 0 32 | projectblackwhitego/util/util.go:145.3,145.18 1 0 33 | projectblackwhitego/util/util.go:151.2,152.27 1 0 34 | projectblackwhitego/util/util.go:153.2,154.57 1 0 35 | projectblackwhitego/util/util.go:155.2,156.87 1 0 36 | projectblackwhitego/util/util.go:157.2,158.27 1 0 37 | projectblackwhitego/util/util.go:159.2,160.29 1 0 38 | projectblackwhitego/util/util.go:136.42,137.22 1 0 39 | projectblackwhitego/util/util.go:137.22,143.5 1 0 40 | projectblackwhitego/util/util.go:145.18,147.4 1 0 41 | projectblackwhitego/util/util.go:147.4,149.4 1 0 42 | projectblackwhitego/util/util.go:167.57,180.9 4 0 43 | projectblackwhitego/util/util.go:184.2,185.16 2 0 44 | projectblackwhitego/util/util.go:188.2,190.33 2 0 45 | projectblackwhitego/util/util.go:180.9,182.3 1 0 46 | projectblackwhitego/util/util.go:185.16,187.3 1 0 47 | projectblackwhitego/util/util.go:193.40,195.16 2 0 48 | projectblackwhitego/util/util.go:198.2,198.24 1 0 49 | projectblackwhitego/util/util.go:201.2,201.18 1 0 50 | projectblackwhitego/util/util.go:195.16,197.3 1 0 51 | projectblackwhitego/util/util.go:198.24,200.3 1 0 52 | projectblackwhitego/util/util.go:204.39,206.16 2 0 53 | projectblackwhitego/util/util.go:209.2,211.16 3 0 54 | projectblackwhitego/util/util.go:214.2,214.29 1 0 55 | projectblackwhitego/util/util.go:220.2,220.12 1 0 56 | projectblackwhitego/util/util.go:206.16,208.3 1 0 57 | projectblackwhitego/util/util.go:211.16,213.3 1 0 58 | projectblackwhitego/util/util.go:214.29,216.17 2 0 59 | projectblackwhitego/util/util.go:216.17,218.4 1 0 60 | -------------------------------------------------------------------------------- /src/test/resources/coverage/util/coverage.out.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/coverage/util/coverage.out.xml -------------------------------------------------------------------------------- /src/test/resources/coverage/util/coverage.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /src/test/resources/coverage/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "errors" 5 | "image" 6 | "image/gif" 7 | "image/jpeg" 8 | "image/png" 9 | "io" 10 | "os" 11 | "path/filepath" 12 | "strings" 13 | 14 | "golang.org/x/image/bmp" 15 | "golang.org/x/image/tiff" 16 | ) 17 | 18 | // Format is an image file format. 19 | type Format int 20 | 21 | // Image file formats. 22 | const ( 23 | JPEG Format = iota 24 | PNG 25 | GIF 26 | TIFF 27 | BMP 28 | ) 29 | 30 | func (f Format) String() string { 31 | switch f { 32 | case JPEG: 33 | return "JPEG" 34 | case PNG: 35 | return "PNG" 36 | case GIF: 37 | return "GIF" 38 | case TIFF: 39 | return "TIFF" 40 | case BMP: 41 | return "BMP" 42 | default: 43 | return "Unsupported" 44 | } 45 | } 46 | 47 | var ( 48 | // ErrUnsupportedFormat means the given image format (or file extension) is unsupported. 49 | ErrUnsupportedFormat = errors.New("imaging: unsupported image format") 50 | ) 51 | 52 | func falseSquare(a int) int { 53 | return a 54 | } 55 | 56 | //Min retourne le min 57 | func Min(a, b int) int { 58 | if a < b { 59 | return a 60 | } 61 | return b 62 | } 63 | 64 | //Max retourne le max 65 | func Max(a, b int) int { 66 | if a > b { 67 | return a 68 | } 69 | return b 70 | } 71 | 72 | func Uint32toUint8(val uint32) uint8 { 73 | return uint8(val >> 8) 74 | } 75 | 76 | //CompareImage calcule le nombre de pixel de différence entre deux images 77 | func CompareImage(img1 *image.Image, img2 *image.Image) int { 78 | 79 | if img1 == nil || img2 == nil { 80 | return -1 81 | } 82 | 83 | w := (*img1).Bounds().Dx() 84 | h := (*img1).Bounds().Dy() 85 | var count int 86 | for y := 0; y < h; y++ { 87 | for x := 0; x < w; x++ { 88 | r, g, b, _ := (*img1).At(x, y).RGBA() 89 | r2, g2, b2, _ := (*img2).At(x, y).RGBA() 90 | if r != r2 || g != g2 || b != b2 { 91 | count++ 92 | } 93 | } 94 | } 95 | return count 96 | } 97 | 98 | //OpenPng permet d'ouvrir un PNG 99 | func OpenPng(name string) (*image.Image, error) { 100 | f, err := os.Open(name) 101 | if err != nil { 102 | return nil, err 103 | } 104 | in, err2 := png.Decode(f) 105 | if err2 != nil { 106 | return nil, err2 107 | } 108 | 109 | return &in, nil 110 | } 111 | 112 | func IsInBoundaries(img *image.NRGBA, x, y int) bool { 113 | return x >= 0 && x < (*img).Bounds().Dx() && y >= 0 && y < (*img).Bounds().Dy() 114 | } 115 | 116 | // //WritePng permet d'écrire un PNG 117 | // func WritePng(img *image.NRGBA, name string) { 118 | // fout, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE, 0600) 119 | // if err != nil { 120 | // log.Fatal(err) 121 | // } 122 | // defer fout.Close() 123 | // 124 | // if err := png.Encode(fout, img); err != nil { 125 | // fout.Close() 126 | // log.Fatal(err) 127 | // } 128 | // 129 | // if err := fout.Close(); err != nil { 130 | // log.Fatal(err) 131 | // } 132 | // } 133 | 134 | //WritePng permet d'écrire un PNG 135 | func WriteImage(w io.Writer, img image.Image, format Format) error { 136 | var err error 137 | switch format { 138 | case JPEG: 139 | var rgba *image.RGBA 140 | if nrgba, ok := img.(*image.NRGBA); ok { 141 | if nrgba.Opaque() { 142 | rgba = &image.RGBA{ 143 | Pix: nrgba.Pix, 144 | Stride: nrgba.Stride, 145 | Rect: nrgba.Rect, 146 | } 147 | } 148 | } 149 | if rgba != nil { 150 | err = jpeg.Encode(w, rgba, &jpeg.Options{Quality: 95}) 151 | } else { 152 | err = jpeg.Encode(w, img, &jpeg.Options{Quality: 95}) 153 | } 154 | 155 | case PNG: 156 | err = png.Encode(w, img) 157 | case GIF: 158 | err = gif.Encode(w, img, &gif.Options{NumColors: 256}) 159 | case TIFF: 160 | err = tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true}) 161 | case BMP: 162 | err = bmp.Encode(w, img) 163 | default: 164 | err = ErrUnsupportedFormat 165 | } 166 | return err 167 | } 168 | 169 | // Save saves the image to file with the specified filename. 170 | // The format is determined from the filename extension: "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported. 171 | func Save(img image.Image, filename string) (err error) { 172 | formats := map[string]Format{ 173 | ".jpg": JPEG, 174 | ".jpeg": JPEG, 175 | ".png": PNG, 176 | ".tif": TIFF, 177 | ".tiff": TIFF, 178 | ".bmp": BMP, 179 | ".gif": GIF, 180 | } 181 | 182 | ext := strings.ToLower(filepath.Ext(filename)) 183 | f, ok := formats[ext] 184 | if !ok { 185 | return ErrUnsupportedFormat 186 | } 187 | 188 | file, err := os.Create(filename) 189 | if err != nil { 190 | return err 191 | } 192 | defer file.Close() 193 | 194 | return WriteImage(file, img, f) 195 | } 196 | 197 | func Exists(path string) (bool, error) { 198 | _, err := os.Stat(path) 199 | if err == nil { 200 | return true, nil 201 | } 202 | if os.IsNotExist(err) { 203 | return false, nil 204 | } 205 | return true, err 206 | } 207 | 208 | func RemoveContents(dir string) error { 209 | d, err := os.Open(dir) 210 | if err != nil { 211 | return err 212 | } 213 | defer d.Close() 214 | names, err := d.Readdirnames(-1) 215 | if err != nil { 216 | return err 217 | } 218 | for _, name := range names { 219 | err = os.RemoveAll(filepath.Join(dir, name)) 220 | if err != nil { 221 | return err 222 | } 223 | } 224 | return nil 225 | } 226 | -------------------------------------------------------------------------------- /src/test/resources/coverage/util/util2.go: -------------------------------------------------------------------------------- 1 | package util 2 | -------------------------------------------------------------------------------- /src/test/resources/coverage/util/util2_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "testing" 4 | 5 | func TestSkipped2(t *testing.T) { 6 | t.SkipNow() 7 | } 8 | 9 | func TestFailure(t *testing.T) { 10 | t.FailNow() 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/coverage/util/util_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "log" 5 | "testing" 6 | ) 7 | 8 | func TestSkipped(t *testing.T) { 9 | t.SkipNow() 10 | } 11 | 12 | func TestFalseSquare(t *testing.T) { 13 | out := falseSquare(5) 14 | 15 | if out != 25 { 16 | t.Error( 17 | "For 5", 18 | "expected", "25", 19 | "got", out, 20 | ) 21 | } 22 | 23 | } 24 | 25 | func TestMin(t *testing.T) { 26 | out := Min(5, 9) 27 | 28 | if out != 5 { 29 | t.Error( 30 | "For 5,9", 31 | "expected", "5", 32 | "got", out, 33 | ) 34 | } 35 | 36 | } 37 | 38 | func TestMax(t *testing.T) { 39 | out := Max(5, 9) 40 | 41 | if out != 9 { 42 | t.Error( 43 | "For 5,9", 44 | "expected", "9", 45 | "got", out, 46 | ) 47 | } 48 | 49 | } 50 | 51 | func TestCompare(t *testing.T) { 52 | img1, err := OpenPng("../imagetest/Image47.png") 53 | if err != nil { 54 | log.Fatal("erreur test compare") 55 | return 56 | } 57 | 58 | count := CompareImage(img1, img1) 59 | 60 | if count != 0 { 61 | t.Error( 62 | "For Image47.png", 63 | "expected 0", 64 | "got", count, 65 | ) 66 | } 67 | } 68 | 69 | func TestCompare2(t *testing.T) { 70 | img1, err := OpenPng("../imagetest/Image47.png") 71 | img2, err2 := OpenPng("../imagetest/Image47.png") 72 | 73 | if err != nil || err2 != nil { 74 | log.Fatal(err, " ", err2) 75 | return 76 | } 77 | 78 | count := CompareImage(img1, img2) 79 | 80 | if count != 0 { 81 | t.Error( 82 | "For Image47.png", 83 | "expected 0", 84 | "got", count, 85 | ) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/resources/coverage/vendor/fileexcludedinvendordirectory.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/coverage/vendor/fileexcludedinvendordirectory.txt -------------------------------------------------------------------------------- /src/test/resources/gotest/test1_test.go: -------------------------------------------------------------------------------- 1 | func TestAverage(t *testing.T){ 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/test/resources/gotest/test2_test.go: -------------------------------------------------------------------------------- 1 | func TestAverage(t *testing.T){ 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/test/resources/gotest/test_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | ) 6 | 7 | func IAmNotATest(t *testing.T) { 8 | // do something 9 | } 10 | 11 | func TestEasyDef(t *testing.T) { 12 | assert.True(t, true, "Should match") 13 | } 14 | 15 | func TestSpaceDef (t *testing.T) { 16 | assert.True(t, true, "Should match") 17 | } 18 | 19 | func TestNoSpaceDef(t *testing.T){ 20 | assert.True(t, true, "Should match") 21 | } 22 | 23 | func TestTwoLines1 (t *testing.T) 24 | { 25 | assert.True(t, true, "Should match") 26 | } 27 | 28 | func 29 | TestTwoLines2 (t *testing.T) { 30 | assert.True(t, true, "Should match") 31 | } 32 | 33 | func TestNested(t *testing.T) { 34 | t.Parallel() 35 | t.Run("match", func(t *testing.T) { 36 | assert.True(t, true, "Should match") 37 | }) 38 | t.Run("nomatch", func(t *testing.T) { 39 | assert.True(t, true, "Should match") 40 | }) 41 | } 42 | 43 | func (suite *ExampleTestSuite) TestSuite() { 44 | suite.Equal(5, suite.VariableThatShouldStartAtFive) 45 | } 46 | -------------------------------------------------------------------------------- /src/test/resources/grammar/constant_expressions.go: -------------------------------------------------------------------------------- 1 | const a = 2 + 3.0 // a == 5.0 (untyped floating-point constant) 2 | const b = 15 / 4 // b == 3 (untyped integer constant) 3 | const c = 15 / 4.0 // c == 3.75 (untyped floating-point constant) 4 | const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer division) 5 | const Π float64 = 3/2. // Π == 1.5 (type float64, 3/2. is float division) 6 | const d = 1 << 3.0 // d == 8 (untyped integer constant) 7 | const e = 1.0 << 3 // e == 8 (untyped integer constant) 8 | const f = int32(1) << 33 // illegal (constant 8589934592 overflows int32) 9 | const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant) 10 | const h = "foo" > "bar" // h == true (untyped boolean constant) 11 | const j = true // j == true (untyped boolean constant) 12 | const k = 'w' + 1 // k == 'x' (untyped rune constant) 13 | const l = "hi" // l == "hi" (untyped string constant) 14 | const m = string(k) // m == "x" (type string) 15 | const Σ = 1 - 0.707i // (untyped complex constant) 16 | const Δ = Σ + 2.0e-4 // (untyped complex constant) 17 | const Φ = iota*1i - 1/1i // (untyped complex constant) 18 | -------------------------------------------------------------------------------- /src/test/resources/grammar/import_complex_definition.go: -------------------------------------------------------------------------------- 1 | import ( 2 | "package1" 3 | "package2" 4 | "package2" 5 | ) 6 | -------------------------------------------------------------------------------- /src/test/resources/grammar/import_simple_definition.go: -------------------------------------------------------------------------------- 1 | import "apackage" 2 | -------------------------------------------------------------------------------- /src/test/resources/grammar/package_definition.go: -------------------------------------------------------------------------------- 1 | package testpackage 2 | -------------------------------------------------------------------------------- /src/test/resources/grammar/var_definition.go: -------------------------------------------------------------------------------- 1 | var test int = 5 2 | var test2 float32 = 8.6 3 | var test3 string = "a string" 4 | 5 | var test4 int 6 | var test5 float64 7 | var test6 string 8 | 9 | 10 | // https://golang.org/ref/spec#Variables 11 | 12 | var x interface{} // x is nil and has static type interface{} 13 | var v *T // v has value nil, static type *T 14 | x = 42 // x has value 42 and dynamic type int 15 | x = v // x has value (*T)(nil) and dynamic type *T 16 | -------------------------------------------------------------------------------- /src/test/resources/grammar/var_fast_definition.go: -------------------------------------------------------------------------------- 1 | test := 1.0 2 | test2 := "a string" 3 | test3 := 1 -------------------------------------------------------------------------------- /src/test/resources/highlighter/test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | 6 | func oneFunction() { 7 | fmt.Println("do something") 8 | } 9 | 10 | func oneFunctionWithParameter(a int) { 11 | fmt.Println("do something") 12 | } 13 | 14 | func oneFunctionWithParameters(a, b int, c float32) { 15 | fmt.Println("do something") 16 | } 17 | 18 | func oneFunctionWithParametersAndReturn(a, b int, c float32) int { 19 | fmt.Println("do something") 20 | } 21 | func oneFunctionWithParametersAndReturns(a, b int, c float32) (int, float32, string) { 22 | fmt.Println("do something") 23 | } 24 | -------------------------------------------------------------------------------- /src/test/resources/highlighter/testbug1.go: -------------------------------------------------------------------------------- 1 | var testBug1 string = "test\"other" 2 | var testBug1_2 string = "stuff\"other" 3 | -------------------------------------------------------------------------------- /src/test/resources/key.properties: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2017 - Université d'Artois 3 | # 4 | # This file is part of SonarQube Golang plugin (sonar-golang). 5 | # 6 | # Sonar-golang is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Sonar-golang is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with Sonar-golang. If not, see . 18 | # 19 | # Contributors: 20 | # Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | ############################################################################### 22 | #golint\:ExportedType=exported type [a-zA-Z0-9]+ should have comment or be unexported 23 | golint\:FormComment=comment on exported [a-zA-Z0-9]+ [a-zA-Z0-9\.]+ should be of the form "[a-zA-Z\.]+ *\t*..." 24 | golint\:AllCaps=don't use ALL_CAPS in Go names; use CamelCase 25 | golint\:UnderscoreInPackageName=don't use an underscore in package name 26 | golint\:LeadingK=don't use leading k in Go names; [a-zA-Z0-9]+ [a-zA-Z0-9]+ should be [a-zA-Z0-9]+ 27 | golint\:UnderscoreInGoName=don't use underscores in Go names; [a-zA-Z0-9]+ [a-zA-Z0-9_]+ should be [a-zA-Z0-9]+ 28 | golint\:ErrorLastReturn=error should be the last type when returning multiple items 29 | golint\:ErrorEndString=error strings should not be capitalized or end with punctuation or a newline 30 | golint\:ErrorVarName=error var [a-zA-Z0-9]+ should have name of the form [a-zA-Z0-9]+ 31 | golint\:AnnoyingUseExportedType=exported [a-zA-Z0-9]+ [a-zA-Z0-9]+ returns unexported type [a-zA-Z0-9]+, which can be annoying to use 32 | golint\:IfBlockReturn=if block ends with a return statement, so drop this else and outdent its block 33 | golint\:PackageCommentForm=package comment should be of the form \"[a-zA-Z0-9]+...\" 34 | golint\:PackageCommentSpace=package comment should not have leading space 35 | golint\:ReceiverNameConsistent=receiver name [a-zA-Z0-9]+ should be consistent with previous receiver name [a-zA-Z0-9]+ for [a-zA-Z0-9]+ 36 | golint\:ReceiverNameReflection=receiver name should be a reflection of its identity; don't use generic names such as \"this\" or \"self\" 37 | golint\:ReceiverNameNotUnderscore=receiver name should not be an underscore 38 | golint\:DropAssignment=should drop = [a-zA-Z0-9]+ from declaration of var [a-zA-Z0-9]+; it is the zero value 39 | golint\:HavePackageComment=should have a package comment, unless it's in another file for this package 40 | golint\:NotUseBasicType=should not use basic type [a-zA-Z0-9]+ as key in context.WithValue 41 | golint\:NotUseDotImport=should not use dot imports 42 | golint\:Omit2ndValueFromRange=should omit 2nd value from range; this loop is equivalent to `for [a-zA-Z0-9]+ := range ...` 43 | golint\:OmitType=should omit type [a-zA-Z0-9]+ from declaration of var [a-zA-Z0-9]+; it will be inferred from the right-hand side 44 | golint\:ReplaceLintIncDec=should replace [a-zA-Z0-9\-\+=]+ with [a-zA-Z0-9\-\+]+ 45 | golint\:ReplaceSprintf=should replace [a-zA-Z0-9\.]+\\(fmt.Sprintf\\(...\\)\\) with [a-zA-Z0-9]+.Errorf\\(...\\) 46 | golint\:Initialisms=[a-zA-Z0-9]+ [a-zA-Z0-9]+ should be [a-zA-Z0-9]+ 47 | golint\:PackageNames=[a-zA-Z0-9]+ name will be used as [a-zA-Z0-9]+.[a-zA-Z0-9]+ by other packages, and that stutters; consider calling this [a-zA-Z0-9]+ 48 | golint\:BlankImport=a blank import should be only in a main or test package, or have a comment justifying it 49 | golint\:CommentExportedType=comment on exported type [a-zA-Z0-9]+ should be of the form "[a-zA-Z0-9]+ ..." \\(with optional leading article\\) 50 | golint\:ContextContextFirstArg=context.Context should be the first parameter of a function 51 | golint\:ExportedHaveComment=exported [a-zA-Z0-9]+ [a-zA-Z0-9\.]+ should have comment or be unexported 52 | golint\:ExportedHaveComment2=exported [a-zA-Z0-9\.]+ [a-zA-Z0-9\.]+ should have comment[\(\) a-zA-Z0-9]+ or be unexported 53 | golint\:ExportedDeclaration=exported [a-zA-Z0-9]+ [a-zA-Z0-9]+ should have its own declaration 54 | golint\:SpecificSuffix=var [a-zA-Z0-9]+ is of type [a-zA-Z0-9\.]+; don't use unit-specific suffix [a-zA-Z0-9]+ 55 | golint\:StructFieldInitialisms=struct field [a-zA-Z0-9]+ should be [a-zA-Z0-9]+ 56 | gocyclo\:CyclomaticComplexity=cyclomatic complexity [0-9]+ of function [a-zA-Z0-9]+\\(\\) is high \\(> 10\\) 57 | errcheck\:ValueNotChecked=error return value not checked .* 58 | unconvert\:UnnecessaryConversion=unnecessary conversion 59 | structcheck\:UnusedStructField=unused struct field \\w+[\\w\\.]* 60 | gosimple\:ChannelInsteadSelect= 61 | ineffassign\:IneffectualAssignment=ineffectual assignment to [a-zA-Z0-9]+ 62 | gas\:UnhandledErrors=Errors unhandled\.,LOW,HIGH 63 | goimports\:FileNotImported=file is not goimported 64 | vet\:Unreachable=unreachable code 65 | vet\:Shadow=declaration of "[A-Za-z0-9\.]+" shadows declaration at [A-Za-z0-9_\-]+.go:[0-9]+ 66 | vet\:Misuse=possible misuse of unsafe.Pointer 67 | gas\:SQLFormatting=SQL string formatting,MEDIUM,HIGH 68 | gas\:SQLConcatenation=SQL string concatenation,MEDIUM,HIGH 69 | gas\:RSAKeyLength=RSA keys should be at least 2048 bits,MEDIUM,HIGH 70 | gas\:UnsafeCall=Use of unsafe calls should be audited,LOW,HIGH 71 | gas\:UnescapedHTMLTemplates=this method will not auto-escape HTML\. Verify data is well formed\.,MEDIUM,LOW 72 | gas\:WeakCrypto=Use of weak cryptographic primitive,HIGH,HIGH 73 | vet\:Lock=[A-Za-z0-9\.]+ passes lock by value: [A-Za-z0-9\.]+ contains [A-Za-z0-9\.]+ 74 | vet\:FormatingPrintfFamily=possible formatting directive in [A-Za-z0-9\.]+ call 75 | -------------------------------------------------------------------------------- /src/test/resources/profile.properties: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright 2017 - Université d'Artois 3 | # 4 | # This file is part of SonarQube Golang plugin (sonar-golang). 5 | # 6 | # Sonar-golang is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Sonar-golang is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with Sonar-golang. If not, see . 18 | # 19 | # Contributors: 20 | # Thibault Falque (thibault_falque@ens.univ-artois.fr) 21 | ############################################################################### 22 | #golint\:ExportedType=true 23 | golint\:FormComment=true 24 | golint\:AllCaps=true 25 | golint\:UnderscoreInPackageName=true 26 | golint\:LeadingK=true 27 | golint\:UnderscoreInGoName=true 28 | golint\:ErrorLastReturn=true 29 | golint\:ErrorEndString=true 30 | golint\:ErrorVarName=true 31 | golint\:AnnoyingUseExportedType=true 32 | golint\:IfBlockReturn=true 33 | golint\:PackageCommentForm=true 34 | golint\:PackageCommentSpace=true 35 | golint\:ReceiverNameConsistent=true 36 | golint\:ReceiverNameReflection=true 37 | golint\:ReceiverNameNotUnderscore=true 38 | golint\:DropAssignment=true 39 | golint\:HavePackageComment=true 40 | golint\:NotUseBasicType=true 41 | golint\:NotUseDotImport=true 42 | golint\:Omit2ndValueFromRange=true 43 | golint\:OmitType=true 44 | golint\:ReplaceLintIncDec=true 45 | golint\:ReplaceSprintf=true 46 | golint\:Initialisms=true 47 | golint\:PackageNames=true 48 | golint\:BlankImport=true 49 | golint\:CommentExportedType=true 50 | golint\:ContextContextFirstArg=true 51 | golint\:ExportedHaveComment=true 52 | golint\:ExportedHaveComment2=true 53 | golint\:ExportedDeclaration=true 54 | golint\:SpecificSuffix=true 55 | golint\:StructFieldInitialisms=true 56 | gocyclo\:CyclomaticComplexity=true 57 | errcheck\:ValueNotChecked=true 58 | unconvert\:UnnecessaryConversion=true 59 | structcheck\:UnusedStructField=true 60 | gosimple\:ChannelInsteadSelect=true 61 | ineffassign\:IneffectualAssignment=true 62 | gas\:UnhandledErrors=true 63 | goimports\:FileNotImported=true 64 | gas\:SQLFormatting=true 65 | vet\:Shadow=true 66 | gas\:SQLConcatenation=true 67 | gas\:RSAKeyLength=true 68 | gas\:UnsafeCall=true 69 | gas\:UnescapedHTMLTemplates=true 70 | gas\:WeakCrypto=true 71 | vet\:Unreachable=true 72 | vet\:Misuse=true 73 | vet\:Lock=true 74 | vet\:FormatingPrintfFamily=true 75 | -------------------------------------------------------------------------------- /src/test/resources/project/package1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "math" 4 | 5 | //SqrtUint32 Permet de faire une racine carré sur un uint32 6 | func SqrtUint32(x uint32) uint32 { 7 | return uint32(math.Ceil(math.Sqrt(float64(x)))) 8 | } 9 | -------------------------------------------------------------------------------- /src/test/resources/project/package1_test.go: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/project/package1_test.go -------------------------------------------------------------------------------- /src/test/resources/project/test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uartois/sonar-golang/c57c5baba1b546642bfdf56d6be8d4ef06edcbf8/src/test/resources/project/test.py --------------------------------------------------------------------------------