Skip to content

Commit

Permalink
SLVSCODE-889 getIssueDetails
Browse files Browse the repository at this point in the history
  • Loading branch information
sophio-japharidze-sonarsource committed Nov 7, 2024
1 parent d58dae1 commit ac87f1a
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 47 deletions.
2 changes: 1 addition & 1 deletion its/src/test/csharpsuite/csharp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ suite('CSharp Test Suite', () => {
const expectedActionTitles = [
'SonarLint: Add comment',
"SonarLint: Deactivate rule 'csharpsquid:S1186'",
"SonarLint: Open description of rule 'csharpsquid:S1186'",
"SonarLint: Show issue details for 'csharpsquid:S1186'",
'SonarLint: Throw NotSupportedException'
];
const actualCodeActionTitles = codeActionsResult
Expand Down
9 changes: 6 additions & 3 deletions its/src/test/javaSuite/java.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,15 @@ suite('Java Test Suite', () => {

// Check that the exception-related diagnostic has 3 code actions
const rangeInMiddleOfThrowsMyException = new vscode.Range(8, 54, 8, 54);
const codeActionsResult = (await vscode.commands.executeCommand<(vscode.Command | vscode.CodeAction)[]>('vscode.executeCodeActionProvider', document.uri, rangeInMiddleOfThrowsMyException, vscode.CodeActionKind.QuickFix.value))!;
const codeActionsResult = (await vscode.commands.executeCommand<(vscode.Command | vscode.CodeAction)[]>('vscode.executeCodeActionProvider', document.uri, rangeInMiddleOfThrowsMyException, vscode.CodeActionKind.QuickFix.value));
// With old versions of VSCode, code actions are not necessarily filtered on kind
console.log('+++++++', codeActionsResult[0].title)
console.log('+++++++', codeActionsResult[2].title)
console.log('+++++++', codeActionsResult[1].title)
const expectedActionTitles = [
"SonarLint: Deactivate rule 'java:S1130'",
"SonarLint: Open description of rule 'java:S1130'",
'SonarLint: Remove "MyException"'
"SonarLint: Remove \"MyException\"",
"SonarLint: Show issue details for 'java:S1130'"
];
const actualCodeActionTitles = codeActionsResult.filter(c => expectedActionTitles.indexOf(c.title) >= 0).map(c => c.title);
// Order of code actions is not stable, forcing lexicographic order for assertion
Expand Down
2 changes: 1 addition & 1 deletion scripts/dependencies.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
"groupId": "org.sonarsource.sonarlint.ls",
"artifactId": "sonarlint-language-server",
"version": "3.12.0.75621",
"version": "3.13.0.75632",
"output": "server/sonarlint-ls.jar"
},
{
Expand Down
4 changes: 2 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,13 @@ function registerCommands(context: VSCode.ExtensionContext) {

context.subscriptions.push(
VSCode.commands.registerCommand(Commands.SHOW_HOTSPOT_RULE_DESCRIPTION, hotspot =>
languageClient.showHotspotRuleDescription(hotspot.ruleKey, hotspot.key, hotspot.fileUri)
languageClient.showHotspotRuleDescription(hotspot.key, hotspot.fileUri)
)
);

context.subscriptions.push(
VSCode.commands.registerCommand(Commands.SHOW_HOTSPOT_DETAILS, async hotspot => {
const hotspotDetails = await languageClient.getHotspotDetails(hotspot.ruleKey, hotspot.key, hotspot.fileUri);
const hotspotDetails = await languageClient.getHotspotDetails(hotspot.key, hotspot.fileUri);
showHotspotDetails(hotspotDetails, hotspot);
})
);
Expand Down
5 changes: 2 additions & 3 deletions src/issue/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,9 @@ export class IssueService {

if (issue.shouldOpenRuleDescription) {
await VSCode.commands.executeCommand(
'SonarLint.OpenRuleDescCodeAction',
'SonarLint.OpenRuleDesc',
issue.ruleKey,
code2ProtocolConverter(documentUri),
''
issue.fileUri,
);
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/lsp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ export class SonarLintExtendedLanguageClient extends LanguageClient {
this.sendRequest(protocol.ShowHotspotLocations.type, { hotspotKey, fileUri });
}

showHotspotRuleDescription(ruleKey: string, hotspotId: string, fileUri: string) {
this.sendNotification(protocol.ShowHotspotRuleDescriptionNotification.type, { ruleKey, hotspotId, fileUri });
showHotspotRuleDescription(hotspotId: string, fileUri: string) {
this.sendNotification(protocol.ShowHotspotRuleDescriptionNotification.type, { hotspotId, fileUri });
}

openHotspotOnServer(hotspotId: string, fileUri: string) {
Expand Down Expand Up @@ -158,8 +158,8 @@ export class SonarLintExtendedLanguageClient extends LanguageClient {
return this.sendRequest(protocol.CheckLocalDetectionSupported.type, { uri: folderUri });
}

getHotspotDetails(ruleKey, hotspotId, fileUri): Promise<protocol.ShowRuleDescriptionParams> {
return this.sendRequest(protocol.GetHotspotDetails.type, { ruleKey, hotspotId, fileUri });
getHotspotDetails(hotspotId, fileUri): Promise<protocol.ShowRuleDescriptionParams> {
return this.sendRequest(protocol.GetHotspotDetails.type, { hotspotId, fileUri });
}

didCreateBinding(mode: protocol.BindingCreationMode): Promise<void> {
Expand Down
40 changes: 37 additions & 3 deletions src/lsp/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as lsp from 'vscode-languageserver-protocol';
//#region Client side extensions to LSP

export namespace ShowRuleDescriptionNotification {
export const type = new lsp.NotificationType<ShowRuleDescriptionParams>('sonarlint/showRuleDescription');
export const type = new lsp.NotificationType<ShowStandaloneRuleDescriptionParams>('sonarlint/showRuleDescription');
}

export namespace SuggestBindingNotification {
Expand Down Expand Up @@ -56,12 +56,11 @@ export namespace ShowHotspotRuleDescriptionNotification {
}

export interface ShowHotspotRuleDescriptionNotificationParams {
ruleKey: string;
hotspotId: string;
fileUri: string;
}

export interface ShowRuleDescriptionParams {
export interface ShowStandaloneRuleDescriptionParams {
key: string;
name: string;
htmlDescription: string;
Expand Down Expand Up @@ -92,6 +91,41 @@ export interface ShowRuleDescriptionParams {
}>;
}

export interface ShowRuleDescriptionParams {
key: string;
name: string;
htmlDescription: string;
htmlDescriptionTabs: Array<{
title: string;
ruleDescriptionTabNonContextual?: {
htmlContent: string;
};
ruleDescriptionTabContextual?: Array<{
htmlContent: string;
contextKey: string;
displayName: string;
}>;
hasContextualInformation: boolean;
defaultContextKey?: string;
}>;
severityDetails: SeverityDetails;
languageKey: string;
isTaint: boolean;
parameters?: Array<{
name: string;
description: string;
defaultValue: string;
}>;
}

interface SeverityDetails {
severity?: string;
type?: string;
cleanCodeAttribute?: string;
cleanCodeAttributeCategory?: string;
impacts?: { [softwareQuality: string]: string };
}

export namespace GetJavaConfigRequest {
export const type = new lsp.RequestType<string, GetJavaConfigResponse, void>('sonarlint/getJavaConfig');
}
Expand Down
2 changes: 1 addition & 1 deletion src/lsp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function languageServerCommand(

const params = [];
if (DEBUG) {
params.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000,quiet=y');
params.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8001,quiet=y');
params.push('-Dsonarlint.telemetry.disabled=true');
}
const vmargs = getSonarLintConfiguration().get('ls.vmargs', '');
Expand Down
22 changes: 11 additions & 11 deletions src/rules/rulepanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ function computeRuleDescPanelContent(
}

function renderCleanCodeAttribute(rule: ShowRuleDescriptionParams) {
const categoryLabel = escapeHtml(rule.cleanCodeAttributeCategory);
const attributeLabel = escapeHtml(rule.cleanCodeAttribute);
const categoryLabel = escapeHtml(rule.severityDetails.cleanCodeAttributeCategory);
const attributeLabel = escapeHtml(rule.severityDetails.cleanCodeAttribute);
return `<div class="clean-code-attribute capsule" title="Clean Code attributes are characteristics code needs to have to be considered clean.">
<span class="attribute-category">${categoryLabel} issue</span>
<span class="attribute">${attributeLabel}</span>
Expand All @@ -109,9 +109,9 @@ function renderImpact(softwareQuality: string, severity: string, resolver: Resou
}

function renderTaxonomyInfo(rule: ShowRuleDescriptionParams, resolver: ResourceResolver) {
if (rule.impacts && Object.keys(rule.impacts).length > 0) {
if (rule.severityDetails.impacts && Object.keys(rule.severityDetails.impacts).length > 0) {
// Clean Code taxonomy
const renderedImpacts = Object.entries(rule.impacts).map(([softwareQuality, severity]) => renderImpact(softwareQuality, severity, resolver));
const renderedImpacts = Object.entries(rule.severityDetails.impacts).map(([softwareQuality, severity]) => renderImpact(softwareQuality, severity, resolver));
return `<div class="taxonomy">
${renderCleanCodeAttribute(rule)}
&nbsp;
Expand All @@ -123,16 +123,16 @@ function renderTaxonomyInfo(rule: ShowRuleDescriptionParams, resolver: ResourceR
</div>`;
} else {
// Old type + severity taxonomy
const severityImgSrc = resolver.resolve('images', 'severity', `${rule.severity.toLowerCase()}.png`);
const typeImgSrc = resolver.resolve('images', 'type', `${rule.type.toLowerCase()}.png`);
const severityImgSrc = resolver.resolve('images', 'severity', `${rule.severityDetails.severity.toLowerCase()}.png`);
const typeImgSrc = resolver.resolve('images', 'type', `${rule.severityDetails.type.toLowerCase()}.png`);
return `<div class="taxonomy">
<div class="impact capsule">
${clean(rule.type)}
<img alt="${rule.type}" src="${typeImgSrc}" />
${clean(rule.severityDetails.type)}
<img alt="${rule.severityDetails.type}" src="${typeImgSrc}" />
</div>
<div class="impact capsule">
${clean(rule.severity)}
<img alt="${rule.severity}" src="${severityImgSrc}" />
${clean(rule.severityDetails.severity)}
<img alt="${rule.severityDetails.severity}" src="${severityImgSrc}" />
</div>
</div>`;
}
Expand All @@ -153,7 +153,7 @@ export function renderTaintBanner(rule: ShowRuleDescriptionParams, infoImgSrc: s
}

export function renderHotspotBanner(rule: ShowRuleDescriptionParams, infoImgSrc: string) {
if (rule.type !== 'SECURITY_HOTSPOT') {
if (rule.severityDetails.type !== 'SECURITY_HOTSPOT') {
return '';
}
return `<div class="info-banner-wrapper">
Expand Down
54 changes: 36 additions & 18 deletions test/suite/rulepanel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ suite('rulepanel', () => {
isTaint: false,
key: '',
name: '',
severity: '',
type: '',
severityDetails: {
severity: '',
type: ''
},
languageKey: '',
htmlDescription: 'monolithicDescription'
})
Expand Down Expand Up @@ -56,9 +58,11 @@ suite('rulepanel', () => {
isTaint: true,
key: '',
name: '',
severity: '',
severityDetails: {
severity: '',
type: ''
},
languageKey: '',
type: '',
htmlDescription: 'contextualDescription'
});
let inlineHtmlResult = htmlResult.replace(/(\r\n|\n|\r)/gm, "");
Expand Down Expand Up @@ -91,9 +95,11 @@ suite('rulepanel', () => {
isTaint: false,
key: '',
name: '',
severity: '',
severityDetails: {
severity: '',
type: ''
},
languageKey: '',
type: '',
htmlDescription: ''
})
).to.be.empty;
Expand All @@ -103,8 +109,10 @@ suite('rulepanel', () => {
isTaint: false,
key: '',
name: '',
severity: '',
type: '',
severityDetails: {
severity: '',
type: ''
},
languageKey: '',
htmlDescription: '',
parameters: []
Expand All @@ -119,8 +127,10 @@ suite('rulepanel', () => {
isTaint: false,
key: '',
name: '',
severity: '',
type: '',
severityDetails: {
severity: '',
type: ''
},
languageKey: '',
htmlDescription: '',
parameters: [
Expand All @@ -142,8 +152,10 @@ suite('rulepanel', () => {
isTaint: false,
key: '',
name: '',
severity: '',
type: 'NOT A HOTSPOT',
severityDetails: {
severity: '',
type: 'NOT_A_HOTSPOT'
},
languageKey: '',
htmlDescription: ''
},
Expand All @@ -160,9 +172,11 @@ suite('rulepanel', () => {
isTaint: false,
key: '',
name: '',
severity: '',
severityDetails: {
severity: '',
type: 'SECURITY_HOTSPOT'
},
languageKey: '',
type: 'SECURITY_HOTSPOT',
htmlDescription: ''
},
''
Expand All @@ -178,9 +192,11 @@ suite('rulepanel', () => {
isTaint: false,
key: '',
name: '',
severity: '',
severityDetails: {
severity: '',
type: ''
},
languageKey: '',
type: '',
htmlDescription: ''
},
''
Expand All @@ -196,9 +212,11 @@ suite('rulepanel', () => {
isTaint: true,
key: '',
name: '',
severity: '',
severityDetails: {
severity: '',
type: ''
},
languageKey: '',
type: '',
htmlDescription: ''
},
''
Expand Down

0 comments on commit ac87f1a

Please sign in to comment.