Skip to content

Commit

Permalink
Merge pull request #11547 from Microsoft/interfaceFixes
Browse files Browse the repository at this point in the history
Codefix for implementing interfaces
  • Loading branch information
mhegazy authored Dec 30, 2016
2 parents 9865a17 + 3fc94bb commit 524fa64
Show file tree
Hide file tree
Showing 163 changed files with 1,564 additions and 222 deletions.
14 changes: 13 additions & 1 deletion Jakefile.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ var servicesSources = [
"signatureHelp.ts",
"symbolDisplay.ts",
"transpile.ts",
// Formatting
"formatting/formatting.ts",
"formatting/formattingContext.ts",
"formatting/formattingRequestKind.ts",
Expand All @@ -166,7 +167,18 @@ var servicesSources = [
"formatting/rulesMap.ts",
"formatting/rulesProvider.ts",
"formatting/smartIndenter.ts",
"formatting/tokenRange.ts"
"formatting/tokenRange.ts",
// CodeFixes
"codeFixProvider.ts",
"codefixes/fixes.ts",
"codefixes/fixExtendsInterfaceBecomesImplements.ts",
"codefixes/fixClassIncorrectlyImplementsInterface.ts",
"codefixes/fixClassDoesntImplementInheritedAbstractMember.ts",
"codefixes/fixClassSuperMustPrecedeThisAccess.ts",
"codefixes/fixConstructorForDerivedNeedSuperCall.ts",
"codefixes/helpers.ts",
"codefixes/importFixes.ts",
"codefixes/unusedIdentifierFixes.ts"
].map(function (f) {
return path.join(servicesDirectory, f);
}));
Expand Down
95 changes: 60 additions & 35 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ namespace ts {
getDeclaredTypeOfSymbol,
getPropertiesOfType,
getPropertyOfType,
getIndexInfoOfType,
getSignaturesOfType,
getIndexTypeOfType,
getBaseTypes,
getTypeFromTypeNode,
getReturnTypeOfSignature,
getNonNullableType,
getSymbolsInScope,
Expand All @@ -90,6 +92,7 @@ namespace ts {
getExportSpecifierLocalTargetSymbol,
getTypeAtLocation: getTypeOfNode,
getPropertySymbolOfDestructuringAssignment,
signatureToString,
typeToString,
getSymbolDisplayBuilder,
symbolToString,
Expand Down Expand Up @@ -1369,7 +1372,9 @@ namespace ts {
return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
}

// Resolves a qualified name and any involved aliases
/**
* Resolves a qualified name and any involved aliases.
*/
function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean, location?: Node): Symbol | undefined {
if (nodeIsMissing(name)) {
return undefined;
Expand Down Expand Up @@ -2110,7 +2115,7 @@ namespace ts {
return result || types;
}

function visibilityToString(flags: ModifierFlags) {
function visibilityToString(flags: ModifierFlags): string | undefined {
if (flags === ModifierFlags.Private) {
return "private";
}
Expand Down Expand Up @@ -2488,26 +2493,6 @@ namespace ts {
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Value, SymbolFormatFlags.None, typeFormatFlags);
}

function writeIndexSignature(info: IndexInfo, keyword: SyntaxKind) {
if (info) {
if (info.isReadonly) {
writeKeyword(writer, SyntaxKind.ReadonlyKeyword);
writeSpace(writer);
}
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writer.writeParameter(info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : "x");
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
writeKeyword(writer, keyword);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
writeType(info.type, TypeFormatFlags.None);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
}

function writePropertyWithModifiers(prop: Symbol) {
if (isReadonlySymbol(prop)) {
writeKeyword(writer, SyntaxKind.ReadonlyKeyword);
Expand Down Expand Up @@ -2595,8 +2580,8 @@ namespace ts {
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
writeIndexSignature(resolved.stringIndexInfo, SyntaxKind.StringKeyword);
writeIndexSignature(resolved.numberIndexInfo, SyntaxKind.NumberKeyword);
buildIndexSignatureDisplay(resolved.stringIndexInfo, writer, IndexKind.String, enclosingDeclaration, globalFlags, symbolStack);
buildIndexSignatureDisplay(resolved.numberIndexInfo, writer, IndexKind.Number, enclosingDeclaration, globalFlags, symbolStack);
for (const p of resolved.properties) {
const t = getTypeOfSymbol(p);
if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) {
Expand Down Expand Up @@ -2787,6 +2772,11 @@ namespace ts {
}

function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
const returnType = getReturnTypeOfSignature(signature);
if (flags & TypeFormatFlags.SuppressAnyReturnType && isTypeAny(returnType)) {
return;
}

if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
writeSpace(writer);
writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken);
Expand All @@ -2800,7 +2790,6 @@ namespace ts {
buildTypePredicateDisplay(signature.typePredicate, writer, enclosingDeclaration, flags, symbolStack);
}
else {
const returnType = getReturnTypeOfSignature(signature);
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
}
}
Expand All @@ -2825,6 +2814,34 @@ namespace ts {
buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack);
}

function buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) {
if (info) {
if (info.isReadonly) {
writeKeyword(writer, SyntaxKind.ReadonlyKeyword);
writeSpace(writer);
}
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writer.writeParameter(info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : "x");
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
switch (kind) {
case IndexKind.Number:
writeKeyword(writer, SyntaxKind.NumberKeyword);
break;
case IndexKind.String:
writeKeyword(writer, SyntaxKind.StringKeyword);
break;
}

writePunctuation(writer, SyntaxKind.CloseBracketToken);
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
buildTypeDisplay(info.type, writer, enclosingDeclaration, globalFlags, symbolStack);
writePunctuation(writer, SyntaxKind.SemicolonToken);
writer.writeLine();
}
}

return _displayBuilder || (_displayBuilder = {
buildSymbolDisplay,
buildTypeDisplay,
Expand All @@ -2835,6 +2852,7 @@ namespace ts {
buildDisplayForTypeParametersAndDelimiters,
buildTypeParameterDisplayFromSymbol,
buildSignatureDisplay,
buildIndexSignatureDisplay,
buildReturnTypeDisplay
});
}
Expand Down Expand Up @@ -3786,11 +3804,13 @@ namespace ts {
return signatures;
}

// The base constructor of a class can resolve to
// undefinedType if the class has no extends clause,
// unknownType if an error occurred during resolution of the extends expression,
// nullType if the extends expression is the null value, or
// an object type with at least one construct signature.
/**
* The base constructor of a class can resolve to
* * undefinedType if the class has no extends clause,
* * unknownType if an error occurred during resolution of the extends expression,
* * nullType if the extends expression is the null value, or
* * an object type with at least one construct signature.
*/
function getBaseConstructorTypeOfClass(type: InterfaceType): Type {
if (!type.resolvedBaseConstructorType) {
const baseTypeNode = getBaseTypeNodeOfClass(type);
Expand Down Expand Up @@ -4271,7 +4291,7 @@ namespace ts {
return <InterfaceTypeWithDeclaredMembers>type;
}

function getTypeWithThisArgument(type: Type, thisArgument?: Type) {
function getTypeWithThisArgument(type: Type, thisArgument?: Type): Type {
if (getObjectFlags(type) & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target,
concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
Expand Down Expand Up @@ -4497,6 +4517,9 @@ namespace ts {
setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}

/**
* Converts an AnonymousType to a ResolvedType.
*/
function resolveAnonymousTypeMembers(type: AnonymousType) {
const symbol = type.symbol;
if (type.target) {
Expand Down Expand Up @@ -7278,10 +7301,12 @@ namespace ts {
return false;
}

// Compare two types and return
// Ternary.True if they are related with no assumptions,
// Ternary.Maybe if they are related with assumptions of other relationships, or
// Ternary.False if they are not related.
/**
* Compare two types and return
* * Ternary.True if they are related with no assumptions,
* * Ternary.Maybe if they are related with assumptions of other relationships, or
* * Ternary.False if they are not related.
*/
function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary {
let result: Ternary;
if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,7 @@ namespace ts {
}
}

function formatStringFromArgs(text: string, args: { [index: number]: string; }, baseIndex?: number): string {
export function formatStringFromArgs(text: string, args: { [index: number]: string; }, baseIndex?: number): string {
baseIndex = baseIndex || 0;

return text.replace(/{(\d+)}/g, (_match, index?) => args[+index + baseIndex]);
Expand Down
12 changes: 4 additions & 8 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3239,23 +3239,19 @@
"category": "Message",
"code": 90002
},
"Change 'extends' to 'implements'": {
"Change 'extends' to 'implements'.": {
"category": "Message",
"code": 90003
},
"Remove unused identifiers": {
"Remove unused identifiers.": {
"category": "Message",
"code": 90004
},
"Implement interface on reference": {
"category": "Message",
"code": 90005
},
"Implement interface on class": {
"Implement interface '{0}'.": {
"category": "Message",
"code": 90006
},
"Implement inherited abstract class": {
"Implement inherited abstract class.": {
"category": "Message",
"code": 90007
},
Expand Down
33 changes: 20 additions & 13 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,9 +640,9 @@ namespace ts {

export interface ParameterDeclaration extends Declaration {
kind: SyntaxKind.Parameter;
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
name: BindingName; // Declared parameter name
questionToken?: QuestionToken; // Present on optional parameter
questionToken?: QuestionToken; // Present on optional parameter
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
}
Expand All @@ -658,14 +658,14 @@ namespace ts {
export interface PropertySignature extends TypeElement {
kind: SyntaxKind.PropertySignature | SyntaxKind.JSDocRecordMember;
name: PropertyName; // Declared property name
questionToken?: QuestionToken; // Present on optional property
questionToken?: QuestionToken; // Present on optional property
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
}

export interface PropertyDeclaration extends ClassElement {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken; // Present for use with reporting a grammar error
questionToken?: QuestionToken; // Present for use with reporting a grammar error
name: PropertyName;
type?: TypeNode;
initializer?: Expression; // Optional initializer
Expand Down Expand Up @@ -2334,6 +2334,7 @@ namespace ts {
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
getPropertiesOfType(type: Type): Symbol[];
getPropertyOfType(type: Type, propertyName: string): Symbol;
getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo;
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
getBaseTypes(type: InterfaceType): ObjectType[];
Expand All @@ -2347,6 +2348,8 @@ namespace ts {
getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol;
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol;
getTypeAtLocation(node: Node): Type;
getTypeFromTypeNode(node: TypeNode): Type;
signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
getSymbolDisplayBuilder(): SymbolDisplayBuilder;
Expand Down Expand Up @@ -2391,6 +2394,7 @@ namespace ts {
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void;
buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void;
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
Expand Down Expand Up @@ -2434,6 +2438,7 @@ namespace ts {
InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type
InTypeAlias = 0x00000200, // Writing type in type alias declaration
UseTypeAliasValue = 0x00000400, // Serialize the type instead of using type-alias. This is needed when we emit declaration file.
SuppressAnyReturnType = 0x00000800, // If the return type is any-like, don't offer a return type.
}

export const enum SymbolFormatFlags {
Expand Down Expand Up @@ -2866,7 +2871,7 @@ namespace ts {
objectFlags: ObjectFlags;
}

// Class and interface types (TypeFlags.Class and TypeFlags.Interface)
/** Class and interface types (TypeFlags.Class and TypeFlags.Interface). */
export interface InterfaceType extends ObjectType {
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none)
Expand All @@ -2886,14 +2891,16 @@ namespace ts {
declaredNumberIndexInfo: IndexInfo; // Declared numeric indexing info
}

// Type references (TypeFlags.Reference). When a class or interface has type parameters or
// a "this" type, references to the class or interface are made using type references. The
// typeArguments property specifies the types to substitute for the type parameters of the
// class or interface and optionally includes an extra element that specifies the type to
// substitute for "this" in the resulting instantiation. When no extra argument is present,
// the type reference itself is substituted for "this". The typeArguments property is undefined
// if the class or interface has no type parameters and the reference isn't specifying an
// explicit "this" argument.
/**
* Type references (TypeFlags.Reference). When a class or interface has type parameters or
* a "this" type, references to the class or interface are made using type references. The
* typeArguments property specifies the types to substitute for the type parameters of the
* class or interface and optionally includes an extra element that specifies the type to
* substitute for "this" in the resulting instantiation. When no extra argument is present,
* the type reference itself is substituted for "this". The typeArguments property is undefined
* if the class or interface has no type parameters and the reference isn't specifying an
* explicit "this" argument.
*/
export interface TypeReference extends ObjectType {
target: GenericType; // Type reference target
typeArguments: Type[]; // Type reference type arguments (undefined if none)
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1830,7 +1830,7 @@ namespace ts {
}
}

export function getAncestor(node: Node, kind: SyntaxKind): Node {
export function getAncestor(node: Node | undefined, kind: SyntaxKind): Node {
while (node) {
if (node.kind === kind) {
return node;
Expand Down
Loading

0 comments on commit 524fa64

Please sign in to comment.