mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add inlay hints support (#42089)
* Add signature arguments label support * Support rest parameters and destruction * make lint * Fix tuple rest parameters * Adjust name styles * Rename to inline hints * Partition inline hints * Adjust range pred * Add function expression like hints * Support configure inline hints * Display hints in single line * Add test suits and tests * Add range tests * Support more hints * Add more options * Fix logical * Add more cases * Support call chains * Rename options * Match lastest protocol * Update protocol changes * Support context value and hover message * Revert "Support context value and hover message" This reverts commit37a7089633. * Revert "Update protocol changes" This reverts commite5ca31bc30. * Add hover message * Accept baseline * Update src/services/inlineHints.ts Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com> * Update src/services/inlineHints.ts Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com> * Cache across the program * Fix possible undefined * Update protocol changes * Fix missing property * Make lint happy * Avoid call chain hints * I'm bad * Add whitespace before type * Add more tests * Should care about jsdoc * Support complex rest parameter * Avoid module symbol hints * Care about leading comments * Fix CR issues * Avoid changes * Simplify comments contains * Fix CR issues * Accept baseline * Check parameter name before create regex * Rename option * Avoid makers * Skip parens for argument * Fix CR issues * Fix enums * Accept baseline Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
co-authored by
Daniel Rosenwasser
parent
2767ab3e3e
commit
66b4ba4b35
@@ -428,6 +428,7 @@ namespace ts {
|
||||
return node ? getTypeFromTypeNode(node) : errorType;
|
||||
},
|
||||
getParameterType: getTypeAtPosition,
|
||||
getParameterIdentifierNameAtPosition,
|
||||
getPromisedTypeOfPromise,
|
||||
getAwaitedType: type => getAwaitedType(type),
|
||||
getReturnTypeOfSignature,
|
||||
@@ -30352,6 +30353,39 @@ namespace ts {
|
||||
return restParameter.escapedName;
|
||||
}
|
||||
|
||||
function getParameterIdentifierNameAtPosition(signature: Signature, pos: number): [parameterName: __String, isRestParameter: boolean] | undefined {
|
||||
const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
|
||||
if (pos < paramCount) {
|
||||
const param = signature.parameters[pos];
|
||||
return isParameterDeclarationWithIdentifierName(param) ? [param.escapedName, false] : undefined;
|
||||
}
|
||||
|
||||
const restParameter = signature.parameters[paramCount] || unknownSymbol;
|
||||
if (!isParameterDeclarationWithIdentifierName(restParameter)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const restType = getTypeOfSymbol(restParameter);
|
||||
if (isTupleType(restType)) {
|
||||
const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
|
||||
const index = pos - paramCount;
|
||||
const associatedName = associatedNames?.[index];
|
||||
const isRestTupleElement = !!associatedName?.dotDotDotToken;
|
||||
return associatedName ? [
|
||||
getTupleElementLabel(associatedName),
|
||||
isRestTupleElement
|
||||
] : undefined;
|
||||
}
|
||||
|
||||
if (pos === paramCount) {
|
||||
return [restParameter.escapedName, true];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isParameterDeclarationWithIdentifierName(symbol: Symbol) {
|
||||
return symbol.valueDeclaration && isParameter(symbol.valueDeclaration) && isIdentifier(symbol.valueDeclaration.name);
|
||||
}
|
||||
function isValidDeclarationForTupleLabel(d: Declaration): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier }) {
|
||||
return d.kind === SyntaxKind.NamedTupleMember || (isParameter(d) && d.name && isIdentifier(d.name));
|
||||
}
|
||||
|
||||
@@ -4104,6 +4104,7 @@ namespace ts {
|
||||
* Returns `any` if the index is not valid.
|
||||
*/
|
||||
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
|
||||
/* @internal */ getParameterIdentifierNameAtPosition(signature: Signature, parameterIndex: number): [parameterName: __String, isRestParameter: boolean] | undefined;
|
||||
getNullableType(type: Type, flags: TypeFlags): Type;
|
||||
getNonNullableType(type: Type): Type;
|
||||
/* @internal */ getNonOptionalType(type: Type): Type;
|
||||
|
||||
@@ -1232,6 +1232,11 @@ namespace ts {
|
||||
return node && isFunctionLikeDeclarationKind(node.kind);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isBooleanLiteral(node: Node): node is BooleanLiteral {
|
||||
return node.kind === SyntaxKind.TrueKeyword || node.kind === SyntaxKind.FalseKeyword;
|
||||
}
|
||||
|
||||
function isFunctionLikeDeclarationKind(kind: SyntaxKind): boolean {
|
||||
switch (kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
|
||||
@@ -644,6 +644,20 @@ namespace ts.server {
|
||||
|
||||
applyCodeActionCommand = notImplemented;
|
||||
|
||||
provideInlayHints(file: string, span: TextSpan): InlayHint[] {
|
||||
const { start, length } = span;
|
||||
const args: protocol.InlayHintsRequestArgs = { file, start, length };
|
||||
|
||||
const request = this.processRequest<protocol.InlayHintsRequest>(CommandNames.ProvideInlayHints, args);
|
||||
const response = this.processResponse<protocol.InlayHintsResponse>(request);
|
||||
|
||||
return response.body!.map(item => ({ // TODO: GH#18217
|
||||
...item,
|
||||
kind: item.kind as InlayHintKind | undefined,
|
||||
position: this.lineOffsetToPosition(file, item.position),
|
||||
}));
|
||||
}
|
||||
|
||||
private createFileLocationOrRangeRequestArgs(positionOrRange: number | TextRange, fileName: string): protocol.FileLocationOrRangeRequestArgs {
|
||||
return typeof positionOrRange === "number"
|
||||
? this.createFileLocationRequestArgs(fileName, positionOrRange)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
namespace FourSlash {
|
||||
import ArrayOrSingle = FourSlashInterface.ArrayOrSingle;
|
||||
|
||||
@@ -836,6 +837,22 @@ namespace FourSlash {
|
||||
});
|
||||
}
|
||||
|
||||
public verifyInlayHints(expected: readonly FourSlashInterface.VerifyInlayHintsOptions[], span: ts.TextSpan = { start: 0, length: this.activeFile.content.length }, preference?: ts.InlayHintsOptions) {
|
||||
const hints = this.languageService.provideInlayHints(this.activeFile.fileName, span, preference);
|
||||
assert.equal(hints.length, expected.length, "Number of hints");
|
||||
|
||||
const sortHints = (a: ts.InlayHint, b: ts.InlayHint) => {
|
||||
return a.position - b.position;
|
||||
};
|
||||
ts.zipWith(hints.sort(sortHints), [...expected].sort(sortHints), (actual, expected) => {
|
||||
assert.equal(actual.text, expected.text, "Text");
|
||||
assert.equal(actual.position, expected.position, "Position");
|
||||
assert.equal(actual.kind, expected.kind, "Kind");
|
||||
assert.equal(actual.whitespaceBefore, expected.whitespaceBefore, "whitespaceBefore");
|
||||
assert.equal(actual.whitespaceAfter, expected.whitespaceAfter, "whitespaceAfter");
|
||||
});
|
||||
}
|
||||
|
||||
public verifyCompletions(options: FourSlashInterface.VerifyCompletionsOptions) {
|
||||
if (options.marker === undefined) {
|
||||
this.verifyCompletionsWorker(options);
|
||||
|
||||
@@ -251,6 +251,10 @@ namespace FourSlashInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public getInlayHints(expected: readonly VerifyInlayHintsOptions[], span: ts.TextSpan, preference?: ts.InlayHintsOptions) {
|
||||
this.state.verifyInlayHints(expected, span, preference);
|
||||
}
|
||||
|
||||
public quickInfoIs(expectedText: string, expectedDocumentation?: string) {
|
||||
this.state.verifyQuickInfoString(expectedText, expectedDocumentation);
|
||||
}
|
||||
@@ -1667,6 +1671,14 @@ namespace FourSlashInterface {
|
||||
readonly containerKind?: ts.ScriptElementKind;
|
||||
}
|
||||
|
||||
export interface VerifyInlayHintsOptions {
|
||||
text: string;
|
||||
position: number;
|
||||
kind?: ts.InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
}
|
||||
|
||||
export type ArrayOrSingle<T> = T | readonly T[];
|
||||
|
||||
export interface VerifyCompletionListContainsOptions extends ts.UserPreferences {
|
||||
|
||||
@@ -599,6 +599,9 @@ namespace Harness.LanguageService {
|
||||
provideCallHierarchyOutgoingCalls(fileName: string, position: number) {
|
||||
return unwrapJSONCallResult(this.shim.provideCallHierarchyOutgoingCalls(fileName, position));
|
||||
}
|
||||
provideInlayHints(fileName: string, span: ts.TextSpan, preference: ts.InlayHintsOptions) {
|
||||
return unwrapJSONCallResult(this.shim.provideInlayHints(fileName, span, preference));
|
||||
}
|
||||
getEmitOutput(fileName: string): ts.EmitOutput {
|
||||
return unwrapJSONCallResult(this.shim.getEmitOutput(fileName));
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ namespace ts.server.protocol {
|
||||
PrepareCallHierarchy = "prepareCallHierarchy",
|
||||
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
|
||||
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
|
||||
ProvideInlayHints = "provideInlayHints"
|
||||
|
||||
// NOTE: If updating this, be sure to also update `allCommandNames` in `testRunner/unittests/tsserver/session.ts`.
|
||||
}
|
||||
@@ -2549,6 +2550,40 @@ namespace ts.server.protocol {
|
||||
body?: SignatureHelpItems;
|
||||
}
|
||||
|
||||
export const enum InlayHintKind {
|
||||
Type = "Type",
|
||||
Parameter = "Parameter",
|
||||
Enum = "Enum",
|
||||
}
|
||||
|
||||
export interface InlayHintsRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* Start position of the span.
|
||||
*/
|
||||
start: number;
|
||||
/**
|
||||
* Length of the span.
|
||||
*/
|
||||
length: number;
|
||||
}
|
||||
|
||||
export interface InlayHintsRequest extends Request {
|
||||
command: CommandTypes.ProvideInlayHints;
|
||||
arguments: InlayHintsRequestArgs;
|
||||
}
|
||||
|
||||
export interface InlayHintItem {
|
||||
text: string;
|
||||
position: Location;
|
||||
kind?: InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
}
|
||||
|
||||
export interface InlayHintsResponse extends Response {
|
||||
body?: InlayHintItem[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous request for semantic diagnostics of one file.
|
||||
*/
|
||||
|
||||
@@ -1450,6 +1450,17 @@ namespace ts.server {
|
||||
});
|
||||
}
|
||||
|
||||
private provideInlayHints(args: protocol.InlayHintsRequestArgs) {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
const hints = languageService.provideInlayHints(file, args, this.getPreferences(file));
|
||||
|
||||
return hints.map(hint => ({
|
||||
...hint,
|
||||
position: scriptInfo.positionToLineOffset(hint.position),
|
||||
}));
|
||||
}
|
||||
|
||||
private setCompilerOptionsForInferredProjects(args: protocol.SetCompilerOptionsForInferredProjectsArgs): void {
|
||||
this.projectService.setCompilerOptionsForInferredProjects(args.options, args.projectRootPath);
|
||||
}
|
||||
@@ -2963,6 +2974,9 @@ namespace ts.server {
|
||||
[CommandNames.UncommentSelectionFull]: (request: protocol.UncommentSelectionRequest) => {
|
||||
return this.requiredResponse(this.uncommentSelection(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.ProvideInlayHints]: (request: protocol.InlayHintsRequest) => {
|
||||
return this.requiredResponse(this.provideInlayHints(request.arguments));
|
||||
}
|
||||
}));
|
||||
|
||||
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
/* @internal */
|
||||
namespace ts.InlayHints {
|
||||
|
||||
const maxHintsLength = 30;
|
||||
|
||||
const leadingParameterNameCommentRegexFactory = (name: string) => {
|
||||
return new RegExp(`^\\s?/\\*\\*?\\s?${name}\\s?\\*\\/\\s?$`);
|
||||
};
|
||||
|
||||
function shouldShowParameterNameHints(preferences: InlayHintsOptions) {
|
||||
return preferences.includeInlayParameterNameHints === "literals" || preferences.includeInlayParameterNameHints === "all";
|
||||
}
|
||||
|
||||
function shouldShowLiteralParameterNameHintsOnly(preferences: InlayHintsOptions) {
|
||||
return preferences.includeInlayParameterNameHints === "literals";
|
||||
}
|
||||
|
||||
export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
|
||||
const { file, program, span, cancellationToken, preferences } = context;
|
||||
const sourceFileText = file.text;
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
|
||||
const checker = program.getTypeChecker();
|
||||
const result: InlayHint[] = [];
|
||||
|
||||
visitor(file);
|
||||
return result;
|
||||
|
||||
function visitor(node: Node): true | undefined {
|
||||
if (!node || node.getFullWidth() === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
}
|
||||
|
||||
if (!textSpanIntersectsWith(span, node.pos, node.getFullWidth())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTypeNode(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preferences.includeInlayVariableTypeHints && isVariableDeclaration(node)) {
|
||||
visitVariableLikeDeclaration(node);
|
||||
}
|
||||
else if (preferences.includeInlayPropertyDeclarationTypeHints && isPropertyDeclaration(node)) {
|
||||
visitVariableLikeDeclaration(node);
|
||||
}
|
||||
else if (preferences.includeInlayEnumMemberValueHints && isEnumMember(node)) {
|
||||
visitEnumMember(node);
|
||||
}
|
||||
else if (shouldShowParameterNameHints(preferences) && (isCallExpression(node) || isNewExpression(node))) {
|
||||
visitCallOrNewExpression(node);
|
||||
}
|
||||
else {
|
||||
if (preferences.includeInlayFunctionParameterTypeHints && isFunctionExpressionLike(node)) {
|
||||
visitFunctionExpressionLikeForParameterType(node);
|
||||
}
|
||||
if (preferences.includeInlayFunctionLikeReturnTypeHints && isFunctionDeclarationLike(node)) {
|
||||
visitFunctionDeclarationLikeForReturnType(node);
|
||||
}
|
||||
}
|
||||
return forEachChild(node, visitor);
|
||||
}
|
||||
|
||||
function isFunctionExpressionLike(node: Node): node is ArrowFunction | FunctionExpression {
|
||||
return isArrowFunction(node) || isFunctionExpression(node);
|
||||
}
|
||||
|
||||
function isFunctionDeclarationLike(node: Node): node is FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration {
|
||||
return isArrowFunction(node) || isFunctionExpression(node) || isFunctionDeclaration(node) || isMethodDeclaration(node);
|
||||
}
|
||||
|
||||
function addParameterHints(text: string, position: number, isFirstVariadicArgument: boolean) {
|
||||
result.push({
|
||||
text: `${isFirstVariadicArgument ? "..." : ""}${truncation(text, maxHintsLength)}:`,
|
||||
position,
|
||||
kind: InlayHintKind.Parameter,
|
||||
whitespaceAfter: true,
|
||||
});
|
||||
}
|
||||
|
||||
function addTypeHints(text: string, position: number) {
|
||||
result.push({
|
||||
text: `: ${truncation(text, maxHintsLength)}`,
|
||||
position,
|
||||
kind: InlayHintKind.Type,
|
||||
whitespaceBefore: true,
|
||||
});
|
||||
}
|
||||
|
||||
function addEnumMemberValueHints(text: string, position: number) {
|
||||
result.push({
|
||||
text: `= ${truncation(text, maxHintsLength)}`,
|
||||
position,
|
||||
kind: InlayHintKind.Enum,
|
||||
whitespaceBefore: true,
|
||||
});
|
||||
}
|
||||
|
||||
function visitEnumMember(member: EnumMember) {
|
||||
if (member.initializer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const enumValue = checker.getConstantValue(member);
|
||||
if (enumValue !== undefined) {
|
||||
addEnumMemberValueHints(enumValue.toString(), member.end);
|
||||
}
|
||||
}
|
||||
|
||||
function isModuleReferenceType(type: Type) {
|
||||
return type.symbol && (type.symbol.flags & SymbolFlags.Module);
|
||||
}
|
||||
|
||||
function visitVariableLikeDeclaration(decl: VariableDeclaration | PropertyDeclaration) {
|
||||
const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(decl);
|
||||
if (effectiveTypeAnnotation || !decl.initializer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const declarationType = checker.getTypeAtLocation(decl);
|
||||
if (isModuleReferenceType(declarationType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeDisplayString = printTypeInSingleLine(declarationType);
|
||||
if (typeDisplayString) {
|
||||
addTypeHints(typeDisplayString, decl.name.end);
|
||||
}
|
||||
}
|
||||
|
||||
function visitCallOrNewExpression(expr: CallExpression | NewExpression) {
|
||||
const args = expr.arguments;
|
||||
if (!args || !args.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const candidates: Signature[] = [];
|
||||
const signature = checker.getResolvedSignatureForSignatureHelp(expr, candidates);
|
||||
if (!signature || !candidates.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < args.length; ++i) {
|
||||
const originalArg = args[i];
|
||||
const arg = skipParentheses(originalArg);
|
||||
if (shouldShowLiteralParameterNameHintsOnly(preferences) && !isHintableExpression(arg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const identifierNameInfo = checker.getParameterIdentifierNameAtPosition(signature, i);
|
||||
if (identifierNameInfo) {
|
||||
const [parameterName, isFirstVariadicArgument] = identifierNameInfo;
|
||||
const isParameterNameNotSameAsArgument = preferences.includeInlayParameterNameHintsWhenArgumentMatchesName || !isIdentifier(arg) || arg.text !== parameterName;
|
||||
if (!isParameterNameNotSameAsArgument && !isFirstVariadicArgument) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = unescapeLeadingUnderscores(parameterName);
|
||||
if (leadingCommentsContainsParameterName(arg, name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addParameterHints(name, originalArg.getStart(), isFirstVariadicArgument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function leadingCommentsContainsParameterName(node: Node, name: string) {
|
||||
if (!isIdentifierText(name, compilerOptions.target, getLanguageVariant(file.scriptKind))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ranges = getLeadingCommentRanges(sourceFileText, node.pos);
|
||||
if (!ranges?.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const regex = leadingParameterNameCommentRegexFactory(name);
|
||||
return some(ranges, range => regex.test(sourceFileText.substring(range.pos, range.end)));
|
||||
}
|
||||
|
||||
function isHintableExpression(node: Node) {
|
||||
return isLiteralExpression(node) || isBooleanLiteral(node) || isFunctionExpressionLike(node) || isObjectLiteralExpression(node) || isArrayLiteralExpression(node);
|
||||
}
|
||||
|
||||
function visitFunctionDeclarationLikeForReturnType(decl: ArrowFunction | FunctionExpression | MethodDeclaration | FunctionDeclaration) {
|
||||
if (isArrowFunction(decl)) {
|
||||
if (!findChildOfKind(decl, SyntaxKind.OpenParenToken, file)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const effectiveTypeAnnotation = getEffectiveReturnTypeNode(decl);
|
||||
if (effectiveTypeAnnotation || !decl.body) {
|
||||
return;
|
||||
}
|
||||
|
||||
const type = checker.getTypeAtLocation(decl);
|
||||
const signatures = checker.getSignaturesOfType(type, SignatureKind.Call);
|
||||
const signature = firstOrUndefined(signatures);
|
||||
if (!signature) {
|
||||
return;
|
||||
}
|
||||
|
||||
const returnType = checker.getReturnTypeOfSignature(signature);
|
||||
if (isModuleReferenceType(returnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeDisplayString = printTypeInSingleLine(returnType);
|
||||
if (!typeDisplayString) {
|
||||
return;
|
||||
}
|
||||
|
||||
addTypeHints(typeDisplayString, getTypeAnnotationPosition(decl));
|
||||
}
|
||||
|
||||
function getTypeAnnotationPosition(decl: ArrowFunction | FunctionExpression | MethodDeclaration | FunctionDeclaration) {
|
||||
const closeParenToken = findChildOfKind(decl, SyntaxKind.CloseParenToken, file);
|
||||
if (closeParenToken) {
|
||||
return closeParenToken.end;
|
||||
}
|
||||
return decl.parameters.end;
|
||||
}
|
||||
|
||||
function visitFunctionExpressionLikeForParameterType(expr: ArrowFunction | FunctionExpression) {
|
||||
if (!expr.parameters.length || expr.parameters.every(param => !!getEffectiveTypeAnnotationNode(param))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const contextualType = checker.getContextualType(expr);
|
||||
if (!contextualType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const signatures = checker.getSignaturesOfType(contextualType, SignatureKind.Call);
|
||||
const signature = firstOrUndefined(signatures);
|
||||
if (!signature) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < expr.parameters.length && i < signature.parameters.length; ++i) {
|
||||
const param = expr.parameters[i];
|
||||
const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(param);
|
||||
|
||||
if (effectiveTypeAnnotation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const typeDisplayString = getParameterDeclarationTypeDisplayString(signature.parameters[i]);
|
||||
if (!typeDisplayString) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addTypeHints(typeDisplayString, param.end);
|
||||
}
|
||||
}
|
||||
|
||||
function getParameterDeclarationTypeDisplayString(symbol: Symbol) {
|
||||
const valueDeclaration = symbol.valueDeclaration;
|
||||
if (!valueDeclaration || !isParameter(valueDeclaration)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const signatureParamType = checker.getTypeOfSymbolAtLocation(symbol, valueDeclaration);
|
||||
if (isModuleReferenceType(signatureParamType)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return printTypeInSingleLine(signatureParamType);
|
||||
}
|
||||
|
||||
function truncation(text: string, maxLength: number) {
|
||||
if (text.length > maxLength) {
|
||||
return text.substr(0, maxLength - "...".length) + "...";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function printTypeInSingleLine(type: Type) {
|
||||
const flags = NodeBuilderFlags.IgnoreErrors | TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
|
||||
const options: PrinterOptions = { removeComments: true };
|
||||
const printer = createPrinter(options);
|
||||
|
||||
return usingSingleLineStringWriter(writer => {
|
||||
const typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer);
|
||||
Debug.assertIsDefined(typeNode, "should always get typenode");
|
||||
printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ file, writer);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1188,6 +1188,7 @@ namespace ts {
|
||||
"prepareCallHierarchy",
|
||||
"provideCallHierarchyIncomingCalls",
|
||||
"provideCallHierarchyOutgoingCalls",
|
||||
"provideInlayHints"
|
||||
];
|
||||
|
||||
const invalidOperationsInSyntacticMode: readonly (keyof LanguageService)[] = [
|
||||
@@ -2504,6 +2505,17 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function getInlayHintsContext(file: SourceFile, span: TextSpan, preferences: UserPreferences): InlayHintsContext {
|
||||
return {
|
||||
file,
|
||||
program: getProgram()!,
|
||||
host,
|
||||
span,
|
||||
preferences,
|
||||
cancellationToken,
|
||||
};
|
||||
}
|
||||
|
||||
function getSmartSelectionRange(fileName: string, position: number): SelectionRange {
|
||||
return SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName));
|
||||
}
|
||||
@@ -2558,6 +2570,12 @@ namespace ts {
|
||||
return declaration ? CallHierarchy.getOutgoingCalls(program, declaration) : [];
|
||||
}
|
||||
|
||||
function provideInlayHints(fileName: string, span: TextSpan, preferences: InlayHintsOptions = emptyOptions): InlayHint[] {
|
||||
synchronizeHostData();
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
return InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences));
|
||||
}
|
||||
|
||||
const ls: LanguageService = {
|
||||
dispose,
|
||||
cleanupSemanticCache,
|
||||
@@ -2623,6 +2641,7 @@ namespace ts {
|
||||
toggleMultilineComment,
|
||||
commentSelection,
|
||||
uncommentSelection,
|
||||
provideInlayHints,
|
||||
};
|
||||
|
||||
switch (languageServiceMode) {
|
||||
|
||||
@@ -280,7 +280,7 @@ namespace ts {
|
||||
prepareCallHierarchy(fileName: string, position: number): string;
|
||||
provideCallHierarchyIncomingCalls(fileName: string, position: number): string;
|
||||
provideCallHierarchyOutgoingCalls(fileName: string, position: number): string;
|
||||
|
||||
provideInlayHints(fileName: string, span: TextSpan, preference: InlayHintsOptions | undefined): string;
|
||||
getEmitOutput(fileName: string): string;
|
||||
getEmitOutputObject(fileName: string): EmitOutput;
|
||||
|
||||
@@ -1067,6 +1067,13 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
public provideInlayHints(fileName: string, span: TextSpan, preference: InlayHintsOptions | undefined): string {
|
||||
return this.forwardJSONCall(
|
||||
`provideInlayHints('${fileName}', '${JSON.stringify(span)}', ${JSON.stringify(preference)})`,
|
||||
() => this.languageService.provideInlayHints(fileName, span, preference)
|
||||
);
|
||||
}
|
||||
|
||||
/// Emit
|
||||
public getEmitOutput(fileName: string): string {
|
||||
return this.forwardJSONCall(
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"rename.ts",
|
||||
"smartSelection.ts",
|
||||
"signatureHelp.ts",
|
||||
"inlayHints.ts",
|
||||
"sourcemaps.ts",
|
||||
"suggestionDiagnostics.ts",
|
||||
"symbolDisplay.ts",
|
||||
|
||||
@@ -487,6 +487,8 @@ namespace ts {
|
||||
provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[];
|
||||
provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[];
|
||||
|
||||
provideInlayHints(fileName: string, span: TextSpan, preferences: UserPreferences | undefined): InlayHint[]
|
||||
|
||||
getOutliningSpans(fileName: string): OutliningSpan[];
|
||||
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
|
||||
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
|
||||
@@ -570,6 +572,16 @@ namespace ts {
|
||||
includeInsertTextCompletions?: boolean;
|
||||
}
|
||||
|
||||
export interface InlayHintsOptions extends UserPreferences {
|
||||
readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
|
||||
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
|
||||
readonly includeInlayFunctionParameterTypeHints?: boolean,
|
||||
readonly includeInlayVariableTypeHints?: boolean;
|
||||
readonly includeInlayPropertyDeclarationTypeHints?: boolean;
|
||||
readonly includeInlayFunctionLikeReturnTypeHints?: boolean;
|
||||
readonly includeInlayEnumMemberValueHints?: boolean;
|
||||
}
|
||||
|
||||
export type SignatureHelpTriggerCharacter = "," | "(" | "<";
|
||||
export type SignatureHelpRetriggerCharacter = SignatureHelpTriggerCharacter | ")";
|
||||
|
||||
@@ -693,6 +705,20 @@ namespace ts {
|
||||
fromSpans: TextSpan[];
|
||||
}
|
||||
|
||||
export const enum InlayHintKind {
|
||||
Type = "Type",
|
||||
Parameter = "Parameter",
|
||||
Enum = "Enum",
|
||||
}
|
||||
|
||||
export interface InlayHint {
|
||||
text: string;
|
||||
position: number;
|
||||
kind?: InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
}
|
||||
|
||||
export interface TodoCommentDescriptor {
|
||||
text: string;
|
||||
priority: number;
|
||||
@@ -1556,4 +1582,13 @@ namespace ts {
|
||||
triggerReason?: RefactorTriggerReason;
|
||||
kind?: string;
|
||||
}
|
||||
|
||||
export interface InlayHintsContext {
|
||||
file: SourceFile;
|
||||
program: Program;
|
||||
cancellationToken: CancellationToken;
|
||||
host: LanguageServiceHost;
|
||||
span: TextSpan;
|
||||
preferences: InlayHintsOptions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +278,7 @@ namespace ts.server {
|
||||
CommandNames.ToggleMultilineComment,
|
||||
CommandNames.CommentSelection,
|
||||
CommandNames.UncommentSelection,
|
||||
CommandNames.ProvideInlayHints
|
||||
];
|
||||
|
||||
it("should not throw when commands are executed with invalid arguments", () => {
|
||||
|
||||
+62
-1
@@ -5676,6 +5676,7 @@ declare namespace ts {
|
||||
prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined;
|
||||
provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[];
|
||||
provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[];
|
||||
provideInlayHints(fileName: string, span: TextSpan, preferences: UserPreferences | undefined): InlayHint[];
|
||||
getOutliningSpans(fileName: string): OutliningSpan[];
|
||||
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
|
||||
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
|
||||
@@ -5737,6 +5738,15 @@ declare namespace ts {
|
||||
/** @deprecated Use includeCompletionsWithInsertText */
|
||||
includeInsertTextCompletions?: boolean;
|
||||
}
|
||||
interface InlayHintsOptions extends UserPreferences {
|
||||
readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
|
||||
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
|
||||
readonly includeInlayFunctionParameterTypeHints?: boolean;
|
||||
readonly includeInlayVariableTypeHints?: boolean;
|
||||
readonly includeInlayPropertyDeclarationTypeHints?: boolean;
|
||||
readonly includeInlayFunctionLikeReturnTypeHints?: boolean;
|
||||
readonly includeInlayEnumMemberValueHints?: boolean;
|
||||
}
|
||||
type SignatureHelpTriggerCharacter = "," | "(" | "<";
|
||||
type SignatureHelpRetriggerCharacter = SignatureHelpTriggerCharacter | ")";
|
||||
interface SignatureHelpItemsOptions {
|
||||
@@ -5842,6 +5852,18 @@ declare namespace ts {
|
||||
to: CallHierarchyItem;
|
||||
fromSpans: TextSpan[];
|
||||
}
|
||||
enum InlayHintKind {
|
||||
Type = "Type",
|
||||
Parameter = "Parameter",
|
||||
Enum = "Enum"
|
||||
}
|
||||
interface InlayHint {
|
||||
text: string;
|
||||
position: number;
|
||||
kind?: InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
}
|
||||
interface TodoCommentDescriptor {
|
||||
text: string;
|
||||
priority: number;
|
||||
@@ -6507,6 +6529,14 @@ declare namespace ts {
|
||||
jsxAttributeStringLiteralValue = 24,
|
||||
bigintLiteral = 25
|
||||
}
|
||||
interface InlayHintsContext {
|
||||
file: SourceFile;
|
||||
program: Program;
|
||||
cancellationToken: CancellationToken;
|
||||
host: LanguageServiceHost;
|
||||
span: TextSpan;
|
||||
preferences: InlayHintsOptions;
|
||||
}
|
||||
}
|
||||
declare namespace ts {
|
||||
/** The classifier is used for syntactic highlighting in editors via the TSServer */
|
||||
@@ -6798,7 +6828,8 @@ declare namespace ts.server.protocol {
|
||||
UncommentSelection = "uncommentSelection",
|
||||
PrepareCallHierarchy = "prepareCallHierarchy",
|
||||
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
|
||||
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls"
|
||||
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
|
||||
ProvideInlayHints = "provideInlayHints"
|
||||
}
|
||||
/**
|
||||
* A TypeScript Server message
|
||||
@@ -8670,6 +8701,35 @@ declare namespace ts.server.protocol {
|
||||
interface SignatureHelpResponse extends Response {
|
||||
body?: SignatureHelpItems;
|
||||
}
|
||||
enum InlayHintKind {
|
||||
Type = "Type",
|
||||
Parameter = "Parameter",
|
||||
Enum = "Enum"
|
||||
}
|
||||
interface InlayHintsRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* Start position of the span.
|
||||
*/
|
||||
start: number;
|
||||
/**
|
||||
* Length of the span.
|
||||
*/
|
||||
length: number;
|
||||
}
|
||||
interface InlayHintsRequest extends Request {
|
||||
command: CommandTypes.ProvideInlayHints;
|
||||
arguments: InlayHintsRequestArgs;
|
||||
}
|
||||
interface InlayHintItem {
|
||||
text: string;
|
||||
position: Location;
|
||||
kind?: InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
}
|
||||
interface InlayHintsResponse extends Response {
|
||||
body?: InlayHintItem[];
|
||||
}
|
||||
/**
|
||||
* Synchronous request for semantic diagnostics of one file.
|
||||
*/
|
||||
@@ -10300,6 +10360,7 @@ declare namespace ts.server {
|
||||
private getSuggestionDiagnosticsSync;
|
||||
private getJsxClosingTag;
|
||||
private getDocumentHighlights;
|
||||
private provideInlayHints;
|
||||
private setCompilerOptionsForInferredProjects;
|
||||
private getProjectInfo;
|
||||
private getProjectInfoWorker;
|
||||
|
||||
+30
@@ -5676,6 +5676,7 @@ declare namespace ts {
|
||||
prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined;
|
||||
provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[];
|
||||
provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[];
|
||||
provideInlayHints(fileName: string, span: TextSpan, preferences: UserPreferences | undefined): InlayHint[];
|
||||
getOutliningSpans(fileName: string): OutliningSpan[];
|
||||
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
|
||||
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
|
||||
@@ -5737,6 +5738,15 @@ declare namespace ts {
|
||||
/** @deprecated Use includeCompletionsWithInsertText */
|
||||
includeInsertTextCompletions?: boolean;
|
||||
}
|
||||
interface InlayHintsOptions extends UserPreferences {
|
||||
readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
|
||||
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
|
||||
readonly includeInlayFunctionParameterTypeHints?: boolean;
|
||||
readonly includeInlayVariableTypeHints?: boolean;
|
||||
readonly includeInlayPropertyDeclarationTypeHints?: boolean;
|
||||
readonly includeInlayFunctionLikeReturnTypeHints?: boolean;
|
||||
readonly includeInlayEnumMemberValueHints?: boolean;
|
||||
}
|
||||
type SignatureHelpTriggerCharacter = "," | "(" | "<";
|
||||
type SignatureHelpRetriggerCharacter = SignatureHelpTriggerCharacter | ")";
|
||||
interface SignatureHelpItemsOptions {
|
||||
@@ -5842,6 +5852,18 @@ declare namespace ts {
|
||||
to: CallHierarchyItem;
|
||||
fromSpans: TextSpan[];
|
||||
}
|
||||
enum InlayHintKind {
|
||||
Type = "Type",
|
||||
Parameter = "Parameter",
|
||||
Enum = "Enum"
|
||||
}
|
||||
interface InlayHint {
|
||||
text: string;
|
||||
position: number;
|
||||
kind?: InlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
}
|
||||
interface TodoCommentDescriptor {
|
||||
text: string;
|
||||
priority: number;
|
||||
@@ -6507,6 +6529,14 @@ declare namespace ts {
|
||||
jsxAttributeStringLiteralValue = 24,
|
||||
bigintLiteral = 25
|
||||
}
|
||||
interface InlayHintsContext {
|
||||
file: SourceFile;
|
||||
program: Program;
|
||||
cancellationToken: CancellationToken;
|
||||
host: LanguageServiceHost;
|
||||
span: TextSpan;
|
||||
preferences: InlayHintsOptions;
|
||||
}
|
||||
}
|
||||
declare namespace ts {
|
||||
/** The classifier is used for syntactic highlighting in editors via the TSServer */
|
||||
|
||||
@@ -66,6 +66,12 @@ declare module ts {
|
||||
Smart = 2,
|
||||
}
|
||||
|
||||
const enum InlayHintKind {
|
||||
Type = "Type",
|
||||
Parameter = "Parameter",
|
||||
Enum = "Enum",
|
||||
}
|
||||
|
||||
enum SemicolonPreference {
|
||||
Ignore = "ignore",
|
||||
Insert = "insert",
|
||||
@@ -396,6 +402,10 @@ declare namespace FourSlashInterface {
|
||||
start: number;
|
||||
length: number;
|
||||
}, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: { name: string, text?: string }[] | undefined): void;
|
||||
getInlayHints(expected: readonly VerifyInlayHintsOptions[], textSpan?: {
|
||||
start: number;
|
||||
length: number;
|
||||
}, preference?: InlayHintsOptions);
|
||||
getSyntacticDiagnostics(expected: ReadonlyArray<Diagnostic>): void;
|
||||
getSemanticDiagnostics(expected: ReadonlyArray<Diagnostic>): void;
|
||||
getSuggestionDiagnostics(expected: ReadonlyArray<Diagnostic>): void;
|
||||
@@ -633,6 +643,15 @@ declare namespace FourSlashInterface {
|
||||
readonly importModuleSpecifierPreference?: "shortest" | "project-relative" | "relative" | "non-relative";
|
||||
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
|
||||
}
|
||||
interface InlayHintsOptions extends UserPreferences {
|
||||
readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
|
||||
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
|
||||
readonly includeInlayFunctionParameterTypeHints?: boolean;
|
||||
readonly includeInlayVariableTypeHints?: boolean;
|
||||
readonly includeInlayPropertyDeclarationTypeHints?: boolean;
|
||||
readonly includeInlayFunctionLikeReturnTypeHints?: boolean;
|
||||
readonly includeInlayEnumMemberValueHints?: boolean;
|
||||
}
|
||||
interface CompletionsOptions {
|
||||
readonly marker?: ArrayOrSingle<string | Marker>;
|
||||
readonly isNewIdentifierLocation?: boolean;
|
||||
@@ -735,6 +754,14 @@ declare namespace FourSlashInterface {
|
||||
readonly commands?: ReadonlyArray<{}>;
|
||||
}
|
||||
|
||||
export interface VerifyInlayHintsOptions {
|
||||
text: string;
|
||||
position: number;
|
||||
kind?: VerifyInlayHintKind;
|
||||
whitespaceBefore?: boolean;
|
||||
whitespaceAfter?: boolean;
|
||||
}
|
||||
|
||||
interface VerifyNavigateToOptions {
|
||||
readonly pattern: string;
|
||||
readonly fileName?: string;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: number, b: number) {}
|
||||
//// foo(/*a*/1, /*b*/2);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// declare const unknownCall: any;
|
||||
//// unknownCall();
|
||||
|
||||
verify.getInlayHints([], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo(a: number) {
|
||||
//// return (b: number) => {
|
||||
//// return a + b
|
||||
//// }
|
||||
//// }
|
||||
//// foo(/*a*/1)(/*b*/2);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo(a: (b: number) => number) {
|
||||
//// return a(/*a*/1) + 2
|
||||
//// }
|
||||
|
||||
//// foo(/*b*/(c: number) => c + 1);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: number, b: number) {}
|
||||
//// declare const a: 1;
|
||||
//// foo(a, /*b*/2);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "all",
|
||||
includeInlayParameterNameHintsWhenArgumentMatchesName: false,
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: number, b: number) {}
|
||||
//// foo(1, 2);
|
||||
|
||||
verify.getInlayHints([], undefined, {
|
||||
includeInlayParameterNameHints: "none"
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a/*a*/ = 123;
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': 123',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a/*a*/ = 123;
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': 123',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a/*a*/ = { a: 123 };
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': { a: number; }',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// class Class {}
|
||||
//// const a/*a*/ = new Class();
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': Class',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a/*a*/ = () => 123;
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': () => number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: number, { c }: any) {}
|
||||
//// foo(/*a*/1, { c: 1});
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a = 123;
|
||||
|
||||
verify.getInlayHints([], undefined, {
|
||||
includeInlayVariableTypeHints: false
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a;
|
||||
|
||||
verify.getInlayHints([], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a/*a*/ = "I'm very very very very very very very very very long";
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: `: "I'm very very very very ve...`,
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (Im_very_very_very_very_very_very_very_long: number) {}
|
||||
//// foo(/*a*/1);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'Im_very_very_very_very_very...:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type F = (a: string, b: number) => void
|
||||
//// const f: F = (a/*a*/, b/*b*/) => { }
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': string',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (cb: (a: string) => void) {}
|
||||
//// foo((a/*a*/) => { })
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': string',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (cb: (a: Exclude<1 | 2 | 3, 1>) => void) {}
|
||||
//// foo((a/*a*/) => { })
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': 2 | 3',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: (b: (c: (d: Exclude<1 | 2 | 3, 1>) => void) => void) => void) {}
|
||||
//// foo(a/*a*/ => {
|
||||
//// a(d/*b*/ => {})
|
||||
//// })
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': (c: (d: 2 | 3) => void) => ...',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: ': 2 | 3',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type F = (a: string, b: number) => void
|
||||
//// const f: F = (a/*a*/, b: number) => { }
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': string',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: (b: (c: (d: Exclude<1 | 2 | 3, 1>) => void) => void) => void) {}
|
||||
//// foo(/*a*/a/*b*/ => {
|
||||
//// a(/*c*/d/*d*/ => {})
|
||||
//// })
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: ': (c: (d: 2 | 3) => void) => ...',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: 'c:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: ': 2 | 3',
|
||||
position: markers[3].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals",
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: number, ...b: number[]) {}
|
||||
//// foo(/*a*/1, /*b*/1, 1, 1);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: '...b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function f<T>(v: T, a: (v: T) => void) {}
|
||||
//// f(1, a/*a*/ => { })
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type F = (a: {
|
||||
//// a: number
|
||||
//// b: string
|
||||
//// }) => void
|
||||
//// const f: F = (a/*a*/) => { }
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': { a: number; b: string; }',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayFunctionParameterTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo1 (a: number, b: number) {}
|
||||
//// function foo2 (c: number, d: number) {}
|
||||
//// function foo3 (e: number, f: number) {}
|
||||
//// function foo4 (g: number, h: number) {}
|
||||
//// function foo5 (i: number, j: number) {}
|
||||
//// function foo6 (k: number, i: number) {}
|
||||
|
||||
//// function c1 () { foo1(/*a*/1, /*b*/2); }
|
||||
//// function c2 () { foo2(/*c*/1, /*d*/2); }
|
||||
//// function c3 () { foo3(/*e*/1, /*f*/2); }
|
||||
//// function c4 () { foo4(/*g*/1, /*h*/2); }
|
||||
//// function c5 () { foo5(/*i*/1, /*j*/2); }
|
||||
//// function c6 () { foo6(/*k*/1, /*l*/2); }
|
||||
|
||||
const start = test.markerByName('c');
|
||||
const end = test.markerByName('h');
|
||||
const span = { start: start.position, length: end.position - start.position };
|
||||
|
||||
verify.getInlayHints(
|
||||
['c', 'd', 'e', 'f', 'g', 'h'].map(mark => {
|
||||
return {
|
||||
text: `${mark}:`,
|
||||
position: test.markerByName(mark).position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
}), span, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
})
|
||||
@@ -0,0 +1,31 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo1 (a: number, b: number) {}
|
||||
//// function foo2 (c: number, d: number) {}
|
||||
//// function foo3 (e: number, f: number) {}
|
||||
//// function foo4 (g: number, h: number) {}
|
||||
//// function foo5 (i: number, j: number) {}
|
||||
//// function foo6 (k: number, l: number) {}
|
||||
|
||||
//// foo1(/*a*/1, /*b*/2);
|
||||
//// foo2(/*c*/1, /*d*/2);
|
||||
//// foo3(/*e*/1, /*f*/2);
|
||||
//// foo4(/*g*/1, /*h*/2);
|
||||
//// foo5(/*i*/1, /*j*/2);
|
||||
//// foo6(/*k*/1, /*l*/2);
|
||||
|
||||
const start = test.markerByName('c');
|
||||
const end = test.markerByName('h');
|
||||
const span = { start: start.position, length: end.position - start.position };
|
||||
|
||||
verify.getInlayHints(
|
||||
['c', 'd', 'e', 'f', 'g', 'h'].map(mark => {
|
||||
return {
|
||||
text: `${mark}:`,
|
||||
position: test.markerByName(mark).position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
}), span, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (v: any) {}
|
||||
|
||||
//// foo(/*a*/1);
|
||||
//// foo(/*b*/'');
|
||||
//// foo(/*c*/true);
|
||||
//// foo(/*d*/() => 1);
|
||||
//// foo(/*e*/function () { return 1 });
|
||||
//// foo(/*f*/{});
|
||||
//// foo(/*g*/{ a: 1 });
|
||||
//// foo(/*h*/[]);
|
||||
//// foo(/*i*/[1]);
|
||||
|
||||
//// foo(foo);
|
||||
//// foo(/*j*/(1));
|
||||
//// foo(foo(/*k*/1));
|
||||
|
||||
const markers = test.markers();
|
||||
|
||||
verify.getInlayHints(
|
||||
markers.map(m => ({
|
||||
text: 'v:',
|
||||
position: m.position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
})) , undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (v: any) {}
|
||||
|
||||
//// foo(/*a*/1);
|
||||
//// foo(/*b*/'');
|
||||
//// foo(/*c*/true);
|
||||
//// foo(/*d*/() => 1);
|
||||
//// foo(/*e*/function () { return 1 });
|
||||
//// foo(/*f*/{});
|
||||
//// foo(/*g*/{ a: 1 });
|
||||
//// foo(/*h*/[]);
|
||||
//// foo(/*i*/[1]);
|
||||
|
||||
//// foo(/*j*/foo);
|
||||
//// foo(/*k*/(1));
|
||||
//// foo(/*l*/foo(/*m*/1));
|
||||
|
||||
const markers = test.markers();
|
||||
|
||||
verify.getInlayHints(
|
||||
markers.map(m => ({
|
||||
text: 'v:',
|
||||
position: m.position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
})) , undefined, {
|
||||
includeInlayParameterNameHints: "all"
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (a: number, b: number) {}
|
||||
//// declare const a: 1;
|
||||
//// foo(/*a*/a, /*b*/2);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "all",
|
||||
includeInlayParameterNameHintsWhenArgumentMatchesName: true,
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// class C {
|
||||
//// a/*a*/ = 1
|
||||
//// b: number = 2
|
||||
//// c;
|
||||
//// }
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayPropertyDeclarationTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo ()/*a*/ {
|
||||
//// return 1
|
||||
//// }
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayFunctionLikeReturnTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (): number {
|
||||
//// return 1
|
||||
//// }
|
||||
|
||||
verify.getInlayHints([], undefined, {
|
||||
includeInlayFunctionLikeReturnTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// declare function foo(w: number): void
|
||||
//// declare function foo(a: number, b: number): void;
|
||||
//// declare function foo(a: number | undefined, b: number | undefined): void;
|
||||
|
||||
//// foo(/*a*/1)
|
||||
//// foo(/*b*/1, /*c*/2)
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'w:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// class C {
|
||||
//// foo()/*a*/ {
|
||||
//// return 1
|
||||
//// }
|
||||
//// }
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayFunctionLikeReturnTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a = ()/*a*/ => 1
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayFunctionLikeReturnTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a = function ()/*a*/ { return 1}
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayFunctionLikeReturnTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const a = (b)/*a*/ => 1
|
||||
//// const aa = b => 1
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayFunctionLikeReturnTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// enum E {
|
||||
//// A/*a*/,
|
||||
//// AA/*b*/,
|
||||
//// B = 10,
|
||||
//// BB/*c*/,
|
||||
//// C = 'C',
|
||||
//// }
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: '= 0',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Enum,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: '= 1',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Enum,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: '= 11',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Enum,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayEnumMemberValueHints: true,
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
//// module.exports.a = 1
|
||||
|
||||
// @Filename: /b.js
|
||||
//// const a = require('./a');
|
||||
|
||||
goTo.file('/b.js')
|
||||
verify.getInlayHints([], undefined, {
|
||||
includeInlayVariableTypeHints: true,
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
//// module.exports.a = 1
|
||||
|
||||
// @Filename: /b.js
|
||||
//// function foo () { return require('./a'); }
|
||||
//// function bar ()/*a*/ { return require('./a').a; }
|
||||
//// const c = foo()
|
||||
//// const d/*b*/ = bar()
|
||||
|
||||
goTo.file('/b.js')
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: ': number',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true,
|
||||
includeInlayFunctionLikeReturnTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
//// var x
|
||||
//// x.foo(1, 2);
|
||||
|
||||
//// /**
|
||||
//// * @type {{foo: (a: number, b: number) => void}}
|
||||
//// */
|
||||
//// var y
|
||||
//// y.foo(/*a*/1, /*b*/2)
|
||||
|
||||
goTo.file('/a.js')
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// declare function foo<T extends number>(t: T): T
|
||||
//// const x/*a*/ = foo(1)
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: `: 1`,
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
//// /**
|
||||
//// * @type {string}
|
||||
//// */
|
||||
//// var x = ""
|
||||
|
||||
|
||||
goTo.file('/a.js')
|
||||
verify.getInlayHints([], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type Args = [a: number, b: number]
|
||||
//// declare function foo(c: number, ...args: Args);
|
||||
//// foo(/*a*/1, /*b*/2, /*c*/3)
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'c:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type T = [a: string, b: boolean, ...c: number[]]
|
||||
//// declare function foo(f: number, ...args: T):void
|
||||
//// declare function foo1(f1: number, ...args: string[]): void
|
||||
//// foo(/*f*/1, /*a*/'', /*b*/false, /*c*/1, 2)
|
||||
//// foo1(/*f1*/1, /*args*/"", "")
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'f:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: '...c:',
|
||||
position: markers[3].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'f1:',
|
||||
position: markers[4].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: '...args:',
|
||||
position: markers[5].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /a.ts
|
||||
//// export interface Foo { a: string }
|
||||
|
||||
// @Filename: /b.ts
|
||||
//// async function foo ()/*a*/ {
|
||||
//// return {} as any as import('./a').Foo
|
||||
//// }
|
||||
//// function bar ()/*b*/ { return import('./a') }
|
||||
//// async function main ()/*c*/ {
|
||||
//// const a/*d*/ = await foo()
|
||||
//// const b = await bar()
|
||||
//// }
|
||||
|
||||
goTo.file('/b.ts')
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': Promise<Foo>',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: ': Promise<typeof import("/a")>',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: ': Promise<void>',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: ': Foo',
|
||||
position: markers[3].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayVariableTypeHints: true,
|
||||
includeInlayFunctionLikeReturnTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// function foo (aParameter: number, bParameter: number, cParameter: number)/*f*/ { }
|
||||
|
||||
//// foo(
|
||||
//// /** aParameter */
|
||||
//// 1,
|
||||
//// // bParameter
|
||||
//// /*a*/2,
|
||||
//// /* cParameter */
|
||||
//// 3
|
||||
//// )
|
||||
|
||||
//// foo(
|
||||
//// /** multiple comments */
|
||||
//// /** aParameter */
|
||||
//// 1,
|
||||
//// /** bParameter */
|
||||
//// /** multiple comments */
|
||||
//// 2,
|
||||
//// // cParameter
|
||||
//// /** multiple comments */
|
||||
//// /*b*/3
|
||||
//// )
|
||||
|
||||
//// foo(
|
||||
//// /** wrong name */
|
||||
//// /*c*/1,
|
||||
//// /*d*/2,
|
||||
//// /** multiple */
|
||||
//// /** wrong */
|
||||
//// /** name */
|
||||
//// /*e*/3
|
||||
//// )
|
||||
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: ': void',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Type,
|
||||
whitespaceBefore: true
|
||||
},
|
||||
{
|
||||
text: 'bParameter:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'cParameter:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'aParameter:',
|
||||
position: markers[3].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'bParameter:',
|
||||
position: markers[4].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'cParameter:',
|
||||
position: markers[5].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals",
|
||||
includeInlayFunctionLikeReturnTypeHints: true
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// const fn = (x: any) => { }
|
||||
//// fn(/* nobody knows exactly what this param is */ /*a*/42);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'x:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// type Args = [number, number]
|
||||
//// declare function foo(c: number, ...args: Args);
|
||||
//// foo(/*a*/1, 2, 3)
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'c:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// interface Call {
|
||||
//// (a: number): void
|
||||
//// (b: number, c: number): void
|
||||
//// }
|
||||
//// declare const call: Call;
|
||||
//// call(/*a*/1);
|
||||
//// call(/*b*/1, /*c*/2);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'c:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// class Class {
|
||||
//// constructor(a: number);
|
||||
//// constructor(b: number, c: number);
|
||||
//// constructor(b: number, c?: number) { }
|
||||
//// }
|
||||
//// new Class(/*a*/1)
|
||||
//// new Class(/*b*/1, /*c*/2)
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'c:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//// interface Call {
|
||||
//// (a: number): void
|
||||
//// (b: number, c: number): void
|
||||
//// new (d: number): Call
|
||||
//// }
|
||||
//// declare const call: Call;
|
||||
//// call(/*a*/1);
|
||||
//// call(/*b*/1, /*c*/2);
|
||||
//// new call(/*d*/1);
|
||||
|
||||
const markers = test.markers();
|
||||
verify.getInlayHints([
|
||||
{
|
||||
text: 'a:',
|
||||
position: markers[0].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'b:',
|
||||
position: markers[1].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'c:',
|
||||
position: markers[2].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
},
|
||||
{
|
||||
text: 'd:',
|
||||
position: markers[3].position,
|
||||
kind: ts.InlayHintKind.Parameter,
|
||||
whitespaceAfter: true
|
||||
}
|
||||
], undefined, {
|
||||
includeInlayParameterNameHints: "literals"
|
||||
});
|
||||
Reference in New Issue
Block a user