For connected mode to work, a connection should be defined to allow SonarLint to communicate with the server. Then, SonarLint needs to know which Sonar Project should be considered. This is the binding. Inside IDE, there could be different bindings, for different configuration scopes.
For most users, there will be only one configured connection (to their corporate SonarQube server, or to SonarCloud). But every time they open a new project or solution, they will need to setup the binding. This process can be tedious, and easily forgotten.
Binding suggestion is the feature where SonarLint assist users as much as possible to configure binding.
Binding suggestion is triggered:
-
when a configuration scope is added (we will look for suggestions among all connections, but only for this configuration scope)
-
when a connection configuration is added/updated (we will look for suggestions for all configuration scopes, but only for this connection)
-
At least one connection configuration is defined
-
Only consider configuration scopes that:
-
are not bound (or maybe if we know the binding is invalid? TBD)
-
have their bindingSuggestionDisabled attribute set to
false
-
For each configuration scope:
-
Search for the presence of files
sonar-project.properties
or.sonarcloud.properties
. This step should be under IDE responsibility, since the configuration scope layout and filesystem is very IDE specific. The IDE should provide the list of files (with filename) and their text content. -
Extract from each file content the following properties (all are optional):
-
sonar.projectKey
-
sonar.host.url
-
sonar.organization
-
-
For each filename + tuple of properties, try to guess if we are looking for a SonarQube or SonarCloud connection, using the following heuristic:
-
if the file is
.sonarcloud.properties
, this is SonarCloud (AutoScan) -
if there is a
sonar.organization
, this is SonarCloud -
if the
sonar.host.url
is equal tohttps://sonarcloud.io
or one of the aliases used for tests, this is SonarCloud, any other non-empty value means it is SonarQube -
at this stage keep properties (normally only projectKey) as an unknown binding clue
-
At the end of this step, we should have a possibly empty list of binding clues having one of those types and attributes:
SonarQube Binding Clue |
---|
projectKey: string? |
serverUrl: string |
SonarCloud Binding Clue |
---|
projectKey: string? |
organization: string? |
Unknown Binding Clue |
---|
projectKey: string |
Candidates for connection matching depend on the trigger. We are not necessarily looking for binding suggestions among all configured connections.
For each binding clue, find the matching connection(s) among connection candidates.
For a SonarQube Binding Clue, select all SonarQube connections having the same[1] url.
For a SonarCloud Binding Clue, select all SonarCloud connections having the same organization. If we don’t have an organization for this candidate binding, select all SonarCloud connections.
For a generic Binding Clue, select all connections.
At the end of this step, we should have each binding clue with a (possibly empty) list of matching connections.
Binding Clues having no matching connections should be discarded (example: the project has a .sonarcloud.properties
, but there is no SonarCloud connection defined).
We should favor binding clues with a non-empty projectKey.
For each binding clue having a projectKey, search for a Sonar project having the exact same projectKey among the matched connections. If there is at least one perfect match, return the match(es).
If no perfect matches were found in the previous step, then for each binding clue with no projectKey, we should do a search among all Sonar Projects of their matched connections. If there were no binding clues with no projectKey, then simply do a search for connection candidates.
The matching is based on a scoring described in TextSearchIndex
. If there is only one Sonar Project with the highest score, then we will return this one, else if there are multiple with top score, then we will return all top candidates. Finally, if there are no matches (FIXME or score is too low?), then we should return NO_MATCHES_FOUND
.
At the end of the binding suggestion computation, one single notification will be sent (1 trigger → 1 notification maximum). The notification will contain the binding suggestion(s) for each configuration scopes where the computation was executed. For each configuration scope:
-
if there is a single best suggestion:
-
the single Sonar Project suggestion + connectionId
-
-
if there are multiple best suggestions (and less than a threshold TBD):
-
the list of (Sonar Project suggestions + connectionIds)
-
-
if there are no suggestions
-
empty suggestion list (to indicate to clients that binding suggestion was attempted but could not find good results, and client should usually forward users to manual binding)
-
Configuration scopes that have been skipped from binding suggestion at any time in the previously described algorithm will not be listed in the notification.
It is the responsibility of the IDE to offer the "Do not ask again" option in the binding suggestion notification, and it should be remembered for this configuration scope in IDE settings. When the client synchronize configuration scopes with the backend, the attribute bindingSuggestionDisabled will be set accordingly.