Skip to content

Commit 808d7ed

Browse files
committed
fix isee #37 completionHelper will break yaml file if it contains \r charactor at #37
1 parent 9cbe196 commit 808d7ed

File tree

4 files changed

+193
-192
lines changed

4 files changed

+193
-192
lines changed

src/server.ts

+49-47
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ function validateTextDocument(textDocument: TextDocument): void {
413413
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] });
414414
return;
415415
}
416-
416+
417417
let yamlDocument = parseYAML(textDocument.getText());
418418
isKubernetes(textDocument) ? setKubernetesParserOption(yamlDocument.documents, true) : setKubernetesParserOption(yamlDocument.documents, false);
419419
customLanguageService.doValidation(textDocument, yamlDocument).then(function(diagnosticResults){
@@ -450,60 +450,62 @@ connection.onCompletion(textDocumentPosition => {
450450
return customLanguageService.doComplete(textDocument, textDocumentPosition.position, jsonDocument);
451451
});
452452

453+
function is_EOL(c) {
454+
return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
455+
}
456+
453457
function completionHelper(document: TextDocument, textDocumentPosition: Position){
454458

455-
//Get the string we are looking at via a substring
456-
let linePos = textDocumentPosition.line;
457-
let position = textDocumentPosition;
458-
let lineOffset = getLineOffsets(document.getText());
459-
let start = lineOffset[linePos]; //Start of where the autocompletion is happening
460-
let end = 0; //End of where the autocompletion is happening
461-
if(lineOffset[linePos+1]){
462-
end = lineOffset[linePos+1];
459+
//Get the string we are looking at via a substring
460+
let linePos = textDocumentPosition.line;
461+
let position = textDocumentPosition;
462+
let lineOffset = getLineOffsets(document.getText());
463+
let start = lineOffset[linePos]; //Start of where the autocompletion is happening
464+
let end = 0; //End of where the autocompletion is happening
465+
if(lineOffset[linePos+1]){
466+
end = lineOffset[linePos+1];
467+
}else{
468+
end = document.getText().length;
469+
}
470+
471+
while (end - 1 >= 0 && is_EOL(document.getText().charCodeAt(end - 1))) {
472+
end--;
473+
}
474+
475+
let textLine = document.getText().substring(start, end);
476+
477+
//Check if the string we are looking at is a node
478+
if(textLine.indexOf(":") === -1){
479+
//We need to add the ":" to load the nodes
480+
481+
let newText = "";
482+
483+
//This is for the empty line case
484+
let trimmedText = textLine.trim();
485+
if(trimmedText.length === 0 || (trimmedText.length === 1 && trimmedText[0] === '-')){
486+
//Add a temp node that is in the document but we don't use at all.
487+
newText = document.getText().substring(0, start+textLine.length) + "holder:\r\n" + document.getText().substr(lineOffset[linePos+1] || document.getText().length);
488+
489+
//For when missing semi colon case
463490
}else{
464-
end = document.getText().length;
491+
//Add a semicolon to the end of the current line so we can validate the node
492+
newText = document.getText().substring(0, start+textLine.length) + ":\r\n" + document.getText().substr(lineOffset[linePos+1] || document.getText().length);
465493
}
466-
let textLine = document.getText().substring(start, end);
467-
468-
//Check if the string we are looking at is a node
469-
if(textLine.indexOf(":") === -1){
470-
//We need to add the ":" to load the nodes
471-
472-
let newText = "";
473-
474-
//This is for the empty line case
475-
let trimmedText = textLine.trim();
476-
if(trimmedText.length === 0 || (trimmedText.length === 1 && trimmedText[0] === '-')){
477-
//Add a temp node that is in the document but we don't use at all.
478-
if(lineOffset[linePos+1]){
479-
newText = document.getText().substring(0, start+(textLine.length-1)) + "holder:\r\n" + document.getText().substr(end+2);
480-
}else{
481-
newText = document.getText().substring(0, start+(textLine.length)) + "holder:\r\n" + document.getText().substr(end+2);
482-
}
483-
//For when missing semi colon case
484-
}else{
485-
//Add a semicolon to the end of the current line so we can validate the node
486-
if(lineOffset[linePos+1]){
487-
newText = document.getText().substring(0, start+(textLine.length-1)) + ":\r\n" + document.getText().substr(end+2);
488-
}else{
489-
newText = document.getText().substring(0, start+(textLine.length)) + ":\r\n" + document.getText().substr(end+2);
490-
}
491-
}
492494

493-
return {
494-
"newText": newText,
495-
"newPosition": textDocumentPosition
496-
}
495+
return {
496+
"newText": newText,
497+
"newPosition": textDocumentPosition
498+
}
497499

498-
}else{
500+
}else{
499501

500-
//All the nodes are loaded
501-
position.character = position.character - 1;
502-
return {
503-
"newText": document.getText(),
504-
"newPosition": position
505-
}
502+
//All the nodes are loaded
503+
position.character = position.character - 1;
504+
return {
505+
"newText": document.getText(),
506+
"newPosition": position
506507
}
508+
}
507509

508510
}
509511

test/autoCompletion.test.ts

+54-55
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ languageService.configure(languageSettings);
3636

3737
suite("Auto Completion Tests", () => {
3838

39-
39+
4040
describe('yamlCompletion with bowerrc', function(){
41-
41+
4242
describe('doComplete', function(){
43-
43+
4444
function setup(content: string){
4545
return TextDocument.create("file://~/Desktop/vscode-k8s/test.yaml", "yaml", 0, content);
4646
}
@@ -55,7 +55,7 @@ suite("Auto Completion Tests", () => {
5555
let content = "";
5656
let completion = parseSetup(content, 0);
5757
completion.then(function(result){
58-
assert.notEqual(result.items.length, 0);
58+
assert.notEqual(result.items.length, 0);
5959
}).then(done, done);
6060
});
6161

@@ -123,39 +123,39 @@ suite("Auto Completion Tests", () => {
123123
}).then(done, done);
124124
});
125125

126-
it('Autocomplete key in middle of file 2', (done) => {
126+
it('Autocomplete key in middle of file 2', (done) => {
127127
let content = "scripts:\n postinstall: /test\n preinsta";
128128
let completion = parseSetup(content, 31);
129129
completion.then(function(result){
130130
assert.notEqual(result.items.length, 0);
131131
}).then(done, done);
132132
});
133133

134-
it('Autocomplete does not happen right after :', (done) => {
134+
it('Autocomplete does not happen right after :', (done) => {
135135
let content = "analytics:";
136136
let completion = parseSetup(content, 9);
137137
completion.then(function(result){
138138
assert.notEqual(result.items.length, 0);
139139
}).then(done, done);
140140
});
141141

142-
it('Autocomplete does not happen right after : under an object', (done) => {
142+
it('Autocomplete does not happen right after : under an object', (done) => {
143143
let content = "scripts:\n postinstall:";
144144
let completion = parseSetup(content, 21);
145145
completion.then(function(result){
146146
assert.notEqual(result.items.length, 0);
147147
}).then(done, done);
148148
});
149149

150-
it('Autocomplete on multi yaml documents in a single file on root', (done) => {
150+
it('Autocomplete on multi yaml documents in a single file on root', (done) => {
151151
let content = `---\nanalytics: true\n...\n---\n...`;
152152
let completion = parseSetup(content, 28);
153153
completion.then(function(result){
154154
assert.notEqual(result.items.length, 0);
155155
}).then(done, done);
156156
});
157157

158-
it('Autocomplete on multi yaml documents in a single file on scalar', (done) => {
158+
it('Autocomplete on multi yaml documents in a single file on scalar', (done) => {
159159
let content = `---\nanalytics: true\n...\n---\njson: \n...`;
160160
let completion = parseSetup(content, 34);
161161
completion.then(function(result){
@@ -166,55 +166,54 @@ suite("Auto Completion Tests", () => {
166166
});
167167
});
168168

169+
function is_EOL(c) {
170+
return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
171+
}
172+
169173
function completionHelper(document: TextDocument, textDocumentPosition){
170-
171-
//Get the string we are looking at via a substring
172-
let linePos = textDocumentPosition.line;
173-
let position = textDocumentPosition;
174-
let lineOffset = getLineOffsets(document.getText());
175-
let start = lineOffset[linePos]; //Start of where the autocompletion is happening
176-
let end = 0; //End of where the autocompletion is happening
177-
if(lineOffset[linePos+1]){
178-
end = lineOffset[linePos+1];
179-
}else{
180-
end = document.getText().length;
181-
}
182-
let textLine = document.getText().substring(start, end);
183-
184-
//Check if the string we are looking at is a node
185-
if(textLine.indexOf(":") === -1){
186-
//We need to add the ":" to load the nodes
187-
188-
let newText = "";
189-
190-
//This is for the empty line case
191-
let trimmedText = textLine.trim();
192-
if(trimmedText.length === 0 || (trimmedText.length === 1 && trimmedText[0] === '-')){
193-
194-
//Add a temp node that is in the document but we don't use at all.
195-
if(lineOffset[linePos+1]){
196-
newText = document.getText().substring(0, start+(textLine.length-1)) + "holder:\r\n" + document.getText().substr(end+2);
197-
}else{
198-
newText = document.getText().substring(0, start+(textLine.length)) + "holder:\r\n" + document.getText().substr(end+2);
199-
}
200-
174+
175+
//Get the string we are looking at via a substring
176+
let linePos = textDocumentPosition.line;
177+
let position = textDocumentPosition;
178+
let lineOffset = getLineOffsets(document.getText());
179+
let start = lineOffset[linePos]; //Start of where the autocompletion is happening
180+
let end = 0; //End of where the autocompletion is happening
181+
if(lineOffset[linePos+1]){
182+
end = lineOffset[linePos+1];
183+
}else{
184+
end = document.getText().length;
185+
}
186+
187+
while (end - 1 >= 0 && is_EOL(document.getText().charCodeAt(end - 1))) {
188+
end--;
189+
}
190+
191+
let textLine = document.getText().substring(start, end);
192+
193+
//Check if the string we are looking at is a node
194+
if(textLine.indexOf(":") === -1){
195+
//We need to add the ":" to load the nodes
196+
197+
let newText = "";
198+
199+
//This is for the empty line case
200+
let trimmedText = textLine.trim();
201+
if(trimmedText.length === 0 || (trimmedText.length === 1 && trimmedText[0] === '-')){
202+
//Add a temp node that is in the document but we don't use at all.
203+
newText = document.getText().substring(0, start+textLine.length) + "holder:\r\n" + document.getText().substr(lineOffset[linePos+1] || document.getText().length);
201204
//For when missing semi colon case
202-
}else{
203-
//Add a semicolon to the end of the current line so we can validate the node
204-
if(lineOffset[linePos+1]){
205-
newText = document.getText().substring(0, start+(textLine.length-1)) + ":\r\n" + document.getText().substr(end+2);
206-
}else{
207-
newText = document.getText().substring(0, start+(textLine.length)) + ":\r\n" + document.getText().substr(end+2);
208-
}
209-
}
210-
let jsonDocument = parseYAML(newText);
211-
return languageService.doComplete(document, position, jsonDocument);
212205
}else{
213-
214-
//All the nodes are loaded
215-
position.character = position.character - 1;
216-
let jsonDocument = parseYAML(document.getText());
217-
return languageService.doComplete(document, position, jsonDocument);
206+
//Add a semicolon to the end of the current line so we can validate the node
207+
newText = document.getText().substring(0, start+textLine.length) + ":\r\n" + document.getText().substr(lineOffset[linePos+1] || document.getText().length);
218208
}
209+
let jsonDocument = parseYAML(newText);
210+
return languageService.doComplete(document, position, jsonDocument);
211+
}else{
212+
213+
//All the nodes are loaded
214+
position.character = position.character - 1;
215+
let jsonDocument = parseYAML(document.getText());
216+
return languageService.doComplete(document, position, jsonDocument);
217+
}
219218

220219
}

0 commit comments

Comments
 (0)