Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Commit

Permalink
[bugfix] callable types suggestion forgot parens on unions and inters…
Browse files Browse the repository at this point in the history
…ections (#3342)
  • Loading branch information
cyrilgandon authored and ajafff committed Oct 18, 2017
1 parent 349d1b8 commit 74d84be
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/rules/callableTypesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ export class Rule extends Lint.Rules.AbstractRule {

function walk(ctx: Lint.WalkContext<void>) {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if ((isInterfaceDeclaration(node) && noSupertype(node)
|| isTypeLiteralNode(node))
if ((isInterfaceDeclaration(node) && noSupertype(node) || isTypeLiteralNode(node))
&& node.members.length === 1) {
const member = node.members[0];
if (isCallSignatureDeclaration(member) &&
Expand Down Expand Up @@ -82,11 +81,15 @@ function noSupertype(node: ts.InterfaceDeclaration): boolean {
function renderSuggestion(call: ts.CallSignatureDeclaration,
parent: ts.InterfaceDeclaration | ts.TypeLiteralNode,
sourceFile: ts.SourceFile): string {

const start = call.getStart(sourceFile);
const colonPos = call.type!.pos - 1 - start;
const text = sourceFile.text.substring(start, call.end);
const suggestion = `${text.substr(0, colonPos)} =>${text.substr(colonPos + 1)}`;

let suggestion = `${text.substr(0, colonPos)} =>${text.substr(colonPos + 1)}`;
if (shouldWrapSuggestion(parent.parent!)) {
suggestion = `(${suggestion})`;
}
if (parent.kind === ts.SyntaxKind.InterfaceDeclaration) {
if (parent.typeParameters !== undefined) {
return `type${sourceFile.text.substring(parent.name.pos, parent.typeParameters.end + 1)} = ${suggestion}`;
Expand All @@ -96,3 +99,13 @@ function renderSuggestion(call: ts.CallSignatureDeclaration,
}
return suggestion.endsWith(";") ? suggestion.slice(0, -1) : suggestion;
}

function shouldWrapSuggestion(parent: ts.Node) {
switch (parent.kind) {
case ts.SyntaxKind.UnionType:
case ts.SyntaxKind.IntersectionType:
return true;
default:
return false;
}
}
5 changes: 5 additions & 0 deletions test/rules/callable-types/test.ts.fix
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ type U = <T>(t: T) => T

var fn: () => void;
function f(x: () => void): void;
function f(x: string | (() => void)): void;
function f(x: string | (() => void)): void;
function f(x: (() => string) | (() => number)): void;
function f(x: string & (() => void)): void;
function f(x: (() => string) & (() => number)): void;

// Overloads OK
interface K {
Expand Down
12 changes: 12 additions & 0 deletions test/rules/callable-types/test.ts.lint
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ var fn: {(): void;};
~~~~~~~~~ [type % ('() => void')]
function f(x: { (): void }): void;
~~~~~~~~ [type % ('() => void')]
function f(x: string | { (): void }): void;
~~~~~~~~ [type % ('(() => void)')]
function f(x: string | ({ (): void })): void;
~~~~~~~~ [type % ('() => void')]
function f(x: { (): string } | { (): number }): void;
~~~~~~~~~~ [type % ('(() => string)')]
~~~~~~~~~~ [type % ('(() => number)')]
function f(x: string & { (): void }): void;
~~~~~~~~ [type % ('(() => void)')]
function f(x: { (): string } & { (): number }): void;
~~~~~~~~~~ [type % ('(() => string)')]
~~~~~~~~~~ [type % ('(() => number)')]

// Overloads OK
interface K {
Expand Down

0 comments on commit 74d84be

Please sign in to comment.