]> source.dussan.org Git - sonarqube.git/commitdiff
DOC embed DEV-space
authorG. Ann Campbell <ann.campbell@sonarsource.com>
Wed, 24 Apr 2019 15:44:23 +0000 (11:44 -0400)
committerSonarTech <sonartech@sonarsource.com>
Wed, 24 Apr 2019 18:21:05 +0000 (20:21 +0200)
15 files changed:
server/sonar-docs/src/images/astSample.png [new file with mode: 0644]
server/sonar-docs/src/images/commit-info-in-code-viewer.png [new file with mode: 0644]
server/sonar-docs/src/images/executable-lines-python-exception.png [new file with mode: 0644]
server/sonar-docs/src/pages/extend/adding-coding-rules.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/adding-scm.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/contributing.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/deploying-to-marketplace.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/developing-plugin.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/executable-lines.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/extend-web-app.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/i18n.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/new-langauges.md [new file with mode: 0644]
server/sonar-docs/src/pages/extend/web-api.md [new file with mode: 0644]
server/sonar-docs/static/SonarQubeNavigationTree.json
server/sonar-docs/static/StaticNavigationTree.json

diff --git a/server/sonar-docs/src/images/astSample.png b/server/sonar-docs/src/images/astSample.png
new file mode 100644 (file)
index 0000000..8f71158
Binary files /dev/null and b/server/sonar-docs/src/images/astSample.png differ
diff --git a/server/sonar-docs/src/images/commit-info-in-code-viewer.png b/server/sonar-docs/src/images/commit-info-in-code-viewer.png
new file mode 100644 (file)
index 0000000..845daf6
Binary files /dev/null and b/server/sonar-docs/src/images/commit-info-in-code-viewer.png differ
diff --git a/server/sonar-docs/src/images/executable-lines-python-exception.png b/server/sonar-docs/src/images/executable-lines-python-exception.png
new file mode 100644 (file)
index 0000000..985e5c0
Binary files /dev/null and b/server/sonar-docs/src/images/executable-lines-python-exception.png differ
diff --git a/server/sonar-docs/src/pages/extend/adding-coding-rules.md b/server/sonar-docs/src/pages/extend/adding-coding-rules.md
new file mode 100644 (file)
index 0000000..7f41857
--- /dev/null
@@ -0,0 +1,381 @@
+---
+title: Adding Coding Rules
+url: /extend/adding-coding-rules/
+---
+
+There are two ways to extend coding rules:
+
+* Writing coding rules using Java via a SonarQube plugin
+* Adding XPath rules directly through the SonarQube web interface
+
+If both are available, the Java API will be more fully-featured than what's available for XPath, and is generally preferable.
+
+[[info]]
+| ![](/images/info.svg) Before implementing a new coding rule, you should consider whether it is specific to your own context or might benefit others. If it might benefit others, you can propose it on the [Community Forum](https://community.sonarsource.com/). If there is shared interest, then it might be implemented for you directly in the related language plugin. It means less maintenance for you, and benefit to others.
+
+## Custom rule support by language
+Languages not listed here don't support custom rules
+
+ &nbsp;  |XPath 1.0|Java|Other
+---|---|---|---
+C#| -  | -  | ![](/images/check.svg)[Importing Issues from Third-Party Roslyn Analyzers (C#, VB.NET)](https://docs.sonarqube.org/pages/viewpage.action?pageId=11640944)
+COBOL| ![](/images/check.svg) | -  | - 
+Flex|![](/images/check.svg) |  -  | - 
+Java |  -  | ![](/images/check.svg) |  - 
+JavaScript |  -  | ![](/images/check.svg) | - 
+PHP |  -  | ![](/images/check.svg)|  - 
+PL/SQL | ![](/images/check.svg) |  -  | - 
+PL/I | ![](/images/check.svg) |  -  | - 
+RPG |  -  | ![](/images/check.svg)| - 
+VB.NET|  -  |  -  | ![](/images/check.svg)[Importing Issues from Third-Party Roslyn Analyzers (C#, VB.NET)](https://docs.sonarqube.org/pages/viewpage.action?pageId=11640944)
+XML |  ![](/images/check.svg) |  -  | - 
+
+
+## Adding coding rules using Java
+Writing coding rules in Java is a six-step process:
+
+* Create a SonarQube plugin.
+* Put a dependency on the API of the language plugin for which you are writing coding rules.
+* Create as many custom rules as required.
+* Generate the SonarQube plugin (jar file).
+* Place this jar file in the SONARQUBE_HOME/extensions/plugins directory.
+* Restart SonarQube server.
+
+See the following pages to see samples and details about how to create coding rules 
+
+* [for COBOL](https://docs.sonarqube.org/display/PLUG/Custom+Rules+for+SonarCOBOL)
+* [for Java](https://docs.sonarqube.org/display/PLUG/Custom+Rules+for+Java)
+* [for JavaScript](https://docs.sonarqube.org/display/PLUG/Custom+Rules+for+SonarJS)
+* [for PHP](https://docs.sonarqube.org/display/PLUG/Custom+Rules+for+PHP)
+* [for RPG](https://docs.sonarqube.org/display/PLUG/Custom+Rules+for+RPG)
+
+
+## Adding coding rules using XPATH
+
+SonarQube provides a quick and easy way to add new coding rules directly via the web interface for certain languages using XPath 1.0 expressions. For XML, which is already immediately accessible to XPath, you can simply write your rules and check them using any of the [freely available tools](http://codebeautify.org/Xpath-Tester) for examining XPath on XML. If you're writing rules for XML, skip down to the Adding your rule to the server section once you've got your rules written.
+
+For other languages how to access a variable, for example, in XPath is less obvious, so we've provided tools.
+
+### Writing an XPath Rule using SSLR Toolkit
+The rules must be written in XPath (version 1.0) to navigate the language's [Abstract Syntax Tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST). For most languages, an SSLR Toolkit is provided to help you navigate the AST. You need to download the `sslr-{language}-toolkit-{version}.jar` file corresponding to the version of your language plugin you have on your SonarQube instance.
+
+Each language's SSLR Toolkit is a standalone application that displays the AST for a piece of code source that you feed into it, allowing you to read the node names and attributes from your code sample and write your XPath expression. Knowing the XPath language is the only prerequisite, and there are a lot of tutorials on XPath online.
+
+The latest version of SSLR Toolkit can be downloaded from following locations:
+
+* [Flex](https://binaries.sonarsource.com/Distribution/sonar-flex-plugin/)
+* [PL/SQL](https://binaries.sonarsource.com/CommercialDistribution/sslr-plsql-toolkit/)
+* [PL/I](https://binaries.sonarsource.com/CommercialDistribution/sslr-pli-toolkit/)
+* [Python](https://binaries.sonarsource.com/Distribution/sslr-python-toolkit/)
+
+For an SSLR preview, consider the following source code sample:
+```
+function HelloWorld(hour) {
+  if (hour) {
+    this.hour = hour;
+  } else {
+    var date = new Date();
+    this.hour = date.getHours();
+  }
+  this.displayGreeting = function() {
+    if (this.hour >= 22 || this.hour <= 5)
+      document.write("Good night, World!");
+    else
+      document.write("Hello, World!");
+  } 
+}
+```
+While parsing source code, SonarQube builds an Abstract Syntax Tree (AST) for it, and the SSLR Toolkit provided for each language will show you SonarQube's AST for a given piece of code. Here's the AST for our sample:
+
+![AST example](/images/astSample.png)
+
+The [XPath](http://en.wikipedia.org/wiki/XPath) language provides a way to write coding rules by navigating this AST, and the SSLR Toolkit for the language will give you the ability to test your new rules against your sample code.
+
+### Adding your Rule to the Server
+Once your new rule is written, you can add it SonarQube:
+
+1. Login as an Quality Profile Administrator
+1. Go to Rules page
+1. Select the Language for which you want to create the XPath rule
+1. Tick the Template criterion and select "Show Templates Only" 
+1. Look for the XPath rule template
+1. Click on it to select it, then use the interface controls to create a new instance
+1. Fill in the form that pops up
+1. Once you've created your rule, you'll need to add it to a Quality Profile and run analysis to see it in action.
+
+
+## Coding rule guidelines
+These are the guidelines that SonarSource uses internally to specify new rules. Rules in community plugins are not required to adhere to these guidelines. They are provided here only in case they are useful.
+
+Note that fields "title", "description" and "message" have a different format when the rule type is "Hotspot".
+
+### Guidelines for Bug, Vulnerability, and Code Smell rules
+#### Titles
+
+* The title of the rule should match the pattern "X should [ not ] Y" for most rules. Note that the "should [ not ]" pattern is too strong for Finding rules, which are about observations on the code. Finding titles should be neutral, such as "Track x".
+* All other things being equal, the positive form is preferred. E.G.
+   * X should Y is preferred to 
+   * X should not Z
+* Titles should be written in plural form if at all possible. E.G.
+   * ![](/images/check.svg)Flibbers should gibbet
+   * ![](/images/cross.svg)A Flibber should gibbet
+* Any piece of code in the rule title should be double-quoted (and not single-quoted).
+* There should be no category/tag prefixed to the rule title, such as "Accessibility - Image tags should have an alternate text attribute"
+* Titles should be as concise as possible. Somewhere around 70 or 80 characters is an ideal maximum, although this is not always achievable.
+
+Noncompliant Title Examples:
+
+* File should not have too many lines of code  // Noncompliant; singular form used
+* Avoid file with too many lines of code  // Noncompliant; doesn't follow "x should (not) y" pattern
+* Too many lines of code  // Noncompliant
+* Don't use "System.(out/err)"  // Noncompliant
+* Parameters in an overriding virtual function should either use the same default arguments as the function they override, or not specify any default arguments  // Noncompliant; waaaay too long
+
+Compliant Solutions:
+
+* Files should not have too many lines of code  
+* "System.(out/err)" should not be used to log messages
+* Overriding virtual functions should not change parameter defaults
+
+Starting with the subject, such as "Files", will ensure that all rules applying to files will be grouped together.
+
+#### Descriptions
+Rule descriptions should contain the following sections in the listed order:
+
+* **Rationale** (unlabeled) - explaining why this rule make sense. 
+If it's not absolutely clear from the rationale what circumstances will cause an issue to be raised, then this section should end with "This rule raises an issue when \[ insert circumstances here ]".
+* **Noncompliant Code Example** - providing some examples of issues
+   * Ideally, the examples should depend upon the default values of any parameters the rule has, and these default values should be mentioned before the code block. This is for the benefit of users whose rule parameters are tuned to something other than the default values. E.G.
+With a parameter of: <code>*:.*log4j.*</code>
+   * The lines in these code samples where issues are expected should be marked with a "Noncompliant" comment
+   * "Compliant" comments may be used to help demonstrate the difference between what is and is not allowed by the rule
+   * It is acceptable to omit this section when demonstrating noncompliance would take too long, e.g. "Classes should not have too many lines of code"
+* **Compliant Solution** - demonstrating how to fix the previous issues. Good to have but not required for rules that detect bugs. 
+   * There is no need to mark anything "Compliant" in the Compliant Solution; everything here is compliant by definition
+   * It is acceptable to omit this section when there are too many equally viable solutions.
+* **Exceptions** (optional) - listing and explaining some specific use cases where no issues are logged even though some might be expected. Note that this is sometimes incorporated into the rationale, instead.
+* **See** (optional) - listing references and/or links to external standards like MISRA, SEI, CERT, &etc.
+Deprecated (optional): listing replacement rules with links
+
+Code samples for COBOL should be in upper case. 
+
+When displayed in SonarQube, any code or keywords in the description should be enclosed in <code> tags. For descriptions written in JIRA, this means using double curly braces (`{{` and `}}`) to enclose such text. They will be translated in the final output.
+
+#### Messages
+Issue messages should contain the remediation message for bug and quality rules. For potential-bug rules, it should make it explicit that a manual review is required. It should be in the imperative mood ("Do x"), and therefore start with a verb.
+
+An issue message should always end with a period ('.') since it is an actual sentence, unless it ends with a regular expression, in which case the regular expression should be preceded by a colon and should end the message.
+
+Any piece of code in the the rule message should be double-quoted (and not single-quoted). Moreover, if an issue is triggered because a number was above a threshold value, then both the number and the threshold value should be mentioned in the issue message. 
+
+Sample messages:
+
+* Remove or refactor this useless "switch" statement. // Compliant
+* This "switch" statement is useless and should be refactored or removed. // Noncompliant
+* Every "switch" statement shall have at least one case-clause. // Noncompliant
+* Rename this variable to comply with the regular expression: [a-z]+  // Compliant
+
+[[collapse]]
+| ## Sample Specification
+| ### Generic exceptions should not be thrown
+|
+| Using generic exceptions such as `Error`, `RuntimeException`, `Throwable`, and `Exception` prevents calling methods from handling true, system-generated exceptions differently than application-generated errors.
+| 
+| **Noncompliant Code Example**  
+| ```
+| With the default regular expression [a-z][a-zA-Z0-9]+:
+| 
+| try { /* ... */ } catch (Exception e) { LOGGER.info("context"); } // Noncompliant; exception is lost
+| try { /* ... */ } catch (Exception e) { LOGGER.info(e); } // Noncompliant; context is required
+| try { /* ... */ } catch (Exception e) { LOGGER.info(e.getMessage()); } // Noncompliant; exception is lost (only message is preserved)
+| try {
+| /* ... */
+| } catch (Exception e) { // Noncompliant - exception is lost
+| throw new RuntimeException("context");
+| }
+| ```
+|
+| **Compliant Solution**  
+| ```
+| try { /* ... */ } catch (Exception e) { LOGGER.info("context", e); }
+| try {
+| /* ... */
+| } catch (Exception e) {
+| throw new RuntimeException("context", e);
+| }
+| ```
+| **Exceptions**  
+| Generic exceptions in the signatures of overriding methods are ignored.
+| ```
+| @Override
+| public void myMethod() throws Exception {...}
+| ```
+| **See**  
+| * MISRA C:2004, 4.5.2
+| * MITRE, [CWE-580](http://cwe.mitre.org/data/definitions/580.html) - clone() Method Without super.clone()
+|
+| **See also**  
+| S4567 - Rule title here
+
+### Guidelines for Hotspot rules
+
+See [RSPEC-4721](https://jira.sonarsource.com/browse/RSPEC-4721) for an example of Hotspot rule.
+
+#### Titles
+* The title should start with a verb in the present participle form (-ing)
+* The title should end with "is security-sensitive"
+
+Noncompliant Title Examples:
+
+*  Avoid executing OS commands
+
+Compliant Solution:
+
+* Executing OS commands is security-sensitive
+* Deserializing objects from an untrusted source is security-sensitive
+
+#### Descriptions
+Rule descriptions should contain the following sections in the listed order:
+
+* **Rationale** (unlabeled) - explaining why this rule make sense.
+   * It starts with a copy of the title. The "is security sensitive" part can be replaced with "can lead to ...<DESCRIBE RISK>" when there is one risk and it is easy to describe in a short manner.
+   * Next is added the phrase "For example, it has led in the past to the following vulnerabilities:".
+   * Next is a list of CVE links formatted as bullet points. Each CVE should point to their description on the (Example: CVE-2018-12465).
+* **Ask Yourself Whether** - listing a set of questions which the developer should ask herself/himself.
+   * Those questions should check if the context in which the code is makes it dangerous.
+For example, if some code enables a user to insert custom data the database, one of the questions could be: Is the user input sanitized?
+   * Some additional questions can be added to remind the developer that there might not be a need for this code.
+For example, if some code enables a user to send and then execute custom code, the question could be: Does the user really need to execute code dynamically?
+   * This section ends with "You are at risk if you answered yes to any of those questions." with an asterisk marking the corresponding questions if it is not the case for all of them.
+* **Recommended Secure Coding Practices** - describing all the ways to mitigate the risk.
+   * It usually contains a mix of all the advices provided by OWASP rules.
+   * Add detailed solutions whenever possible.
+* one of the following:
+   * **Noncompliant Code Example** - same as for Bug, Vulnerability and Code Smell rules.
+some code can be added to give an example of dangerous context. For example: putting a password in an insecure cookie.
+   * **Questionable Code Example** - use this instead of "Noncompilant code example" when the Hotspot highlights some code which is not dangerous but might be the source of some vulnerability. Example: an opening Socket.
+* **See** (optional) -  same as for Bug, Vulnerability and Code Smell rules.
+* **Deprecated** (optional) -  listing replacement rules with links.
+
+Guidelines regarding COBOL, keywords and code are the same as for other rules.
+
+#### Messages
+Most of the time you can paraphrase the title:
+* start the sentence with "Make sure that"
+* replace "is security-sensitive" with "is safe here"
+
+However for some rules it can make sense to change the title. See the examples below: 
+
+* Title: Executing OS commands is security-sensitive
+   * Message: make sure that executing this OS command is safe here.
+* Title: Delivering code in production with debug mode activated is security-sensitive
+   * Message: Make sure this debug mode is deactivated before delivering the code in production.
+
+### Guidelines applicable to all rules
+#### See/References
+When a reference is made to a standards specification, e.g. MISRA, the following steps must also be taken:
+
+* add any related tags, such as: security, bug, &etc.
+* add the relevant standard-related tag/label such as cwe, misra, etc. (If you forget, the overnight automation will remember for you.) 
+* update the appropriate field on the References tab with the cited id. (If you forget, the overnight automation will remember for you.) 
+
+If needed, references to other rules should be listed under a "See also" heading. If a "See" heading exists in the rule, then the "See also" title should be at the h3 level. Otherwise, use an h2 for it.
+
+Other rules should be linked to only if they are related or contradictory (such as a pair of rules about where `{` should go).
+
+Why list references to other rules under "see also" instead of "see"? The see section is used to support the current rule, and one rule cannot be used as justification for another rule. 
+
+#### Rule Type
+Now that you've fleshed out the description, you should have a fairly clear idea of what type of rule this is, but to be explicit:
+
+**Bug** - Something that's wrong or potentially wrong. 
+
+**Code Smell** - Something that will confuse a maintainer or cause her to stumble in her reading of the code.
+
+**Vulnerability** - Something that has a high chance of being exploited by an attacker.
+
+**HotSpot** - Something that could result in a vulnerability depending on the context in which this code is present. 
+
+Sometimes the line between Bug and Code Smell is fuzzy. When in doubt, ask yourself: "Is code that breaks this rule doing what the programmer probably intended?" If the answer is "probably not" then it's a Bug. Everything else is a Code Smell.
+
+#### Default severities
+When assessing the default severity of a rule, the first thing to do is ask yourself "what's the worst thing that could happen?" In answering, you should factor in Murphy's Law without predicting Armageddon.
+
+Once you have your answer, it's time to assess whether the Impact and Likelihood of the Worst Thing are High or Low. To do that, ask yourself these specific questions:
+
+Vulnerability
+* Impact: Could the exploitation of the vulnerability result in significant damage to your assets or your users? (Yes = High)
+* Likelihood: What is the probability a hacker will be able to exploit the issue?
+
+Bug
+* Impact: Could the bug cause the application to crash or corrupt stored data?
+(Languages where an error can cause program termination: COBOL, Python, PL/SQL, RPG.) 
+* Likelihood: What is the probability the worst will happen?
+
+Code Smell
+* Impact: Could the Code Smell lead a maintainer to introduce a bug?
+* Likelihood: What is the probability the worst will happen?
+
+Once you have your Impact and Likelihood assessments, the rest is easy:
+
+&nbsp;| impact|likelihood
+---|---|---
+Blocker|![](/images/check.svg)|![](/images/check.svg)
+Critical|![](/images/check.svg)|![](/images/cross.svg)
+Major|![](/images/cross.svg)|![](/images/check.svg)
+Minor|![](/images/cross.svg)|![](/images/cross.svg)
+
+#### Tags
+Rules can have 0-n tags, although most rules should have at least one. Many of the common-across-languages tags are described in [the issues docs](/user-guide/issues/).
+
+#### Evaluation of the remediation cost
+For most rules, the SQALE remediation cost is constant per issue. The goal of this section is to help defining the value of this constant and to unify the way those estimations are done to prevent having some big discrepancies among language plugins. 
+
+First step, classify the effort to do the remediation :
+
+1. TRIVIAL
+No need to understand the logic and no potential impact. 
+Examples: remove unused imports, replace tabulations by spaces, remove call to System.out.println() used for debugging purpose, ...
+1. EASY
+No need to understand the logic but potential impacts. 
+Examples: rename a method, rename a parameter, remove unused private method, ...
+1. MEDIUM
+Understanding the logic of a piece of code is required before doing a little and easy refactoring (1 or 2 lines of code). But understanding the big picture is not required.
+Examples : CURSORs should not be declared inside a loop, EXAMINE statement should not be used, IF should be closed with END-IF, ...
+1. MAJOR
+Understanding the logic of a piece of code is required and it's up to the developer to define the remediation action.
+Examples: Too many nested IF statements, Methods should not have too many parameters, UNION should not be used in SQL SELECT statements, Public java method should have a javadoc, Avoid using deprecated methods, ...
+1. HIGH
+The remediation action might lead to locally impact the design of the application.
+Examples: Classes should not have too many responsibilities, Cobol programs should not have too many lines of code, Architectural constraint, ...
+1. COMPLEX
+The remediation action might lead to impact the overall design of the application.
+Examples: Avoid cycles between packages, ...
+
+Then use the following table to get the remediation cost according to the required remediation effort and to the language:
+
+&nbsp;|Trivial|Easy|Medium|Major|High|Complex
+---|---|---|---|---|---|---
+ABAP, COBOL, ...| 10min | 20min | 30min | 1h | 3h | 1d 
+Other languages| 5min |10min|20min|1h|3h|1d
+
+For rules using either the "linear" or "linear with offset" remediation functions, the "Effort To Fix" field must be fed on each issue and this field is used to compute the remediation cost.  
+
+#### Issue location(s) and highlighting
+For any given rule, highlighting behavior should be consistent across languages within the bounds of what's relevant for each language.
+
+When possible, each issue should be raised on the line of code that needs correction, with highlighting limited to the portion of the line to be corrected. For example:
+
+* an issue for a misnamed method should be raised on the line with the method name, and the method name itself should be highlighted.
+
+When correcting an issue requires action across multiple lines, the issue should be raised on the the lowest block that encloses all relevant lines. For example an issue for:
+
+* method complexity should be raised on the method signature
+* method count in a class should be raised on the class declaration
+
+When an issue could be made clearer by highlighting multiple code segments, such as a method complexity issue, additional issue locations may be highlighted, and additional messages may optionally be logged for those locations. In general, these guidelines should be followed for secondary issue locations:
+
+* highlight the minimum code to show the line's contribution to the issue. 
+* avoid using an additional message if the secondary location is likely to be on the same issue as the issue itself. For example: the rule "Parameters should be final" will raise an issue on the method name, and highlight each non-final parameter. Since all locations are likely to be on the same line, additional messages would only confuse the issue.
+* don't write a novel. The message for a secondary location is meant to be a hint to push the user in the right direction. Don't take over the interface with a narrative.
+
diff --git a/server/sonar-docs/src/pages/extend/adding-scm.md b/server/sonar-docs/src/pages/extend/adding-scm.md
new file mode 100644 (file)
index 0000000..4004ba2
--- /dev/null
@@ -0,0 +1,12 @@
+---
+title: Supporting SCM Providers
+url: /extend/adding-scm/
+---
+SonarQube Scanner uses information from the project's SCM, if available, to:
+
+* Assign a new issue to the person who introduced it. The last committer on the related line of code is considered to be the author of the issue. 
+* Estimate the coverage on new code, including added and changed code, on the new code period. 
+* Display the most recent commit on each line the code viewer.
+![Commit info is available from the margin of the code viewer](/images/commit-info-in-code-viewer.png)
+
+The only required SCM command is "blame", which gets the last committer of each line for a given file. This command is executed by a SonarQube plugin through the extension point  org.sonar.api.batch.scm.ScmProvider. See the multiple existing plugins, for instance [Git](https://docs.sonarqube.org/display/SONAR/Git+Integration), for more details.
diff --git a/server/sonar-docs/src/pages/extend/contributing.md b/server/sonar-docs/src/pages/extend/contributing.md
new file mode 100644 (file)
index 0000000..734c8a5
--- /dev/null
@@ -0,0 +1,27 @@
+---
+title: Contributing
+url: /extend/contributing/
+---
+
+Please be aware that we are not actively looking for feature contributions to SonarQube itself because it's extremely difficult for someone outside SonarSource to comply with our roadmap and expectations. Therefore, we typically only accept minor cosmetic changes and typo fixes for SonarQube, but we do happily welcome contributions to the other open source projects under the SonarSource umbrella. 
+
+
+## General guidelines
+* Choose an open ticket in [JIRA](https://jira.sonarsource.com/secure/Dashboard.jspa) or propose your change on the [SonarQube Community Forum](https://groups.google.com/forum/#!forum/sonarqube) - the discussion there is likely to result in an open JIRA ticket. ;-)
+* Use the SonarSource conventions, which you'll find neatly packaged here: https://github.com/SonarSource/sonar-developer-toolset#the-almost-unbreakable-build
+* Use pull requests to submit your work
+
+## New rule implementations in existing plugins
+* Start from an existing [RSpec](https://jira.sonarsource.com/browse/RSPEC-1973?filter=10375) (Rule Specification) that lists your language of interest in the "Targeted languages" field. 
+   * If the RSpec you're interested in doesn't target the language where you want to implement it, raise the question on the Community Forums .
+   * If no RSpec exists for the rule you want to implement, raise the question on the [Community Forum](https://community.sonarsource.com/).
+* Put your rule implementation class in the [language]-checks (e.g. java-checks, javascript-checks, &etc.) module, in the checks sub-package
+* The naming convention for implementation classes is [A-Z][A-Za-z]+Check.java. (Yes, put "Check" in the name too.) The class name should be descriptive and not reflect the rule key. E.G. FindBadCodeCheck.java, not S007.java.
+* A good way to get started on a rule implementation is to look at the implementations of rules that do similar things.
+* During development there's no need to load the plugin in a server to test your implementation, use the rule's unit test for that.
+* For a complete implementation, make sure all of the following are done:
+   * create HTML description file and metadata file
+   * write test class
+   * register the rule in CheckList.java
+   * add the rule to the profile used for the integration test in `profile.xml`
+   * run the integration test and add any new issues to the set of expected issues 
diff --git a/server/sonar-docs/src/pages/extend/deploying-to-marketplace.md b/server/sonar-docs/src/pages/extend/deploying-to-marketplace.md
new file mode 100644 (file)
index 0000000..a924717
--- /dev/null
@@ -0,0 +1,194 @@
+---
+title: Deploying to the Marketplace
+url: /extend/deploying-to-marketplace/
+---
+
+If you have developed a SonarQube plugin, and it meets the requirements, we can even add it in the [SonarQube Marketplace](/instance-administration/marketplace/).
+
+## Requirements
+If your plugin meets the following requirements, then you can ask SonarSource (via the [Community Forum](https://community.sonarsource.com/c/plugins)) to reference your plugin in the [SonarQube Marketplace](/instance-administration/marketplace/):
+
+1. Your plugin is open-source
+   1. Source is freely accessible
+   1. The license is a known FLOSS one (check [the list provided by the Open Source Initiative](http://opensource.org/licenses))
+   1. There's a public issue tracking system
+   1. Documentation is available online in English
+   1. Binaries of each version are accessible somewhere
+1. Releases follow open source conventions. For each release, the following must be available:
+   1. release notes that reflect all significant changes in the version
+   1. plugin jar
+1. The key of your plugin must be:
+   1. short and unique
+   1. lowercase (no camelcase)
+   1. composed only of [a-z0-9]
+   1. related to the name of your plugin
+   1. not just the name of a language (e.g. cannot be java, rust, js/javascript, ...)  
+   examples of good keys: motionchart, communityphp, scmactivity
+1. The description of your plugin must not be misleading in terms of content (the code needs to do pretty much what the name and description say it does). 
+1. On initial entry into the Marketplace, SonarSource staff will test the plugin to verify reasonable functionality and quality. SonarSource staff must be provided with the necessary means to do this testing *without* the need to sign any agreements or fill out any forms. Ideally, the means to do this testing will be made available to the community at large, with the same lack of restrictions.
+1. Your plugin does not compete with existing or soon-to-be-released SonarSource products (sorry, but we gotta pay the bills somehow).
+1. It is analyzed on [SonarCloud](https://sonarcloud.io/) and the quality gate is green when doing a release.
+1. It is compatible with the platform requirements (e.g. it runs on the minimum listed JRE).
+1. If your plugin adds analysis of a language which is not analyzed by any SonarSource analyzer you must provide the NCLOC and NCLOC_DATA metrics, which are both required to make the user experience within SonarQube consistent. You can take a look at how those metrics are provided by SonarJava (NCLOC, NCLOC_DATA). 
+1. Last but not least: your plugin must be aligned with the goal of the SonarQube platform: management of the technical debt and the quality of the code.  
+To be more precise: every feature of SonarQube is tied to the code, so if your plugin provides data that can't be attached to a source or a test file, then there are chances that your plugin won't be accepted in the Marketplace
+
+If your plugin meets these requirements, feel free to start a new thread on the Community Forum requesting inclusion. This thread should include:
+
+* plugin description
+* plugin home page url
+* plugin project homepage on SonarCloud
+* the link to a PR adding a file for your plugin to the sonar-update-center-properties repo, and the elements of a "new release" email listed below.
+
+[[info]]
+| ![](/images/info.svg) We reserve the right to exclude from the Marketplace plugins that we feel would be a dis-service to the community.
+
+## Announcing new releases
+When you've got a new release that should be published in the Marketplace, please:
+
+* create a PR on the [sonar-update-center-properties repo](https://github.com/SonarSource/sonar-update-center-properties) updating the file for your plugin with the data for your new release
+* start a new topic on the Community Forum with the following information:
+   * Subject: [NEW RELEASE] Plugin Name & version
+   * Body contains:
+      * Short description: a few words about what's new in this version.
+      * SonarQube compatibility: unchanged or specific versions.
+      * Link to SonarCloud project dashboard so that we can check the quality gate status
+      * Link to your PR
+   * If it is the first release of the plugin, please mention that the plugin should be added to the Plugin Library page. (Otherwise, we're likely to forget!)
+
+Once this thread is created, someone from SonarSource will review your PR and perform the manual steps to make the version available in the Marketplace.
+
+
+## How to fill in the `sonar-update-center-properties` files
+
+### Initial creation
+
+#### Create file
+In https://github.com/SonarSource/sonar-update-center-properties
+
+File name should correspond to plugin's `pluginKey` and end with a `.properties` extension. Plugin key is set in the plugin module's pom (not the top-level pom):
+
+* Explicitly in a `sonar.pluginKey` property. This is the first choice / preferred
+* Implicitly by the artifactId:
+   * `sonar-{pluginKey}-plugin`
+   * when the `sonar-x-plugin` pattern is not used for the artifactId, the plugin key will be the whole artifact id.
+
+#### Populate file
+Provide the following meta values:
+
+* `category` - one of: Coverage, Developer Tools, External Analyzers, Governance, Integration, Languages, Localization, Visualization/Reporting
+* `description`
+* `homepageUrl`
+* `archivedVersions`=\[ leave this blank for now ]
+* `publicVersions`=\[versionId] 
+* `defaults.mavenGroupId`=\[the Maven `groupId`]
+* `defaults.mavenArtifactId`=\[value of the top-level `artifactId`]
+
+For the initially listed version create the following block:
+
+* `[versionId].description`=\[free text. Spaces allowed. No quoting required]
+* `[versionId].sqVersions`=\[compatibility information. See 'Filling in sqVersions compatibility ranges' below]
+* `[versionId].date`=\[release date with format: YYYY-MM-DD]
+* `[versionId].changelogUrl`=
+* `[versionId].downloadUrl`=
+
+The full list of meta information that can be provided (potentially overriding pom file values) can be found on [GitHub](https://github.com/SonarSource/sonar-update-center/blob/master/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Plugin.java#L154).
+
+
+#### Register file
+Add file name (without `.properties` extension) to `plugins` value in https://github.com/SonarSource/sonar-update-center-properties/blob/master/update-center-source.properties
+
+
+### Updating for new releases
+Create a new block in the file with this format: 
+
+* `[versionId].description`=\[free text. Spaces allowed. No quoting required]
+* `[versionId].sqVersions`=\[compatibility information. See 'Filling in sqVersions compatibility ranges' below]
+* `[versionId].date`=\[release date with format: YYYY-MM-DD]
+* `[versionId].changelogUrl`=
+* `[versionId].downloadUrl`=
+Add `[versionId]` to the `publicVersions` list. Move to `archivedVersions` any versions with identical compatibility. See also 'Filling in sqVersions, publicVersions, and archivedVersions' below
+
+
+### Filling in `sqVersions`, `publicVersions` and `archivedVersions`
+
+The global field `publicVersions` is a comma-delimited list of plugin versions which should be offered to the user in the Marketplace and listed in the Plugin Version Matrix.
+
+* Compatibility of Public versions cannot overlap
+* Multiple versions can be in publicVersions if the versions of SonarQube they are compatible with do not overlap. 
+
+The global field `archivedVersions` is a comma-delimited list of no-longer-preferred plugin versions. If a user has an archived version of a plugin installed, the Marketplace will offer an upgrade to the relevant public version. Upgrades will not be offered for plugin versions which are not found in `archivedVersions`.
+
+* Compatibility of Archived versions can overlap
+* If new version and previous version are compatible with the same versions of SonarQube, move the previous version into `archivedVersions`.
+
+The `sqVersions` field of a release block gives the versions of SonarQube with which the plugin version is compatible. 
+
+* Compatibility can be with a range, with a single version, or with a list of versions / ranges
+* Compatibility is generally listed as a range in the form of [start,end]
+* The value of start should be a SonarQube version number. 
+* The value used for end may either be a version number or the special string `LATEST`.
+* Only one version of a plugin can be compatible with `LATEST`, and it must be the most recent release
+* Compatibility of public versions cannot overlap, so if necessary edit the range end for the older version to stop just before the newer version's compatibility starts. 
+* You can use a wildcard at the end of a range, but not at the beginning.
+   * ![](/images/check.svg) `[6.7,6.7.*]`
+   * ![](/images/cross.svg) `[6.7.*,LATEST]`
+* Multiple entries in a compatibility list should be comma-delimited, E.G. `5.5,[6.7,6.7.*],[7.3,LATEST]`
+
+## Suggestions to manage your plugin development
+A project hosted in a GitHub repository can easily meet the requirements:
+
+* Sources are on Git - and you can easily configure them to be built by Travis CI
+* GitHub Issues can be used as a bug tracking system
+* GitHub Wiki or `README.md` can be used to write the documentation
+* GitHub Releases can be used to publish your binaries
+
+You can obviously use the [Community Forum](https://community.sonarsource.com/c/plugins) to ask for feedback on your plugin. You may want to post an RFF (Request for Feedback) before a release although it is not required. If you do, please close the thread before final release with a "feedback period closed" notice.
+
+
+## Plugin deprecation
+
+Occasionally, there's a need to deprecate a plugin. Typically for one or more of the following reasons:
+
+* the functionality is obsolete or relies on deprecated platform functionality.
+* It's no longer maintained by its authors and is buggy.
+* It's no longer compatible with supported versions of the SonarQube platform.
+
+In such case, the plugin is removed from the Marketplace.
+
+## FAQ
+**Q.** What should the release candidate announcement look like?  
+This is up to you, but ideally, it will contain a:
+* link to download the RC
+* link to the version change log 
+* deadline for feedback
+
+Also, you should probably mention the contributors to the version if you didn't handle it solo.
+
+**Q.** How long should the feedback period be?  
+Again, that's up to you; it's your plugin. At SonarSource, when we put out a Release Candidate (we don't always & its optional for you too), we use a minimum 72 hour feedback period (with variations for holidays, weekends, and significant feedback).
+
+**Q.**  Who can give feedback?  
+Anyone! In fact, the more feedback the better. That's what makes developing in a community so wonderful. We just ask that when you have feedback, you keep it polite and respectful.
+
+**Q.**  What if I don't get any feedback on my release candidate?  
+You have two choices: agitate for more attention or consider no news to be good news and proceed with your release.
+
+**Q.**  What if I get feedback that should block the release?  
+The normal course of action here is to address the feedback and put out another release candidate. Typically, you would extend the feedback period to give people time to test the new version.
+
+**Q.**  What happens when the feedback period is over?  
+If you didn't get any feedback that you feel should block the release, then send a "period closed" notification on the same thread, perform the release, and in a separate thread ask that the new version be added to the Marketplace.
+
+**Q.**  Should the initial release of a plugin be handled any differently than subsequent releases?  
+Not necessarily, although it's probably more critical to get feedback on an initial release. So if there's no response within the initial feedback period, you should probably agitate for more attention, instead of assuming that no news is good news. It's up to you, though.
+
+**Q.**  Who performs the release process?  
+You do.
+
+**Q.**  Where should the jars be posted for download?  
+Up to you. If you're using GitHub to host your source code, then the easiest thing to do is create a project release and post downloads there.
+
+**Q.**  What should the release notes look like?  
+In the best case, it will be a publicly accessible list of work tickets handled in the version, similar to what you can get from Jira or GitHub Issues. At minimum, it will be an outline of the work done. In either case, it must reflect all significant changes.
diff --git a/server/sonar-docs/src/pages/extend/developing-plugin.md b/server/sonar-docs/src/pages/extend/developing-plugin.md
new file mode 100644 (file)
index 0000000..05cc7ac
--- /dev/null
@@ -0,0 +1,506 @@
+---
+title: Developing a plugin
+url: /extend/developing-plugin/
+---
+
+## Building your plugin
+
+### Prerequisites
+To build a plugin, you need Java 8 and Maven 3.1 (or greater). Gradle can also be used thanks to https://github.com/iwarapter/gradle-sonar-packaging-plugin. Note that this Gradle plugin is not officially supported by SonarSource.
+
+### Create a Maven Project
+The recommended way to start is by duplicating the plugin example project: https://github.com/SonarSource/sonar-custom-plugin-example.
+
+If you want to start the project from scratch, use the following Maven pom.xml template:
+
+[[collapse]]
+| ## pom.xml
+| ```
+| <?xml version="1.0" encoding="UTF-8"?>
+| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+|   <modelVersion>4.0.0</modelVersion>
+|   <groupId>YOUR_GROUP_ID</groupId>
+|   <!-- it's recommended to follow the pattern "sonar-{key}-plugin", for example "sonar-php-plugin" -->
+|   <artifactId>YOUR_ARTIFACT_ID</artifactId>
+|   <version>YOUR_VERSION</version>
+|   
+|   <!-- this is important for sonar-packaging-maven-plugin -->
+|   <packaging>sonar-plugin</packaging>
+|  
+|   <dependencies>
+|     <dependency>
+|       <groupId>org.sonarsource.sonarqube</groupId>
+|       <artifactId>sonar-plugin-api</artifactId>
+|       <!-- minimal version of SonarQube to support. -->
+|       <version>6.7</version>
+|       <!-- mandatory scope -->
+|       <scope>provided</scope>
+|     </dependency>
+|   </dependencies>
+|  
+|   <build>
+|     <plugins>
+|       <plugin>
+|         <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
+|         <artifactId>sonar-packaging-maven-plugin</artifactId>
+|         <version>1.18.0.372</version>
+|         <extensions>true</extensions>
+|         <configuration>
+|           <!-- the entry-point class that extends org.sonar.api.SonarPlugin -->
+|           <pluginClass>com.mycompany.sonar.reference.ExamplePlugin</pluginClass>
+|            
+|           <!-- advanced properties can be set here. See paragraph "Advanced Build Properties". -->
+|         </configuration>
+|       </plugin>
+|     </plugins>
+|   </build>
+| </project>
+| ```
+
+### Build
+To build your plugin project, execute this command from the project root directory:  
+`mvn clean package`  
+The plugin jar file is generated in the project's `target/` directory.
+
+### Deploy
+**"Cold" Deploy**  
+The standard way to install the plugin for regular users is to copy the JAR artifact, from the `target/` directory  to the `extensions/plugins/` directory of your SonarQube installation then start the server. The file `logs/sonar.log` will then contain a log line similar to:  
+`Deploy plugin Example Plugin / 0.1-SNAPSHOT`  
+Scanner extensions such as sensors are immediately retrieved and loaded when scanning source code. 
+
+### Debug
+**Debugging web server extensions**  
+
+1. Edit conf/sonar.properties and set: `sonar.web.javaAdditionalOpts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000`
+1. Install your plugin by copying its JAR file to extensions/plugins
+1. Start the server. The line `Listening for transport dt_socket at address: 5005` is logged in  `logs/sonar.log`.
+1. Attach your IDE to the debug process (listening on port 8000 in the example)
+
+**Debugging compute engine extensions**  
+Same procedure as for web server extensions (see previous paragraph), but with the property: `sonar.ce.javaAdditionalOpts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000`
+
+**Debugging scanner extensions**  
+```
+export SONAR_SCANNER_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000"
+cd /path/to/project
+sonar-scanner 
+```
+When using the Scanner for Maven, then simply execute:
+```
+cd /path/to/project
+mvnDebug sonar:sonar
+# debug port is 8000
+```
+
+### Advanced Build Properties
+Plugin properties are defined in the file `META-INF/MANIFEST.MF` of the plugin .jar file.
+
+Most of them are defined through the `<configuration>` section of the [sonar-packaging-maven-plugin](https://jira.sonarsource.com/browse/PACKMP). Some are taken from standard pom nodes Effective values are listed at the end of the build log:
+```
+[INFO] --- sonar-packaging-maven-plugin:1.15:sonar-plugin (default-sonar-plugin) @ sonar-widget-lab-plugin ---
+[INFO] -------------------------------------------------------
+[INFO] Plugin definition in Marketplace
+[INFO]     Key: widgetlab
+[INFO]     Name: Widget Lab
+[INFO]     Description: Additional widgets
+[INFO]     Version: 1.9-SNAPSHOT
+[INFO]     Entry-point Class: org.codehaus.sonar.plugins.widgetlab.WidgetLabPlugin
+[INFO]     Required Plugins:
+[INFO]     Use Child-first ClassLoader: false
+[INFO]     Base Plugin:
+[INFO]     Homepage URL: https://redirect.sonarsource.com/plugins/widgetlab.html
+[INFO]     Minimal SonarQube Version: 4.5.1
+[INFO]     Licensing: GNU LGPL 3
+[INFO]     Organization: Shaw Industries
+[INFO]     Organization URL: http://shawfloors.com
+[INFO]     Terms and Conditions:
+[INFO]     Issue Tracker URL: http://jira.codehaus.org/browse/SONARWIDLB
+[INFO]     Build date: 2015-12-15T18:28:54+0100
+[INFO]     Sources URL: https://github.com/SonarCommunity/sonar-widget-lab
+[INFO]     Developers: G. Ann Campbell,Patroklos Papapetrou
+[INFO] -------------------------------------------------------
+[INFO] Building jar: /dev/sonar-widget-lab/target/sonar-widget-lab-plugin-1.9-SNAPSHOT.jar 
+```
+
+Supported standard pom node properties:
+
+Maven Property|Manifest Key|Notes
+---|---|---
+`version` | Plugin-Version | (required) Plugin version as displayed in page "Marketplace". Default: ${project.version}
+- | Sonar-Version | (required) Minimal version of supported SonarQube at runtime. For example if value is 5.2, then deploying the plugin on versions 5.1 and lower will fail. Default value is given by the version of sonar-plugin-api dependency. It can be overridden with the Maven property sonarQubeMinVersion (since sonar-packaging-maven-plugin 1.16). That allows in some cases to use new features of recent API and to still be compatible at runtime with older versions of SonarQube. Default: version of dependency sonar-plugin-api
+`license` | Plugin-License | Plugin license as displayed in page "Marketplace". Default `${project.licenses}`
+`developers` | Plugin-Developers | List of developers displayed in page "Marketplace". Default: `${project.developers}`
+
+Supported `<configuration>` properties:
+
+Maven Property|Manifest Key|Notes
+---|---|---
+`pluginKey` | Plugin-Key | (required) Contains only letters/digits and is unique among all plugins. Examples: groovy, widgetlab. Constructed from `${project.artifactId}.` Given an artifactId of: `sonar-widget-lab-plugin`, your pluginKey will be: `widgetlab`
+`pluginClass` | Plugin-Class | (required) Name of the entry-point class that extends `org.sonar.api.SonarPlugin`. Example: `org.codehaus.sonar.plugins.widgetlab.WidgetLabPlugin` 
+`pluginName` | Plugin-Name | (required) Displayed in the page "Marketplace". Default: `${project.name}`
+`pluginDescription` | Plugin-Description | Displayed in the page "Marketplace". Default: `${project.description}`
+`pluginUrl` |  Plugin-Homepage | Homepage of website, for example https://github.com/SonarQubeCommunity/sonar-widget-lab `${project.url}`
+`pluginIssueTrackerUrl` |  Plugin-IssueTrackerUrl | Example: https://github.com/SonarQubeCommunity/sonar-widget-lab/issues. Default: `${project.issueManagement.url}`
+`pluginTermsConditionsUrl`  |  Plugin-TermsConditionsUrl | Users must read this document when installing the plugin from Marketplace. Default: `${sonar.pluginTermsConditionsUrl}`
+`useChildFirstClassLoader` | Plugin-ChildFirstClassLoader | Each plugin is executed in an isolated classloader, which inherits a shared classloader that contains API and some other classes. By default the loading strategy of classes is parent-first (look up in shared classloader then in plugin classloader). If the property is true, then the strategy is child-first. This property is mainly used when building plugin against API < 5.2, as the shared classloader contained many 3rd party libraries (guava 10, commons-lang, ...) false
+`basePlugin` | Plugin-Base | If specified, then the plugin is executed in the same classloader as basePlugin.
+`pluginSourcesUrl` | Plugin-SourcesUrl | URL of SCM repository for open-source plugins. Displayed in page "Marketplace". Default: `${project.scm.url}`
+`pluginOrganizationName` | Plugin-Organization | Organization which develops the plugin, displayed in the page "Marketplace". Default: `${project.organization.name}`
+`pluginOrganizationUrl` | Plugin-OrganizationUrl | URL of the organization, displayed in the page "Marketplace". Default: `${project.organization.url}`
+`sonarLintSupported` | SonarLint-Supported | Whether the (language) plugin supports SonarLint or not. Only SonarSource analyzers (SonarJava, SonarJS, ...) and custom rules plugins for SonarSource analyzers should set this to true. 
+`pluginDisplayVersion` | Plugin-Display-Version | The version as displayed in SonarQube administration console. By default it's the raw version, for example "1.2", but can be overridden to "1.2 (build 12345)" for instance. Supported in sonar-packaging-maven-plugin 1.18.0.372. Default: `${project.version}`
+
+
+The Maven sonar-packaging-maven-plugin supports also these properties:
+
+Maven Property|Manifest Key|Notes
+---|---|---
+`addMavenDescriptor` |Copy pom file inside the directory META-INF of generated JAR file? | Boolean. Default: `${sonar.addMavenDescriptor}` / `true`.
+`skipDependenciesPackaging` | Do not copy Maven dependencies into JAR file. | Default: `${sonar.skipDependenciesPackaging} / `false`.
+
+Other Manifest fields:  
+
+* `Implementation-Build` - Identifier of build or commit, for example the Git sha1 "94638028f0099de59f769cdca776e506684235d6". It is displayed for debugging purpose in logs when SonarQube server starts.
+
+## API basics
+
+### Extension points
+SonarQube provides extension points for its three technical stacks:
+
+* Scanner, which runs the source code analysis
+* Compute Engine, which consolidates the output of scanners, for example by 
+   * computing 2nd-level measures such as ratings
+   * aggregating measures (for example number of lines of code of project = sum of lines of code of all files)
+   * assigning new issues to developers
+   * persisting everything in data stores
+* Web application
+
+Extension points are not designed to add new features but to complete existing features. Technically they are contracts defined by a Java interface or an abstract class annotated with @ExtensionPoint. The exhaustive list of extension points is available in the javadoc.
+
+The implementations of extension points (named "extensions") provided by a plugin must be declared in its entry point class, which implements org.sonar.api.Plugin and which is referenced in pom.xml:
+
+ExamplePlugin.java
+```
+package org.sonarqube.plugins.example;
+import org.sonar.api.Plugin;
+public class ExamplePlugin implements Plugin {
+  @Override
+  public void define(Context context) {
+    // implementations of extension points
+    context.addExtensions(FooLanguage.class, ExampleProperties.class);
+  }
+}
+```
+pom.xml
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+  ...
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
+        <artifactId>sonar-packaging-maven-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <pluginClass>org.sonarqube.plugins.example.ExamplePlugin</pluginClass>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
+```
+### Lifecycle
+A plugin extension exists only in its associated technical stacks. A scanner sensor is for example instantiated and executed only in a scanner runtime, but not in the web server nor in Compute Engine. The stack is defined by the annotations [@ScannerSide](http://javadocs.sonarsource.org/latest/apidocs/org/sonar/api/batch/ScannerSide.html), [@ServerSide](http://javadocs.sonarsource.org/latest/apidocs/index.html?org/sonar/api/server/ServerSide.html) (for web server) and [@ComputeEngineSide](http://javadocs.sonarsource.org/latest/apidocs/index.html?org/sonar/api/ce/ComputeEngineSide.html). 
+
+An extension can call core components or another extension of the same stack. These dependencies are defined by constructor injection:
+
+```
+@ScannerSide
+public class Foo {
+  public void call() {}
+}
+// Sensor is a scanner extension point 
+public class MySensor implements Sensor {
+  private final Foo foo;
+  private final Languages languages;
+  
+  // Languages is core component which lists all the supported programming languages.
+  public MySensor(Foo foo, Languages languages) {   
+    this.foo = foo;
+    this.languages = languages;
+  }
+  
+  @Override
+  public void execute(SensorContext context) {
+    System.out.println(this.languages.all());
+    foo.call();
+  }
+}
+  
+public class ExamplePlugin implements Plugin {
+  @Override
+  public void define(Context context) {
+    // Languages is a core component. It must not be declared by plugins.
+    context.addExtensions(Foo.class, MySensor.class);
+  }
+}
+```
+
+It is recommended not to call other components in constructors. Indeed, they may not be initialized at that time. Constructors should only be used for dependency injection.
+
+[[warning]]
+| ![](/images/exclamation.svg) Compilation does not fail if incorrect dependencies are defined, such as a scanner extension trying to call a web server extension. Still it will fail at runtime when plugin is loaded.
+
+### Third-party Libraries
+Plugins are executed in their own isolated classloaders. That allows the packaging and use of 3rd-party libraries without runtime conflicts with core internal libraries or other plugins. Note that since version 5.2, the SonarQube API does not bring transitive dependencies, except SLF4J. The libraries just have to be declared in the pom.xml with default scope "compile":
+
+pom.xml
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+  ...
+  <dependencies>
+    ...
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>1.10</version>
+    </dependency>
+ </dependencies>
+</project>
+```
+Technically the libraries are packaged in the directory META-INF/lib of the generated JAR file. An alternative is to shade libraries, for example with maven-shade-plugin. That minimizes the size of the plugin .jar file by copying only the effective used classes.
+
+[[info]]
+| ![](/images/info.svg) The command `mvn dependency:tree` gives the list of all dependencies, including transitive ones.
+
+### Configuration
+The core component [`org.sonar.api.config.Configuration`](http://javadocs.sonarsource.org/latest/apidocs/index.html?org/sonar/api/config/Configuration.html) provides access to configuration. It deals with default values and decryption of values. It is available in all stacks (scanner, web server, Compute Engine). As recommended earlier, it must not be called from constructors.
+
+MyExtension.java
+```
+public class MyRules implements RulesDefinition {
+  private final Configuration config;
+  
+  public MyRules(Configuration config) {   
+    this.config = config; 
+  }
+  
+  @Override
+  public void define(Context context) {
+    int value = config.getInt("sonar.property").orElse(0);
+  }
+}
+```
+Scanner sensors can get config directly from SensorContext, without using constructor injection:
+
+MySensor.java
+```
+public class MySensor extends Sensor {
+  @Override
+  public void execute(SensorContext context) {
+    int value = context.config().getInt("sonar.property").orElse(0);
+  }
+}
+```
+
+In the scanner stack, properties are checked in the following order, and the first non-blank value is the one that is used:
+
+1. System property
+1. Scanner command-line (-Dsonar.property=foo for instance)
+1. Scanner tool (<properties> of scanner for Maven for instance) 
+1. Project configuration defined in the web UI 
+1. Global configuration defined in the web UI 
+1. Default value
+
+Plugins can define their own properties so that they can be configured from web administration console. The extension point org.sonar.api.config.PropertyDefinition must be used :
+```
+public class ExamplePlugin implements Plugin {
+  @Override
+  public void define(Context context) {
+    context.addExtension(
+      PropertyDefinition.builder("sonar.my.property")
+       .name("My Property")
+       .description("This is the description displayed in web admin console")
+       .defaultValue("42")
+       .build()
+    );
+  }
+}
+```
+
+[[info]]
+| ![](/images/info.svg) Values of the properties suffixed with `.secured` are not available to non-authorized users (anonymous and users without project or global administration rights). `.secured` is needed for passwords, for instance.
+
+The annotation [`@org.sonar.api.Property`](http://javadocs.sonarsource.org/latest/apidocs/index.html?org/sonar/api/Property.html) can also be used on an extension to declare a property, but org.sonar.api.config.PropertyDefinition is preferred.
+```
+@Properties(
+    @Property(key="sonar.my.property", name="My Property", defaultValue="42")
+)
+public class MySensor implements Sensor {
+  // ...
+}
+  
+public class ExamplePlugin implements Plugin {
+  @Override
+  public void define(Context context) {
+    context.addExtension(MySensor.class);
+  }
+}
+```
+
+### Logging
+The class [`org.sonar.api.utils.log.Logger`](http://javadocs.sonarsource.org/latest/apidocs/index.html?org/sonar/api/utils/log/Logger.html) is used to log messages to scanner output, web server logs/sonar.log, or Compute Engine logs (available from administration web console). It's convenient for unit testing (see class [`LogTester`](http://javadocs.sonarsource.org/latest/apidocs/index.html?org/sonar/api/utils/log/LogTester.html)).
+```
+import org.sonar.api.utils.log.*;
+public class MyClass {
+  private static final Logger LOGGER = Loggers.get(MyClass.class);
+  public void doSomething() {
+    LOGGER.info("foo");
+  }
+}
+```
+Internally [SLF4J](http://www.slf4j.org/) is used as a facade of various logging frameworks (log4j, commons-log, logback, java.util.logging). That allows all these frameworks to work at runtime, such as when they are required for a 3rd party library. SLF4J loggers can also be used instead of org.sonar.api.utils.log.Logger. Read the [SLF4J manual](http://www.slf4j.org/manual.html) for more details.
+
+As an exception, plugins must not package logging libraries. Dependencies like SLF4J or log4j must be declared with scope "provided".
+
+### Exposing APIs to Other Plugins
+The common use case is to write a language plugin that will allow some other plugins to contribute additional rules (see for example how it is done in SonarJava). The main plugin will expose some APIs that will be implemented/used by the "rule" plugins.
+
+Plugins are loaded in isolated classloaders. It means a plugin can't access another plugin's classes. There is an exception for package names following pattern `org.sonar.plugins.<pluginKey>.api`. For example all classes in a plugin with the key myplugin that are located in `org.sonar.plugins.myplugin.api` are visible to other plugins.
+
+
+## Versioning and API Deprecation
+### Versioning Strategy
+The goal of this versioning strategy is both to:
+
+* Release often, release early in order to get quick feedback from the SonarQube community
+* Release stable versions of the SonarQube platform for companies whose main priority is to set up a very stable environment. Even if the price for such stable environments is missing out on the latest, sexy SonarQube features
+* Support the API deprecation strategy (see next section)
+
+The rules are:
+
+* Each ~two months a new version of SonarQube is released. This version should increment the minor digit of the previous version (ex: 4.2 -> 4.3)
+* After three (or more) releases, a bug-fix version is released, and becomes the new LTS. The major digit of the subsequent version is incremented to start a new cycle (ex: 5.6 -> 6.0)
+
+And here is the strategy in action:
+```
+4.4 -> 4.5 -> 5.0 -> 5.1 -> 5.2 -> ... -> 5.5 -> 6.0 -> ...     <- New release every ~2 months
+        |                                  |
+      4.5.1 -> 4.5.2 -> ...              5.5.1 -> 5.5.2 -> ...  <- New LTS
+```
+
+### API Deprecation Strategy
+The goal of this deprecation strategy is to make sure that deprecated APIs will be dropped without side-effects at a given planned date. The expected consequence of such strategy is to ease the evolution of the SonarQube API by making such refactoring painless.
+
+The rules are:
+
+* An API must be deprecated before being dropped
+* A deprecated API must be fully supported until its drop (For instance the implementation of a deprecated method can't be replaced by `throw new UnsupportedOperationException())`
+* If an API is deprecated in version X.Y, this API will be dropped in version (X+2).0. Example: an API deprecated in 4.1 is supported in 4.2, 4.3, 5.0, 5.1, 5.2, 5.3 and is dropped in version 6.0.
+* According to the versioning strategy, that means that an API can remain deprecated before being dropped during 6 to 12 months.
+* Any release of a SonarQube plugin must at least depend on the latest LTS version of the SonarQube API
+* For each SonarQube plugin there must at least one release on each LTS version of SonarQube, which means at least one release each 6 months.
+* No use of deprecated APIs is accepted when releasing a plugin. It raises a critical issue in SonarQube analysis. This issue can't be postponed.
+* No deprecated API introduced 2 major versions ago is accepted when releasing SonarQube. It raises a critical issue in SonarQube analysis. This issue can't be postponed.
+* An API is marked as deprecated with both:
+   * the annotation @Deprecated
+   * the javadoc tag @deprecated whose message must start with "in x.y", for example:
+    ```
+    /**
+     * @deprecated in 4.2. Replaced by {@link #newMethod()}.
+     */
+    @Deprecated
+    public void foo() {
+    ```
+## API Changes
+### Release 7.7
+
+![](/images/check.svg) Added
+* ` org.sonar.api.batch.scm.ScmProvider#ignoreCommand`
+
+![](/images/exclamation.svg) Deprecated
+* `org.sonar.api.batch.fs.InputFile::status`
+* `org.sonar.api.resources.Qualifiers#BRC`
+
+![](/images/cross.svg) Removed
+* The preview/issues mode of scanner has been removed
+
+### Release 7.6
+
+![](/images/info.svg) Changed
+
+* `PostJob` moved to project level IoC container
+* `InputFileFilter` moved to project level IoC container
+
+![](/images/check.svg) Added
+
+* New annotation `org.sonar.api.scanner.ScannerSide` to mark (project level) scanner components
+* `org.sonar.api.batch.fs.InputProject` to create issues on project
+* `org.sonar.api.scanner.ProjectSensor` to declare Sensors that only run at project level
+
+![](/images/exclamation.svg) Deprecated
+
+* `org.sonar.scanner.issue.IssueFilter` deprecated
+* `org.sonar.api.batch.InstantiationStrategy` deprecated
+* `org.sonar.api.batch.ScannerSide` deprecated
+* `org.sonar.api.batch.fs.InputModule` deprecated
+* Concept of global Sensor is deprecated (use `ProjectSensor` instead)
+
+![](/images/cross.svg) Removed
+
+* Support of scanner tasks was removed
+* `RulesProfile` is no longer available for scanner side components (use `ActiveRules` instead)
+
+### Release 7.5
+No changes
+
+### Release 7.4
+![](/images/info.svg) Changed
+
+* Allow identity provider to not provide login
+
+![](/images/check.svg) Added
+
+* Allow sensors to report adhoc rules metadata
+
+![](/images/cross.svg) Removed
+
+* `org.sonar.api.rules.RuleFinder` removed from scanner side
+* `sonar-channel` removed from plugin classloader
+* stop support of plugins compiled with API < 5.2
+
+### Release 7.3
+
+![](/images/check.svg) Added
+
+* `RulesDefinitions` supports HotSpots and security standards
+
+![](/images/exclamation.svg) Deprecated
+* `org.sonar.api.batch.AnalysisMode` and `org.sonar.api.issue.ProjectIssues` since preview mode is already deprecated for a while
+
+### Release 7.2
+![](/images/check.svg) Added
+* `org.sonar.api.batch.sensor.SensorContext#newExternalIssue` to report external issues
+* `org.sonar.api.batch.sensor.SensorContext#newSignificantCode` to report part of the source file that should be used for issue tracking
+* `org.sonar.api.scan.issue.filter.FilterableIssue#textRange`
+
+![](/images/exclamation.svg) Deprecated
+* org.sonar.api.scan.issue.filter.FilterableIssue#line
+
+### Release 7.1
+![](/images/check.svg) Added
+* `org.sonar.api.Plugin.Context#getBootConfiguration`
+* `org.sonar.api.server.rule.RulesDefinition.NewRule#addDeprecatedRuleKey` to support deprecated rule keys
+
+### Release 7.0
+![](/images/check.svg) Added
+* `org.sonar.api.batch.scm.ScmProvider#relativePathFromScmRoot`, `org.sonar.api.batch.scm.ScmProvider#branchChangedFiles` and `org.sonar.api.batch.scm.ScmProvider#revisionId` to improve branch and PR support
+
+### Release 6.7
+No changes
diff --git a/server/sonar-docs/src/pages/extend/executable-lines.md b/server/sonar-docs/src/pages/extend/executable-lines.md
new file mode 100644 (file)
index 0000000..3d4bf52
--- /dev/null
@@ -0,0 +1,106 @@
+---
+title: Executable Lines
+url: /extend/executable-lines/
+---
+These are the guidelines that SonarSource uses internally when defining executable lines for a language. Community plugins are not required to adhere to these guidelines. They are provided here only in case they are useful.
+
+## Things that are executable
+Executable lines data is used to calculate missing test coverage for files that are not included in coverage reports. Ideally, executable line counts will be at or just under what coverage engines would calculate.
+
+Generally, each line containing a statement should count as an executable line, with the exception that compound statements ({}) are ignored, although their contents are not
+
+So:
+```
+void doTheThing ()        // +0
+{                         // +0
+  String fname="Finn";    // +1
+  etc();                  // +1
+}                         // +0
+```
+
+## Things that are ignored
+### !Statement: +0 
+Since some coverage engines mark these things as executable, it's worth stating explicitly that we will ignore them:
+
+* lines containing only punctuation: }, });, ;
+* the method signature of a method definition
+
+### Imports, Declarations: +0
+Imports, package and namespace statements, declarations, and a few other things demonstrated below are ignored, 
+```
+package foo;     // +0
+namespace bar {  // +0
+  ...
+}
+  
+import java.util.ArrayList;  // +0
+#include <stdio>             // +0
+  
+public interface FooFace {  // +0
+  void doFoo();             // +0
+}
+public class Foo1 implements FooFace {  // +0
+  private String name;                  // +0
+}
+struct PairWithOperator { // +0
+  int x;                  // +0
+  int y;                  // +0
+  
+  bool operator==(PairWithOperator rhs) const {  // +0
+    return x == rhs.x && y == rhs.y;             // +1
+  }
+}
+  
+class C {
+  C(const C&) =default;  // +0 (explicit inheritance of parent method)
+}
+using Vec = std::vector<T,MyAllocator<T>>;       // +0
+  
+static {                 // +0
+  ...
+}
+01  ERROR-MESSAGE.                                      *> +0
+        02  ERROR-TEXT  PIC X(132) OCCURS 10 TIMES      *> +0
+                                   INDEXED BY ERROR-INDEX.
+77  ERROR-TEXT-LEN      PIC S9(9)  COMP VALUE +132.     *> +0
+```
+
+### Location
+The presence of executable code on a line makes the entire line executable.
+
+If a statement is split over multiple lines, the line to be marked executable is the first one with executable code. 
+Given that a for loop is considered executable:
+```
+for         // +1
+  (         // +0
+   int i=0; // +0
+   i < 10;  // +0
+   i++      // +0
+  )         // +0
+{           // +0
+}
+```
+Regardless of the number of lines across which nested statements are spread, the executable line count should only be incremented by one, since typically the execution of one naturally follows from the other. 
+
+```
+foo(1, bar());  // +1
+  
+foo(1,          // +1
+    bar());     // +0
+```
+We ignore here the possibility that `bar()` could throw an exception, preventing `foo` from being executed.
+
+## Exceptions
+### Python
+Based on observations from code on SonarCloud, `# pragma: no cover` exempts a block from coverage
+
+![# pragma: no cover example](/images/executable-lines-python-exception.png)
+
+### JavaScript
+It seems to be accepted practice in JavaScript to mark variable declarations executable, so we will too. E.G.
+```
+var a;  // +1
+```
diff --git a/server/sonar-docs/src/pages/extend/extend-web-app.md b/server/sonar-docs/src/pages/extend/extend-web-app.md
new file mode 100644 (file)
index 0000000..cffa351
--- /dev/null
@@ -0,0 +1,280 @@
+---
+title: Extending the Web App
+url: /extend/extend-web-app/
+---
+SonarQube provides the ability to add a new JavaScript page. A page (or page extension) is a JavaScript application that runs in the SonarQube environment. You can find the example of page extensions in the SonarQube or [sonar-custom-plugin-example](https://github.com/SonarSource/sonar-custom-plugin-example/tree/6.x/) repositories on GitHub. 
+
+## Getting Started
+### Step 1. Create a Java class implementing PageDefinition
+For each page, you'll need to set a key and a name. The page key should have the format `plugin_key/page_id`. Example: `governance/project_dump`. The `plugin_key` is computed from the `<artifactId>` in your `pom.xml`, or can be set explicitly in the pom using the `<pluginKey>` parameter in `sonar-packaging-maven-plugin` configuration.
+
+All the pages should be declared in this class. 
+```
+import org.sonar.api.web.page.PageDefinition;
+public class MyPluginPageDefinition implements PageDefinition {
+  @Override
+  public void define(Context context) {
+    context
+      .addPage(Page.builder("my_plugin/my_page").setName("My Page").build())
+      .addPage(Page.builder("my_plugin/another_page").setName("Another Page").build());
+  }
+}
+```
+
+### Step 2. Create a JavaScript file
+This file should have the same name as the page key (`my_page.js` in this case) and should be located in `src/main/resources/static`.
+```
+// my_page.js
+window.registerExtension('my_plugin/my_page', function (options) {
+  options.el.textContent = 'This is my page!';
+  return function () {
+    options.el.textContent = '';
+  };
+});
+```
+Where `my_plugin/my_page` is the same page key specified in step 1.
+
+### Configuring the page 
+There are 3 settings available when you define the page extensions using the PageDefinition class:
+
+* `isAdmin`: tells if the page should be restricted to users with the administer permission.
+* `scope`: tells if the page should be displayed in the primary menu (`GLOBAL` scope) or inside a component page (`COMPONENT` scope). By default, a page is global. 
+* `component qualifiers`: allows you to specify if the page should be displayed for `PROJECT`, `MODULE`, `VIEW` or `SUB_VIEW` (the last two come with the Enterprise Edition). If set, the scope of the page must be `COMPONENT`.
+
+### Runtime environment
+SonarQube provides a global function `registerExtension` which should be called from the main javascript file. The function accepts two parameters:
+
+* page extension key, which has a form of `<plugin key>/<page key>` (Ex: `governance/project_dump`)
+* callback function, which is executed when the page extension is loaded. This callback should return another function, which will be called once the page extension will be closed. The callback accepts a single parameter options containing: 
+   * `options.el` is a DOM element you must use to put the content inside
+   * `options.currentUser` contains the response of api/users/current (see Web API docs for details)
+   * (optional) `options.component` contains the information of the current project or view, if the page is project-level: key, name and qualifier
+
+[[info]]
+| SonarQube doesn't guarantee any JavaScript library availability at runtime. If you need a library, include it in the final file.
+
+### Example
+Displaying the number of project issues
+```
+window.registerExtension('my_plugin/my_page', function (options) {
+  // let's create a flag telling if the page is still displayed
+  var isDisplayed = true;
+  // then do a Web API call to the /api/issues/search to get the number of issues
+  // we pass `resolved: false` to request only unresolved issues
+  // and `componentKeys: options.component.key` to request issues of the given project
+  window.SonarRequest.getJSON('/api/issues/search', {
+    resolved: false,
+    componentKeys: options.component.key
+  }).then(function (response) {
+    // once the request is done, and the page is still displayed (not closed already)
+    if (isDisplayed) {
+      // let's create an `h2` tag and place the text inside
+      var header = document.createElement('h2');
+      header.textContent = 'The project has ' + response.total + ' issues';
+      // append just created element to the container
+      options.el.appendChild(header);
+    }
+  });
+  // return a function, which is called when the page is being closed
+  return function () {
+    // we unset the `isDisplayed` flag to ignore to Web API calls finished after the page is closed
+    isDisplayed = false;
+  };
+});
+```
+
+## Implement Pages with React
+### Prerequisites 
+* Be familiar with how to [build, deploy, and debug a plugin](/extend/developing-plugin/)
+* Read the Get Started guide of ReactJS: https://reactjs.org/ to be familiar with React Components
+* [NodeJS](https://nodejs.org/en/) has to be installed on your developer box
+
+[[info]]
+| SonarQube uses React 15.6.2 in the background. You should not try to use features of React 16+ in Custom Pages. This has not been tested.
+
+
+### Custom Plugin
+Everything has been prepared for you to be ready to start coding Custom Pages in this repo: https://github.com/SonarSource/sonar-custom-plugin-example. This way you don't have to spend time with the glue (maven, yarn, npm) and you can concentrate on implementing your pages.
+
+Clone it and run `mvn clean package`. You will get a deployable JAR file. Once deployed, you will see some new pages at global, project and admin level. This has been done so you see Custom Pages with React in action.
+
+This plugin contains 2 example pages built with React: 
+
+* https://github.com/SonarSource/sonar-custom-plugin-example/blob/master/src/main/js/app-measures_history.js
+* https://github.com/SonarSource/sonar-custom-plugin-example/blob/master/src/main/js/app-sanity_check.js
+
+### Instance Statistics Page Example
+The goal of this page is to show some statistics about your SonarQube instance and so to demonstrate how to call SQ Web API from your custom page inside a React component.
+
+The page `app-sanity_check.js` is made of only one React Component named `InstanceStatisticsApp`. `InstanceStatisticsApp` is called in the `render()` method and will be in charge of:
+
+* executing the queries to gather the data
+* displaying them.
+
+
+In the `componentDidMount()` method you will retrieve all the method calls to get the data from SonarQube. The various methods such as `findQualityProfilesStatistics` are defined in the `api.js` file. The complexity to gather the information is hidden in the `api.js`:
+```
+//InstanceStatisticsApp.js
+componentDidMount() {
+  findQualityProfilesStatistics().then(
+    (valuesReturnedByAPI) => {
+     this.setState({
+          numberOfQualityProfiles: valuesReturnedByAPI
+     });
+    }
+  );
+  [...]
+}
+```
+In the render() method we display the information gathered by `componentDidMount()` by mixing HTML and data, aka JSX code.
+```
+render() {
+  return (
+    <div className="page page-limited sanity-check">
+      <table className="data zebra">
+        <tbody>
+          <tr>
+            <td className="code-name-cell"># Quality Profiles</td>
+            <td className="thin nowrap text-right">{this.state.numberOfQualityProfiles}</td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+  )
+}
+```
+
+### FAQ
+
+Q: Can I reuse React Components created by SonarSource to build SonarQube?  
+A: No, SonarQube is not exposing them, so you will have to build your own React Component
+
+Q: How can I add my own styles?  
+A: Feed the `style.css` and reference it in your custom page
+
+
+## Making AJAX requests
+All ajax requests must provide CSRF protection token. In order to help you to do so, we provide a set of useful helpers.
+
+### Getting Started
+Let's start with a simple `GET` request
+```
+window.SonarRequest
+    .getJSON('/api/issues/search')
+    .then(function (response) {
+      // here 'response' contains the object representing the JSON output
+    });
+```    
+* `window.SonarRequest` contains all the helper methods to do an API requests.
+* `window.SonarRequest.getJSON` is a simplest helper to do an API call, receive some data and parse it as JSON.
+
+### API Documentation
+* `window.SonarRequest.request(url: string): Request`  
+Start making an API call. Return a Request instance which has the following methods:
+   * `setMethod(method: string)`: Request sets the http method, can be GET, POST, etc.  
+   * `setData(data: object)`: Request sets the request parameters`
+   * `submit()`: Promise sends the request
+   
+* `window.SonarRequest.getJSON(url: string[, data: object]): Promise`  
+Send a GET request, get a response, parse it as JSON.
+
+* `window.SonarRequest.postJSON(url: string[, data: object]): Promise`  
+Send a POST request, get a response, parse it as JSON.
+
+* `window.SonarRequest.post(url: string[, data: object]): Promise`  
+Send a POST request, ignore the response content.
+
+### Examples
+Get the list of unresolved issues
+```
+window.SonarRequest.getJSON(
+  '/api/issues/search',
+  { resolved: false }
+).then(function (response) {
+  // response.issues contains the list of issues
+});
+```
+Create new project
+```
+window.SonarRequest.post(
+  '/api/projects/create',
+  { key: 'sample', name: 'Sample' }
+).then(function () {
+  // the project has been created
+});
+```
+Handle bad requests
+```
+window.SonarRequest.post(
+  '/api/users/deactivate',
+  { login: 'admin' }
+).catch(function (error) {
+  // error.response.status === 400
+  // error.response.statusText === 'Bad Request'
+  // To read the response:
+  // error.response.json().then(function (jsonResponse) { ... });
+});
+```
+
+
+
+
+## Debugging your page
+When you are developing a custom page, if you want to see the impacts of your changes, you have to compile your plugin, deploy it in SonarQube and finally point your browser to that page to see the changes. This process is long, not efficient and doesn't allow you to quickly adjust your code. 
+
+The easiest way to shorten the loop is to setup an HTTP proxy working like this:
+
+* each time you will request a standard SonarQube URL, the proxy will redirect the call to SonarQube itself
+* when you will request your page in the browser, the proxy will server your JS file from your local box from the path you are currently developing it.
+
+In this example, we are going to use a JS implementation for the HTTP proxy based on Node.js: https://github.com/nodejitsu/node-http-proxy
+
+**Requirements**
+* Node.js LTS 6.11+
+* HTTP Proxy 1.16.2 for Node.js: https://github.com/nodejitsu/node-http-proxy (to be installed in the next step)
+* Your custom plugin containing the custom page you want to debug has to be deployed at least once in SonarQube
+
+### Running the Proxy
+Once Node is installed, check you can run it using : `node --version`
+
+Install HTTP Proxy using this command: `npm install http-proxy --save`
+
+Then put the following code in a file named `sq-proxy.js`:
+```
+var http = require('http'),
+    httpProxy = require('http-proxy'),
+    fs = require('fs');
+var proxy = httpProxy.createProxyServer({});
+var server = http.createServer(function(req, res) {
+  //console.log(req.url);
+  if (req.url === '/static/example/custom_page_global.js') {
+    res.writeHead(200, { 'Content-Type': 'application/javascript' });
+    fs.readFile('/Users/.../sonar-custom-plugin-example/src/main/resources/static/custom_page_global.js', 'utf8', function (err,data) {
+        if (err) {
+          return console.log(err);
+        }
+        res.write(data);
+        res.end();
+    });
+  } else {
+    proxy.web(req, res, { target: 'http://127.0.0.1:9000' });
+  }
+});
+console.log("listening on port 5050")
+server.listen(5050);
+```
+... and finally run your proxy like this: `node sq-proxy.js`
+
+This will:
+
+* run an HTTP proxy on the port 5050 
+* catch all calls to the URL /static/example/custom_page_global.js
+* serve the file located in the path `/Users/.../sonar-custom-plugin-example/src/main/resources/static/custom_page_global.js` instead of the one available in the Custom Plugin.
diff --git a/server/sonar-docs/src/pages/extend/i18n.md b/server/sonar-docs/src/pages/extend/i18n.md
new file mode 100644 (file)
index 0000000..cb22792
--- /dev/null
@@ -0,0 +1,65 @@
+---
+title: Internationalization
+url: /extend/i18n/
+---
+
+This page gives guidelines to I18n for:
+
+* Plugin developers who would like to apply the i18n mechanism in their own plugin, so that this plugin can be available in several languages.
+* People who would like to help the community by making the platform available in a new language.
+
+## Principles
+Although the basics of the i18n mechanism are the same for every part of the ecosystem, the packaging differs depending on what you are developing:
+
+* Translations for SonarQube: making SonarQube available in a new language requires you to develop and publish a new Language Pack plugin. 
+   * By default SonarQube embeds the English Pack.
+   * All other Language Pack plugins, like the French Pack plugin, are maintained by the community, and are available through Marketplace (category "Localization").
+* Translations for the SonarQube Community Plugins: open-source plugins from the SonarQube Community must embed only the bundles for the default locale (en). Translations will be done in the Language Pack plugins.
+
+* Translations for other Plugins: closed-source/commercial/independent plugins must embed the bundles for the default locale and the translations for every language they want to support.
+
+## Translation Bundles
+Localized messages are stored in properties files:
+
+* These are regular properties files with key/value pairs where you put most translations
+* These files must be stored in the org.sonar.l10n package (usually in the `src/main/resources/org/sonar/l10n` directory)
+* The names of these files must follow the convention `<key of the plugin to translate>_<language>.properties`, for example `widgetlabs_fr.properties` or `core_fr.properties` for the core bundle. See `sonar-packaging-maven-plugin` for details on plugin key derivation.
+* Messages can accept arguments. Such entries would look like:
+   * `myplugin.foo=This is a message with 2 params: the first "{0}" and the second "{1}".`
+   
+[[warning]]
+| **UTF-8 encoding**  
+| In the Java API, properties files are supposed to be encoded in ISO-8859 charset. Without good tooling, it can be quite annoying to write translations for languages that do not fit in this charset.
+| This is why we decided to encode the properties files in UTF-8, and let Maven turn them into ASCII at build time thanks to native2ascii-maven-plugin (check the French plugin pom.xml). This makes the process of writing translations with a standard editor far easier.
+
+### How to read localized messages from a plugin extension?
+The component `org.sonar.api.i18n.I18n` is available for web server extensions. Scanner extensions cannot load bundles.
+
+## Writing a Language Pack
+A Language Pack defines bundles for SonarQube and/or plugins.
+
+### Creating a Language Pack
+The easiest way to create a new pack is to copy the [Chinese Pack](https://github.com/SonarQubeCommunity/sonar-l10n-zh) and adapt it to your language.
+
+### Maintaining a Language Pack
+In the pom file, set the versions of SonarQube and of the plugins you want to translate. When it's time to update your language pack for a new version of SonarQube or a plugin, the easiest way to see what keys are missing is to run:
+```
+mvn test
+```
+If the build fails, it means that some keys are missing. Go to `target/l10n` to check the reports for each bundle. Missing keys are listed under 'Missing translations are:'
+```
+Missing translations are:
+code_viewer.no_info_displayed_due_to_security=Due to security settings, no information can be displayed.
+comparison.version.latest=LATEST
+...
+```
+
+Each time you add a new bundle or update an existing one, please create a JIRA ticket on the corresponding L10n component in order to track changes.
+
+## Localizing a Plugin
+This section applies if you are developing a closed-source plugin. If your plugin falls in this category, it must embed its own bundles. Bundle must be defined in `src/main/resources/org/sonar/l10n/<plugin key>_<language>.properties`
+
+The default bundle is mandatory, and must be English. For example the plugin with key "mysonarplugin" must define the following files in order to enable the French translation:
+
+* `org/sonar/l10n/mysonarplugin.properties`
+* `org/sonar/l10n/mysonarplugin_fr.properties`
diff --git a/server/sonar-docs/src/pages/extend/new-langauges.md b/server/sonar-docs/src/pages/extend/new-langauges.md
new file mode 100644 (file)
index 0000000..26db3f6
--- /dev/null
@@ -0,0 +1,26 @@
+---
+title: Supporting New Langauges
+url: /extend/new-languages/
+---
+
+
+The steps to cover a new programming language are:
+
+1. Write the grammar. This is the hardest part.
+1. Write a parser (a parser simply parses an input based on your grammar to yield a parse tree).
+1. Test your grammar, to ensure it is able to parse real-life language files.
+1. Write a few parse tree visitors. Some visitors will compute metrics, while others will enforce [coding rules](/extend/adding-coding-rules/). A dozen or so visitors is sufficient for an initial release.
+1. Write a scanner Sensor, in a SonarQube plugin, to launch the visitors. 
+1. Compute
+   1. issues
+   1. raw measures
+   1. code duplications
+   1. syntax highlighting
+   1. symbol table
+   1. coverage information (lines/branches to cover, line/branch hits)
+   
+In fulfilling these steps, the [SonarSource Language Recognizer (SSLR)](https://github.com/SonarSource/sslr) can be an important resource.
+   
+
+
diff --git a/server/sonar-docs/src/pages/extend/web-api.md b/server/sonar-docs/src/pages/extend/web-api.md
new file mode 100644 (file)
index 0000000..310eea6
--- /dev/null
@@ -0,0 +1,22 @@
+---
+title: Web API Authentication
+url: /extend/web-api/
+---
+SonarQube provides web API to access its functionalities from applications. The web services composing the web API are documented within SonarQube, through the URL [/web_api](/#sonarqube#/web_api), which can also be reached from a link in the page footer. 
+
+Administrative web services are secured and require the user to have specific permissions. In order to be authenticated, the user must provide credentials as described below.
+
+## User Token
+
+This is the recommended way. Benefits are described in the page [User Token](/user-guide/user-token/). The token is sent via the login field of HTTP basic authentication, without any password.
+```
+# note that the colon after the token is required in curl to set an empty password 
+curl -u THIS_IS_MY_TOKEN: https://sonarqube.com/api/user_tokens/search
+```
+
+## HTTP Basic Access
+Login and password are sent via the standard HTTP Basic fields:
+```
+curl -u MY_LOGIN:MY_PASSWORD https://sonarqube.com/api/user_tokens/search
+```
+Users who authenticate in web application through an OAuth provider, for instance GitHub or Bitbucket, don't have credentials and can't use HTTP Basic mode. They must generate and use tokens.
index fade6da232e7da8ed5bd95c49b3988cb1b60d709..9c39db51d6e0ad519209fdb379801a37b9452e07 100644 (file)
       "/instance-administration/db-copy/"
     ]
   },
+  {
+    "title": "Extension Guide",
+    "children": [
+      "/extend/web-api/",
+      "/extend/adding-coding-rules/",
+      "/extend/developing-plugin/",
+      "/extend/new-languages/",
+      "/extend/executable-lines/",
+      "/extend/adding-scm/",
+      "/extend/extend-web-app/",
+      "/extend/i18n/",
+      "/extend/deploying-to-marketplace/",
+      "/extend/contributing/"
+    ]
+  },
   "/faq/"
 
 ]
index 3ba25104f483c476744664c34a09089b7fdf41fa..43b99594c9abc8e221134c5673182505a320ed9b 100644 (file)
       "/instance-administration/db-copy/"
     ]
   },
+  {
+    "title": "Extension Guide",
+    "children": [
+      "/extend/web-api/",
+      "/extend/adding-coding-rules/",
+      "/extend/developing-plugin/",
+      "/extend/new-languages/",
+      "/extend/executable-lines/",
+      "/extend/adding-scm/",
+      "/extend/extend-web-app/",
+      "/extend/i18n/",
+      "/extend/deploying-to-marketplace/",
+      "/extend/contributing/"
+    ]
+  },
   "/previous-versions/",
   "/faq/",
   {
   {
     "title": "Plugins",
     "url": "https://docs.sonarqube.org/display/PLUG"
-  },
-  {
-    "title": "Extension",
-    "url": "https://docs.sonarqube.org/display/DEV"
+  
   }
 ]