Skip to content

Commit 5a51731

Browse files
committed
Add convert to boolean code action
Adds a codeaction that converts string true or false to boolean when boolean is expected.
1 parent 5fcaa1b commit 5a51731

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/languageservice/services/yamlCodeActions.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export class YamlCodeActions {
4040

4141
const result = [];
4242

43+
result.push(...this.getConvertToBooleanActions(params.context.diagnostics, document));
4344
result.push(...this.getJumpToSchemaActions(params.context.diagnostics));
4445
result.push(...this.getTabToSpaceConverting(params.context.diagnostics, document));
4546

@@ -162,6 +163,25 @@ export class YamlCodeActions {
162163

163164
return result;
164165
}
166+
private getConvertToBooleanActions(diagnostics: Diagnostic[], document: TextDocument): CodeAction[] {
167+
const results: CodeAction[] = [];
168+
for (const diagnostic of diagnostics) {
169+
if (diagnostic.message === 'Incorrect type. Expected "boolean".') {
170+
const value = document.getText(diagnostic.range).toLocaleLowerCase();
171+
if (value === '"true"' || value === '"false"' || value === "'true'" || value === "'false'") {
172+
const newValue = value.includes('true') ? 'true' : 'false';
173+
results.push(
174+
CodeAction.create(
175+
'Convert to boolean',
176+
createWorkspaceEdit(document.uri, [TextEdit.replace(diagnostic.range, newValue)]),
177+
CodeActionKind.QuickFix
178+
)
179+
);
180+
}
181+
}
182+
}
183+
return results;
184+
}
165185
}
166186

167187
function createWorkspaceEdit(uri: string, edits: TextEdit[]): WorkspaceEdit {

test/code-action-schema.test.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Red Hat. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
import { SCHEMA_ID, setupLanguageService, setupSchemaIDTextDocument } from './utils/testHelper';
6+
import { ServiceSetup } from './utils/serviceSetup';
7+
import { TextDocumentIdentifier, CodeActionParams, CodeActionContext, TextEdit, Range } from 'vscode-languageserver';
8+
import { expect } from 'chai';
9+
import { SettingsState, TextDocumentTestManager } from '../src/yamlSettings';
10+
import { ValidationHandler } from '../src/languageserver/handlers/validationHandlers';
11+
import { LanguageService } from '../src/languageservice/yamlLanguageService';
12+
import { YamlCodeActions } from '../src/languageservice/services/yamlCodeActions';
13+
import { TextDocument } from 'vscode-languageserver-textdocument';
14+
import { TEST_URI } from './utils/testHelper';
15+
16+
describe('Schema Errors Code Action Tests', () => {
17+
let languageSettingsSetup: ServiceSetup;
18+
let validationHandler: ValidationHandler;
19+
let languageService: LanguageService;
20+
let yamlSettings: SettingsState;
21+
22+
before(() => {
23+
languageSettingsSetup = new ServiceSetup().withValidate();
24+
const { languageService: langService, validationHandler: valHandler, yamlSettings: settings } = setupLanguageService(
25+
languageSettingsSetup.languageSettings
26+
);
27+
languageService = langService;
28+
validationHandler = valHandler;
29+
yamlSettings = settings;
30+
});
31+
32+
function parseSetup(content: string, customSchemaID?: string): TextDocument {
33+
const testTextDocument = setupSchemaIDTextDocument(content, customSchemaID);
34+
yamlSettings.documents = new TextDocumentTestManager();
35+
(yamlSettings.documents as TextDocumentTestManager).set(testTextDocument);
36+
return testTextDocument;
37+
}
38+
39+
afterEach(() => {
40+
languageService.deleteSchema(SCHEMA_ID);
41+
});
42+
43+
describe('Convert value code action tests', () => {
44+
it('Should provide convert to boolean action for false', async () => {
45+
languageService.addSchema(SCHEMA_ID, {
46+
type: 'object',
47+
properties: {
48+
analytics: {
49+
type: 'boolean',
50+
},
51+
},
52+
});
53+
const content = 'analytics: "false"';
54+
const doc = parseSetup(content);
55+
const diagnostics = await validationHandler.validateTextDocument(doc);
56+
const params: CodeActionParams = {
57+
context: CodeActionContext.create(diagnostics),
58+
range: undefined,
59+
textDocument: TextDocumentIdentifier.create(TEST_URI),
60+
};
61+
const actions = new YamlCodeActions({});
62+
const result = actions.getCodeAction(doc, params);
63+
expect(result.length).to.be.equal(1);
64+
expect(result[0].title).to.be.equal('Convert to boolean');
65+
expect(result[0].edit.changes[doc.uri]).to.exist;
66+
const edit = result[0].edit.changes[doc.uri];
67+
expect(edit.length).to.be.equal(1);
68+
expect(edit[0]).deep.equal(TextEdit.replace(Range.create(0, 11, 0, 18), 'false'));
69+
});
70+
71+
it('Should provide convert to boolean action for true', async () => {
72+
languageService.addSchema(SCHEMA_ID, {
73+
type: 'object',
74+
properties: {
75+
analytics: {
76+
type: 'boolean',
77+
},
78+
},
79+
});
80+
const content = "analytics: 'true'";
81+
const doc = parseSetup(content);
82+
const diagnostics = await validationHandler.validateTextDocument(doc);
83+
const params: CodeActionParams = {
84+
context: CodeActionContext.create(diagnostics),
85+
range: undefined,
86+
textDocument: TextDocumentIdentifier.create(TEST_URI),
87+
};
88+
const actions = new YamlCodeActions({});
89+
const result = actions.getCodeAction(doc, params);
90+
expect(result.length).to.be.equal(1);
91+
expect(result[0].title).to.be.equal('Convert to boolean');
92+
expect(result[0].edit.changes[doc.uri]).to.exist;
93+
const edit = result[0].edit.changes[doc.uri];
94+
expect(edit.length).to.be.equal(1);
95+
expect(edit[0]).deep.equal(TextEdit.replace(Range.create(0, 11, 0, 17), 'true'));
96+
});
97+
});
98+
});

0 commit comments

Comments
 (0)