Skip to content

Commit 07e8263

Browse files
authored
Start using a union for FunctionLike things (microsoft#16988)
* Start using a union for FunctionLike things * Rename to shorter name
1 parent 4e6b2f3 commit 07e8263

6 files changed

Lines changed: 73 additions & 45 deletions

File tree

src/compiler/checker.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ namespace ts {
183183
return declaration ? getSignatureFromDeclaration(declaration) : undefined;
184184
},
185185
isImplementationOfOverload: node => {
186-
node = getParseTreeNode(node, isFunctionLike);
187-
return node ? isImplementationOfOverload(node) : undefined;
186+
const parsed = getParseTreeNode(node, isFunctionLike);
187+
return parsed ? isImplementationOfOverload(parsed) : undefined;
188188
},
189189
getImmediateAliasedSymbol: symbol => {
190190
Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here.");
@@ -12569,7 +12569,7 @@ namespace ts {
1256912569
}
1257012570
}
1257112571

12572-
function getContainingObjectLiteral(func: FunctionLikeDeclaration) {
12572+
function getContainingObjectLiteral(func: FunctionLike) {
1257312573
return (func.kind === SyntaxKind.MethodDeclaration ||
1257412574
func.kind === SyntaxKind.GetAccessor ||
1257512575
func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? <ObjectLiteralExpression>func.parent :
@@ -12587,7 +12587,7 @@ namespace ts {
1258712587
});
1258812588
}
1258912589

12590-
function getContextualThisParameterType(func: FunctionLikeDeclaration): Type {
12590+
function getContextualThisParameterType(func: FunctionLike): Type {
1259112591
if (func.kind === SyntaxKind.ArrowFunction) {
1259212592
return undefined;
1259312593
}
@@ -12764,7 +12764,7 @@ namespace ts {
1276412764
return false;
1276512765
}
1276612766

12767-
function getContextualReturnType(functionDecl: FunctionLikeDeclaration): Type {
12767+
function getContextualReturnType(functionDecl: FunctionLike): Type {
1276812768
// If the containing function has a return type annotation, is a constructor, or is a get accessor whose
1276912769
// corresponding set accessor has a type annotation, return statements in the function are contextually typed
1277012770
if (functionDecl.kind === SyntaxKind.Constructor ||
@@ -17862,7 +17862,7 @@ namespace ts {
1786217862
error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
1786317863
}
1786417864
}
17865-
if (node.questionToken && isBindingPattern(node.name) && func.body) {
17865+
if (node.questionToken && isBindingPattern(node.name) && (func as FunctionLikeDeclaration).body) {
1786617866
error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
1786717867
}
1786817868
if ((<Identifier>node.name).text === "this") {
@@ -18622,12 +18622,12 @@ namespace ts {
1862218622
let hasOverloads = false;
1862318623
let bodyDeclaration: FunctionLikeDeclaration;
1862418624
let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration;
18625-
let previousDeclaration: FunctionLikeDeclaration;
18625+
let previousDeclaration: FunctionLike;
1862618626

1862718627
const declarations = symbol.declarations;
1862818628
const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0;
1862918629

18630-
function reportImplementationExpectedError(node: FunctionLikeDeclaration): void {
18630+
function reportImplementationExpectedError(node: FunctionLike): void {
1863118631
if (node.name && nodeIsMissing(node.name)) {
1863218632
return;
1863318633
}
@@ -18686,7 +18686,7 @@ namespace ts {
1868618686
let duplicateFunctionDeclaration = false;
1868718687
let multipleConstructorImplementation = false;
1868818688
for (const current of declarations) {
18689-
const node = <FunctionLikeDeclaration>current;
18689+
const node = <FunctionLike>current;
1869018690
const inAmbientContext = isInAmbientContext(node);
1869118691
const inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext;
1869218692
if (inAmbientContextOrInterface) {
@@ -18707,7 +18707,7 @@ namespace ts {
1870718707
someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node);
1870818708
allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node);
1870918709

18710-
if (nodeIsPresent(node.body) && bodyDeclaration) {
18710+
if (nodeIsPresent((node as FunctionLikeDeclaration).body) && bodyDeclaration) {
1871118711
if (isConstructor) {
1871218712
multipleConstructorImplementation = true;
1871318713
}
@@ -18719,9 +18719,9 @@ namespace ts {
1871918719
reportImplementationExpectedError(previousDeclaration);
1872018720
}
1872118721

18722-
if (nodeIsPresent(node.body)) {
18722+
if (nodeIsPresent((node as FunctionLikeDeclaration).body)) {
1872318723
if (!bodyDeclaration) {
18724-
bodyDeclaration = node;
18724+
bodyDeclaration = node as FunctionLikeDeclaration;
1872518725
}
1872618726
}
1872718727
else {
@@ -18731,7 +18731,7 @@ namespace ts {
1873118731
previousDeclaration = node;
1873218732

1873318733
if (!inAmbientContextOrInterface) {
18734-
lastSeenNonAmbientDeclaration = node;
18734+
lastSeenNonAmbientDeclaration = node as FunctionLikeDeclaration;
1873518735
}
1873618736
}
1873718737
}
@@ -19928,7 +19928,7 @@ namespace ts {
1992819928
forEach((<BindingPattern>node.name).elements, checkSourceElement);
1992919929
}
1993019930
// For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body
19931-
if (node.initializer && getRootDeclaration(node).kind === SyntaxKind.Parameter && nodeIsMissing(getContainingFunction(node).body)) {
19931+
if (node.initializer && getRootDeclaration(node).kind === SyntaxKind.Parameter && nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) {
1993219932
error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
1993319933
return;
1993419934
}
@@ -20527,12 +20527,12 @@ namespace ts {
2052720527
// TODO: Check that target label is valid
2052820528
}
2052920529

20530-
function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLikeDeclaration) {
20530+
function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLike) {
2053120531
return node.kind === SyntaxKind.GetAccessor
2053220532
&& getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind<SetAccessorDeclaration>(node.symbol, SyntaxKind.SetAccessor)) !== undefined;
2053320533
}
2053420534

20535-
function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean {
20535+
function isUnwrappedReturnTypeVoidOrAny(func: FunctionLike, returnType: Type): boolean {
2053620536
const unwrappedReturnType = (getFunctionFlags(func) & FunctionFlags.AsyncGenerator) === FunctionFlags.Async
2053720537
? getPromisedTypeOfPromise(returnType) // Async function
2053820538
: returnType; // AsyncGenerator function, Generator function, or normal function
@@ -23053,8 +23053,8 @@ namespace ts {
2305323053
return false;
2305423054
}
2305523055

23056-
function isImplementationOfOverload(node: FunctionLikeDeclaration) {
23057-
if (nodeIsPresent(node.body)) {
23056+
function isImplementationOfOverload(node: FunctionLike) {
23057+
if (nodeIsPresent((node as FunctionLikeDeclaration).body)) {
2305823058
const symbol = getSymbolOfNode(node);
2305923059
const signaturesOfSymbol = getSignaturesOfSymbol(symbol);
2306023060
// If this function body corresponds to function with multiple signature, it is implementation of overload

src/compiler/transformers/ts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,7 +1682,7 @@ namespace ts {
16821682
const valueDeclaration =
16831683
isClassLike(node)
16841684
? getFirstConstructorWithBody(node)
1685-
: isFunctionLike(node) && nodeIsPresent(node.body)
1685+
: isFunctionLike(node) && nodeIsPresent((node as FunctionLikeDeclaration).body)
16861686
? node
16871687
: undefined;
16881688

@@ -1707,7 +1707,7 @@ namespace ts {
17071707
return createArrayLiteral(expressions);
17081708
}
17091709

1710-
function getParametersOfDecoratedDeclaration(node: FunctionLikeDeclaration, container: ClassLikeDeclaration) {
1710+
function getParametersOfDecoratedDeclaration(node: FunctionLike, container: ClassLikeDeclaration) {
17111711
if (container && node.kind === SyntaxKind.GetAccessor) {
17121712
const { setAccessor } = getAllAccessorDeclarations(container.members, <AccessorDeclaration>node);
17131713
if (setAccessor) {

src/compiler/types.ts

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -705,14 +705,24 @@ namespace ts {
705705
initializer?: Expression; // Optional initializer
706706
}
707707

708-
export interface PropertySignature extends TypeElement {
709-
kind: SyntaxKind.PropertySignature | SyntaxKind.JSDocRecordMember;
708+
export interface TSPropertySignature extends TypeElement {
709+
kind: SyntaxKind.PropertySignature;
710710
name: PropertyName; // Declared property name
711711
questionToken?: QuestionToken; // Present on optional property
712712
type?: TypeNode; // Optional type annotation
713713
initializer?: Expression; // Optional initializer
714714
}
715715

716+
export interface JSDocPropertySignature extends TypeElement {
717+
kind: SyntaxKind.JSDocRecordMember;
718+
name: PropertyName; // Declared property name
719+
questionToken?: QuestionToken; // Present on optional property
720+
type?: TypeNode; // Optional type annotation
721+
initializer?: Expression; // Optional initializer
722+
}
723+
724+
export type PropertySignature = TSPropertySignature | JSDocPropertySignature;
725+
716726
export interface PropertyDeclaration extends ClassElement {
717727
kind: SyntaxKind.PropertyDeclaration;
718728
questionToken?: QuestionToken; // Present for use with reporting a grammar error
@@ -796,21 +806,38 @@ namespace ts {
796806

797807
/**
798808
* Several node kinds share function-like features such as a signature,
799-
* a name, and a body. These nodes should extend FunctionLikeDeclaration.
809+
* a name, and a body. These nodes should extend FunctionLikeDeclarationBase.
800810
* Examples:
801811
* - FunctionDeclaration
802812
* - MethodDeclaration
803813
* - AccessorDeclaration
804814
*/
805-
export interface FunctionLikeDeclaration extends SignatureDeclaration {
815+
export interface FunctionLikeDeclarationBase extends SignatureDeclaration {
806816
_functionLikeDeclarationBrand: any;
807817

808818
asteriskToken?: AsteriskToken;
809819
questionToken?: QuestionToken;
810820
body?: Block | Expression;
811821
}
812822

813-
export interface FunctionDeclaration extends FunctionLikeDeclaration, DeclarationStatement {
823+
export type FunctionLikeDeclaration =
824+
| FunctionDeclaration
825+
| MethodDeclaration
826+
| ConstructorDeclaration
827+
| GetAccessorDeclaration
828+
| SetAccessorDeclaration
829+
| FunctionExpression
830+
| ArrowFunction;
831+
export type FunctionLike =
832+
| FunctionLikeDeclaration
833+
| FunctionTypeNode
834+
| ConstructorTypeNode
835+
| IndexSignatureDeclaration
836+
| MethodSignature
837+
| ConstructSignatureDeclaration
838+
| CallSignatureDeclaration;
839+
840+
export interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement {
814841
kind: SyntaxKind.FunctionDeclaration;
815842
name?: Identifier;
816843
body?: FunctionBody;
@@ -830,13 +857,13 @@ namespace ts {
830857
// Because of this, it may be necessary to determine what sort of MethodDeclaration you have
831858
// at later stages of the compiler pipeline. In that case, you can either check the parent kind
832859
// of the method, or use helpers like isObjectLiteralMethodDeclaration
833-
export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
860+
export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
834861
kind: SyntaxKind.MethodDeclaration;
835862
name: PropertyName;
836863
body?: FunctionBody;
837864
}
838865

839-
export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement {
866+
export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement {
840867
kind: SyntaxKind.Constructor;
841868
parent?: ClassDeclaration | ClassExpression;
842869
body?: FunctionBody;
@@ -850,7 +877,7 @@ namespace ts {
850877

851878
// See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a
852879
// ClassElement and an ObjectLiteralElement.
853-
export interface GetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
880+
export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
854881
kind: SyntaxKind.GetAccessor;
855882
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
856883
name: PropertyName;
@@ -859,7 +886,7 @@ namespace ts {
859886

860887
// See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a
861888
// ClassElement and an ObjectLiteralElement.
862-
export interface SetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
889+
export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
863890
kind: SyntaxKind.SetAccessor;
864891
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
865892
name: PropertyName;
@@ -1323,13 +1350,13 @@ namespace ts {
13231350
export type FunctionBody = Block;
13241351
export type ConciseBody = FunctionBody | Expression;
13251352

1326-
export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration {
1353+
export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase {
13271354
kind: SyntaxKind.FunctionExpression;
13281355
name?: Identifier;
13291356
body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional
13301357
}
13311358

1332-
export interface ArrowFunction extends Expression, FunctionLikeDeclaration {
1359+
export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase {
13331360
kind: SyntaxKind.ArrowFunction;
13341361
equalsGreaterThanToken: EqualsGreaterThanToken;
13351362
body: ConciseBody;
@@ -2110,7 +2137,7 @@ namespace ts {
21102137

21112138
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
21122139

2113-
export interface JSDocRecordMember extends PropertySignature {
2140+
export interface JSDocRecordMember extends JSDocPropertySignature {
21142141
kind: SyntaxKind.JSDocRecordMember;
21152142
name: Identifier | StringLiteral | NumericLiteral;
21162143
type?: JSDocType;
@@ -2600,7 +2627,7 @@ namespace ts {
26002627
*/
26012628
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
26022629
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
2603-
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined;
2630+
isImplementationOfOverload(node: FunctionLike): boolean | undefined;
26042631
isUndefinedSymbol(symbol: Symbol): boolean;
26052632
isArgumentsSymbol(symbol: Symbol): boolean;
26062633
isUnknownSymbol(symbol: Symbol): boolean;

src/compiler/utilities.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -907,11 +907,11 @@ namespace ts {
907907
});
908908
}
909909

910-
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
910+
export function getContainingFunction(node: Node): FunctionLike {
911911
while (true) {
912912
node = node.parent;
913913
if (!node || isFunctionLike(node)) {
914-
return <FunctionLikeDeclaration>node;
914+
return <FunctionLike>node;
915915
}
916916
}
917917
}
@@ -1893,7 +1893,7 @@ namespace ts {
18931893
AsyncGenerator = Async | Generator, // Function is an async generator function
18941894
}
18951895

1896-
export function getFunctionFlags(node: FunctionLikeDeclaration | undefined) {
1896+
export function getFunctionFlags(node: FunctionLike | undefined) {
18971897
if (!node) {
18981898
return FunctionFlags.Invalid;
18991899
}
@@ -1914,7 +1914,7 @@ namespace ts {
19141914
break;
19151915
}
19161916

1917-
if (!node.body) {
1917+
if (!(node as FunctionLikeDeclaration).body) {
19181918
flags |= FunctionFlags.Invalid;
19191919
}
19201920

@@ -4864,7 +4864,7 @@ namespace ts {
48644864

48654865
// Functions
48664866

4867-
export function isFunctionLike(node: Node): node is FunctionLikeDeclaration {
4867+
export function isFunctionLike(node: Node): node is FunctionLike {
48684868
return node && isFunctionLikeKind(node.kind);
48694869
}
48704870

src/services/findAllReferences.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,16 +1049,17 @@ namespace ts.FindAllReferences.Core {
10491049
if (isVariableLike(parent) && parent.type === containingTypeReference && parent.initializer && isImplementationExpression(parent.initializer)) {
10501050
addReference(parent.initializer);
10511051
}
1052-
else if (isFunctionLike(parent) && parent.type === containingTypeReference && parent.body) {
1053-
if (parent.body.kind === SyntaxKind.Block) {
1054-
forEachReturnStatement(<Block>parent.body, returnStatement => {
1052+
else if (isFunctionLike(parent) && parent.type === containingTypeReference && (parent as FunctionLikeDeclaration).body) {
1053+
const body = (parent as FunctionLikeDeclaration).body;
1054+
if (body.kind === SyntaxKind.Block) {
1055+
forEachReturnStatement(<Block>body, returnStatement => {
10551056
if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) {
10561057
addReference(returnStatement.expression);
10571058
}
10581059
});
10591060
}
1060-
else if (isImplementationExpression(<Expression>parent.body)) {
1061-
addReference(parent.body);
1061+
else if (isImplementationExpression(<Expression>body)) {
1062+
addReference(body);
10621063
}
10631064
}
10641065
else if (isAssertionExpression(parent) && isImplementationExpression(parent.expression)) {
@@ -1643,7 +1644,7 @@ namespace ts.FindAllReferences.Core {
16431644
}
16441645
}
16451646
else if (isFunctionLike(node)) {
1646-
return !!node.body || hasModifier(node, ModifierFlags.Ambient);
1647+
return !!(node as FunctionLikeDeclaration).body || hasModifier(node, ModifierFlags.Ambient);
16471648
}
16481649
else {
16491650
switch (node.kind) {

src/services/symbolDisplay.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ namespace ts.SymbolDisplay {
201201
else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration
202202
(location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration
203203
// get the signature from the declaration and write it
204-
const functionDeclaration = <FunctionLikeDeclaration>location.parent;
204+
const functionDeclaration = <FunctionLike>location.parent;
205205
// Use function declaration to write the signatures only if the symbol corresponding to this declaration
206206
const locationIsSymbolDeclaration = findDeclaration(symbol, declaration =>
207207
declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration));

0 commit comments

Comments
 (0)