Skip to content

Commit 9bde9ea

Browse files
committed
IsValidSnippetInsertionAtPosition
1 parent ea6cd93 commit 9bde9ea

File tree

9 files changed

+91
-0
lines changed

9 files changed

+91
-0
lines changed

src/harness/fourslash.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,13 @@ namespace FourSlash {
967967
}
968968
}
969969

970+
public verifySnippetInsertionAtPosition(expectedResult: boolean) {
971+
const actual = this.languageService.isValidSnippetInsertionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
972+
if (actual !== expectedResult) {
973+
this.raiseError(`verifySnippetInsertionAtPosition failed - expected result to be ${actual}`);
974+
}
975+
}
976+
970977
public verifyQuickInfoExists(negative: boolean) {
971978
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
972979
if (negative) {
@@ -2956,6 +2963,10 @@ namespace FourSlashInterface {
29562963
public isValidBraceCompletionAtPosition(openingBrace: string) {
29572964
this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace);
29582965
}
2966+
2967+
public isValidSnippetInsertionAtPosition(expectedResult: boolean) {
2968+
this.state.verifySnippetInsertionAtPosition(expectedResult);
2969+
}
29592970
}
29602971

29612972
export class Verify extends VerifyNegatable {

src/harness/harnessLanguageService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,9 @@ namespace Harness.LanguageService {
480480
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean {
481481
return unwrapJSONCallResult(this.shim.isValidBraceCompletionAtPosition(fileName, position, openingBrace));
482482
}
483+
isValidSnippetInsertionAtPosition(fileName: string, position: number): boolean {
484+
return unwrapJSONCallResult(this.shim.isValidSnippetInsertionAtPosition(fileName, position));
485+
}
483486
getEmitOutput(fileName: string): ts.EmitOutput {
484487
return unwrapJSONCallResult(this.shim.getEmitOutput(fileName));
485488
}

src/server/client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,10 @@ namespace ts.server {
603603
throw new Error("Not Implemented Yet.");
604604
}
605605

606+
isValidSnippetInsertionAtPosition(fileName: string, position: number): boolean {
607+
throw new Error("Not Implemented Yet.");
608+
}
609+
606610
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] {
607611
const lineOffset = this.positionToOneBasedLineOffset(fileName, position);
608612
const args: protocol.FileLocationRequestArgs = {

src/server/session.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ namespace ts.server {
132132
export const NameOrDottedNameSpan = "nameOrDottedNameSpan";
133133
export const BreakpointStatement = "breakpointStatement";
134134
export const CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects";
135+
export const SnippetInsertion = "snippetInsertion";
135136
}
136137

137138
export function formatMessage<T extends protocol.Message>(msg: T, logger: server.Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string {
@@ -781,6 +782,12 @@ namespace ts.server {
781782
return project.getLanguageService(/*ensureSynchronized*/ false).isValidBraceCompletionAtPosition(file, position, args.openingBrace.charCodeAt(0));
782783
}
783784

785+
private isValidSnippetInsertion(args: protocol.FileLocationRequestArgs) {
786+
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
787+
const position = this.getPosition(args, project.getScriptInfoForNormalizedPath(file));
788+
return project.getLanguageService(/*ensureSynchronized*/ false).isValidSnippetInsertionAtPosition(file, position);
789+
}
790+
784791
private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo {
785792
const { file, project } = this.getFileAndProject(args);
786793
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
@@ -1397,6 +1404,9 @@ namespace ts.server {
13971404
[CommandNames.CompletionDetails]: (request: protocol.CompletionDetailsRequest) => {
13981405
return this.requiredResponse(this.getCompletionEntryDetails(request.arguments));
13991406
},
1407+
[CommandNames.SnippetInsertion]: (request: protocol.FileLocationRequest) => {
1408+
return this.requiredResponse(this.isValidSnippetInsertion(request.arguments));
1409+
},
14001410
[CommandNames.CompileOnSaveAffectedFileList]: (request: protocol.CompileOnSaveAffectedFileListRequest) => {
14011411
return this.requiredResponse(this.getCompileOnSaveAffectedFileList(request.arguments));
14021412
},

src/server/utilities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ namespace ts.server {
195195
getFormattingEditsAfterKeystroke: (): any => throwLanguageServiceIsDisabledError(),
196196
getDocCommentTemplateAtPosition: (): any => throwLanguageServiceIsDisabledError(),
197197
isValidBraceCompletionAtPosition: (): any => throwLanguageServiceIsDisabledError(),
198+
isValidSnippetInsertionAtPosition: (): any => throwLanguageServiceIsDisabledError(),
198199
getEmitOutput: (): any => throwLanguageServiceIsDisabledError(),
199200
getProgram: (): any => throwLanguageServiceIsDisabledError(),
200201
getNonBoundSourceFile: (): any => throwLanguageServiceIsDisabledError(),

src/services/services.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,8 @@ namespace ts {
12741274

12751275
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
12761276

1277+
isValidSnippetInsertionAtPosition(fileName: string, position: number): boolean;
1278+
12771279
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
12781280

12791281
getProgram(): Program;
@@ -8635,6 +8637,11 @@ namespace ts {
86358637
return true;
86368638
}
86378639

8640+
function isValidSnippetInsertionAtPosition(fileName: string, position: number): boolean {
8641+
const completionInfo = getCompletionsAtPosition(fileName, position);
8642+
return completionInfo !== undefined && !completionInfo.isMemberCompletion;
8643+
}
8644+
86388645
function getParametersForJsDocOwningNode(commentOwner: Node): ParameterDeclaration[] {
86398646
if (isFunctionLike(commentOwner)) {
86408647
return commentOwner.parameters;
@@ -8974,6 +8981,7 @@ namespace ts {
89748981
getFormattingEditsAfterKeystroke,
89758982
getDocCommentTemplateAtPosition,
89768983
isValidBraceCompletionAtPosition,
8984+
isValidSnippetInsertionAtPosition,
89778985
getEmitOutput,
89788986
getNonBoundSourceFile,
89798987
getProgram

src/services/shims.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,13 @@ namespace ts {
245245
*/
246246
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): string;
247247

248+
/**
249+
* Returns JSON-encoded boolean to indicate whether we should support snippet insertion
250+
* at the current position.
251+
* E.g. we don't want snippets inserted in the completion list for member completions
252+
*/
253+
isValidSnippetInsertionAtPosition(fileName: string, position: number): string;
254+
248255
getEmitOutput(fileName: string): string;
249256
getEmitOutputObject(fileName: string): EmitOutput;
250257
}
@@ -820,6 +827,13 @@ namespace ts {
820827
);
821828
}
822829

830+
public isValidSnippetInsertionAtPosition(fileName: string, position: number): string {
831+
return this.forwardJSONCall(
832+
`isValidSnippetInsertionAtPosition('${fileName}', ${position})`,
833+
() => this.languageService.isValidSnippetInsertionAtPosition(fileName, position)
834+
);
835+
}
836+
823837
/// GET SMART INDENT
824838
public getIndentationAtPosition(fileName: string, position: number, options: string /*Services.EditorOptions*/): string {
825839
return this.forwardJSONCall(

tests/cases/fourslash/fourslash.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ declare namespace FourSlashInterface {
137137
definitionLocationExists(): void;
138138
verifyDefinitionsName(name: string, containerName: string): void;
139139
isValidBraceCompletionAtPosition(openingBrace?: string): void;
140+
isValidSnippetInsertionAtPosition(expectedResult: boolean): void;
140141
}
141142
class verify extends verifyNegatable {
142143
assertHasRanges(ranges: Range[]): void;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////import { /*1*/ } from "./test"; // no snippets in imports
4+
////var test = "/*2*/"; // no snippets in strings
5+
/////*3*/class A { // insert snippets
6+
//// foo(): string { return ''; }
7+
////}
8+
////
9+
////class /*4*/B extends A { // no snippets after class keyword
10+
//// bar(): string {
11+
//// /*5*/ // insert snippets
12+
//// return '';
13+
//// }
14+
////}
15+
////
16+
////class C</*6*/ U extends A, T extends A> { // no snippets at beginning of generics
17+
//// x: U;
18+
//// y = this./*7*/x; // no snippets inserted for member completions
19+
//// /*8*/ // insert snippets
20+
////}
21+
/////*9*/ // insert snippets
22+
goTo.marker("1");
23+
verify.isValidSnippetInsertionAtPosition(false);
24+
goTo.marker("2");
25+
verify.isValidSnippetInsertionAtPosition(false);
26+
goTo.marker("3");
27+
verify.isValidSnippetInsertionAtPosition(true);
28+
goTo.marker("4");
29+
verify.isValidSnippetInsertionAtPosition(false);
30+
goTo.marker("5");
31+
verify.isValidSnippetInsertionAtPosition(true);
32+
goTo.marker("6");
33+
verify.isValidSnippetInsertionAtPosition(false);
34+
goTo.marker("7");
35+
verify.isValidSnippetInsertionAtPosition(false);
36+
goTo.marker("8");
37+
verify.isValidSnippetInsertionAtPosition(true);
38+
goTo.marker("9");
39+
verify.isValidSnippetInsertionAtPosition(true);

0 commit comments

Comments
 (0)