Compare commits

...

1 commit

Author SHA1 Message Date
Daniel Rosenwasser c5aa91391e Placeholder intermediate work. 2020-05-14 11:35:09 -07:00
7 changed files with 133 additions and 36 deletions

View file

@ -40,6 +40,7 @@ namespace ts {
// 1. interface declarations, type alias declarations
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.PlaceholderTypeDeclaration:
return ModuleInstanceState.NonInstantiated;
// 2. const enum declarations
case SyntaxKind.EnumDeclaration:
@ -517,12 +518,6 @@ namespace ts {
}
}
const relatedInformation: DiagnosticRelatedInformation[] = [];
if (isTypeAliasDeclaration(node) && nodeIsMissing(node.type) && hasModifier(node, ModifierFlags.Export) && symbol.flags & (SymbolFlags.Alias | SymbolFlags.Type | SymbolFlags.Namespace)) {
// export type T; - may have meant export type { T }?
relatedInformation.push(createDiagnosticForNode(node, Diagnostics.Did_you_mean_0, `export type { ${unescapeLeadingUnderscores(node.name.escapedText)} }`));
}
const declarationName = getNameOfDeclaration(node) || node;
forEach(symbol.declarations, (declaration, index) => {
const decl = getNameOfDeclaration(declaration) || declaration;
@ -1783,6 +1778,7 @@ namespace ts {
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.PlaceholderTypeDeclaration:
case SyntaxKind.MappedType:
return ContainerFlags.IsContainer | ContainerFlags.HasLocals;
@ -1904,6 +1900,7 @@ namespace ts {
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.PlaceholderTypeDeclaration:
case SyntaxKind.MappedType:
// All the children of these container types are never visible through another
// symbol (i.e. through another symbol's 'exports' or 'members'). Instead,
@ -2624,6 +2621,8 @@ namespace ts {
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
case SyntaxKind.TypeAliasDeclaration:
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
case SyntaxKind.PlaceholderTypeDeclaration:
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.PlaceholderType, SymbolFlags.PlaceholderTypeExcludes);
case SyntaxKind.EnumDeclaration:
return bindEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ModuleDeclaration:
@ -3409,6 +3408,7 @@ namespace ts {
switch (s.kind) {
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.PlaceholderTypeDeclaration:
return true;
case SyntaxKind.ModuleDeclaration:
return getModuleInstanceState(s as ModuleDeclaration) !== ModuleInstanceState.Instantiated;
@ -4235,6 +4235,7 @@ namespace ts {
case SyntaxKind.ParenthesizedType:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.PlaceholderTypeDeclaration:
case SyntaxKind.ThisType:
case SyntaxKind.TypeOperator:
case SyntaxKind.IndexedAccessType:
@ -4412,6 +4413,7 @@ namespace ts {
case SyntaxKind.IndexSignature:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.PlaceholderTypeDeclaration:
return TransformFlags.TypeExcludes;
case SyntaxKind.ObjectLiteralExpression:
return TransformFlags.ObjectLiteralExcludes;

View file

@ -2002,6 +2002,7 @@ namespace ts {
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.PlaceholderTypeDeclaration:
case SyntaxKind.ModuleDeclaration: // For `namespace N { N; }`
return true;
default:
@ -3554,6 +3555,12 @@ namespace ts {
return type;
}
function createPlaceholderType(symbol: Symbol) {
const type = <TypeParameter>createType(TypeFlags.TypeVariable);
type.symbol = symbol;
return type;
}
// A reserved member name starts with two underscores, but the third character cannot be an underscore,
// @, or #. A third underscore indicates an escaped form of an identifier that started
// with at least two underscores. The @ character indicates that the name is denoted by a well known ES
@ -8697,6 +8704,40 @@ namespace ts {
return links.declaredType;
}
function getDeclaredTypeOfPlaceholderType2(symbol: Symbol) {
const links = getSymbolLinks(symbol);
if (!links.declaredType) {
// Note that we use the links object as the target here because the symbol object is used as the unique
// identity for resolution of the 'type' property in SymbolLinks.
if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) {
return errorType;
}
const declarations = filter(symbol.declarations, isPlaceholderDeclaration);
Debug.assert(declarations.length > 0, "Expected at least one placeholder type.");
const constraints = map(declarations, d => d.constraint ? getTypeFromTypeNode(d.constraint) : unknownType);
let effectiveConstraint = getIntersectionType(constraints);
if (popTypeResolution()) {
const typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
if (typeParameters) {
// Initialize the instantiation cache for generic type aliases. The declared type corresponds to
// an instantiation of the type alias with the type parameters supplied as type arguments.
links.typeParameters = typeParameters;
links.instantiations = createMap<Type>();
links.instantiations.set(getTypeListId(typeParameters), effectiveConstraint);
}
}
else {
effectiveConstraint = errorType;
const declaration = declarations[0];
error(isNamedDeclaration(declaration) ? declaration.name : declaration || declaration, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
}
links.declaredType = effectiveConstraint;
}
return links.declaredType;
}
function isStringConcatExpression(expr: Node): boolean {
if (isStringLiteralLike(expr)) {
return true;
@ -8802,6 +8843,11 @@ namespace ts {
return links.declaredType || (links.declaredType = createTypeParameter(symbol));
}
function getDeclaredTypeOfPlaceholderType(symbol: Symbol): PlaceholderType {
const links = getSymbolLinks(symbol);
return links.declaredType || (links.declaredType = createPlaceholderType(symbol));
}
function getDeclaredTypeOfAlias(symbol: Symbol): Type {
const links = getSymbolLinks(symbol);
return links.declaredType || (links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol)));
@ -8827,6 +8873,11 @@ namespace ts {
if (symbol.flags & SymbolFlags.EnumMember) {
return getDeclaredTypeOfEnumMember(symbol);
}
if (symbol.flags & SymbolFlags.PlaceholderType) {
// Note that placeholder types must yield to the above types,
// so order actually matters here.
return getDeclaredTypeOfPlaceholderType(symbol);
}
if (symbol.flags & SymbolFlags.Alias) {
return getDeclaredTypeOfAlias(symbol);
}
@ -29193,6 +29244,17 @@ namespace ts {
}
}
function checkPlaceholderTypeDeclaration(node: PlaceholderTypeDeclaration) {
// Grammar checking
checkGrammarDecoratorsAndModifiers(node);
checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0); // todo obviously
checkExportsOnMergedDeclarations(node); // todo
checkTypeParameters(node.typeParameters);
checkSourceElement(node.constraint);
// registerForUnusedIdentifiersCheck(node);
}
function checkParameter(node: ParameterDeclaration) {
// Grammar checking
// It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
@ -34566,6 +34628,8 @@ namespace ts {
return checkInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.TypeAliasDeclaration:
return checkTypeAliasDeclaration(<TypeAliasDeclaration>node);
case SyntaxKind.PlaceholderTypeDeclaration:
return checkPlaceholderTypeDeclaration(<PlaceholderTypeDeclaration>node);
case SyntaxKind.EnumDeclaration:
return checkEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ModuleDeclaration:

View file

@ -5583,6 +5583,7 @@ namespace ts {
case SyntaxKind.AbstractKeyword:
case SyntaxKind.AsyncKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.ExistsKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PublicKeyword:
@ -5751,6 +5752,7 @@ namespace ts {
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.ExistsKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.EnumKeyword:
case SyntaxKind.ExportKeyword:
@ -5823,7 +5825,7 @@ namespace ts {
case SyntaxKind.InterfaceKeyword:
return parseInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.TypeKeyword:
return parseTypeAliasDeclaration(<TypeAliasDeclaration>node);
return parseTypeAliasOrPlaceholderTypeDeclaration(<TypeAliasDeclaration>node);
case SyntaxKind.EnumKeyword:
return parseEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.GlobalKeyword:
@ -6366,13 +6368,19 @@ namespace ts {
return finishNode(node);
}
function parseTypeAliasDeclaration(node: TypeAliasDeclaration): TypeAliasDeclaration {
node.kind = SyntaxKind.TypeAliasDeclaration;
function parseTypeAliasOrPlaceholderTypeDeclaration(node: TypeAliasDeclaration | PlaceholderTypeDeclaration): TypeAliasDeclaration | PlaceholderTypeDeclaration {
parseExpected(SyntaxKind.TypeKeyword);
node.name = parseIdentifier();
node.typeParameters = parseTypeParameters();
parseExpected(SyntaxKind.EqualsToken);
node.type = parseType();
if (parseOptional(SyntaxKind.EqualsToken)) {
// an '=' token has already been parsed at this point.
(node as TypeAliasDeclaration).type = parseType();
}
else {
if (parseOptional(SyntaxKind.ExtendsKeyword)) {
(node as PlaceholderTypeDeclaration).constraint = parseType();
}
}
parseSemicolon();
return finishNode(node);
}

View file

@ -85,9 +85,9 @@ namespace ts {
const: SyntaxKind.ConstKeyword,
["" + "constructor"]: SyntaxKind.ConstructorKeyword,
debugger: SyntaxKind.DebuggerKeyword,
declare: SyntaxKind.DeclareKeyword,
default: SyntaxKind.DefaultKeyword,
delete: SyntaxKind.DeleteKeyword,
exists: SyntaxKind.ExistsKeyword,
do: SyntaxKind.DoKeyword,
else: SyntaxKind.ElseKeyword,
enum: SyntaxKind.EnumKeyword,

View file

@ -412,6 +412,10 @@ namespace ts {
case SyntaxKind.TypeAliasDeclaration:
// TypeScript type-only declarations are elided.
return undefined;
case SyntaxKind.PlaceholderTypeDeclaration:
// TypeScript type-only declarations are elided.
return undefined;
case SyntaxKind.PropertyDeclaration:
// TypeScript property declarations are elided. However their names are still visited, and can potentially be retained if they could have sideeffects

View file

@ -47,6 +47,7 @@ namespace ts {
| SyntaxKind.ConstructorKeyword
| SyntaxKind.DebuggerKeyword
| SyntaxKind.DeclareKeyword
| SyntaxKind.ExistsKeyword
| SyntaxKind.DefaultKeyword
| SyntaxKind.DeleteKeyword
| SyntaxKind.DoKeyword
@ -264,6 +265,7 @@ namespace ts {
BooleanKeyword,
ConstructorKeyword,
DeclareKeyword,
ExistsKeyword,
GetKeyword,
InferKeyword,
IsKeyword,
@ -285,10 +287,8 @@ namespace ts {
FromKeyword,
GlobalKeyword,
BigIntKeyword,
OfKeyword, // LastKeyword and LastToken and LastContextualKeyword
OfKeyword,
// Parse tree nodes
// Names
QualifiedName,
ComputedPropertyName,
@ -363,7 +363,6 @@ namespace ts {
NonNullExpression,
MetaProperty,
SyntheticExpression,
// Misc
TemplateSpan,
SemicolonClassElement,
@ -393,6 +392,7 @@ namespace ts {
ClassDeclaration,
InterfaceDeclaration,
TypeAliasDeclaration,
PlaceholderTypeDeclaration,
EnumDeclaration,
ModuleDeclaration,
ModuleBlock,
@ -410,10 +410,8 @@ namespace ts {
NamespaceExport,
ExportSpecifier,
MissingDeclaration,
// Module references
ExternalModuleReference,
// JSX
JsxElement,
JsxSelfClosingElement,
@ -426,18 +424,15 @@ namespace ts {
JsxAttributes,
JsxSpreadAttribute,
JsxExpression,
// Clauses
CaseClause,
DefaultClause,
HeritageClause,
CatchClause,
// Property assignments
PropertyAssignment,
ShorthandPropertyAssignment,
SpreadAssignment,
// Enum
EnumMember,
// Unparsed
@ -446,13 +441,11 @@ namespace ts {
UnparsedText,
UnparsedInternalText,
UnparsedSyntheticReference,
// Top-level nodes
SourceFile,
Bundle,
UnparsedSource,
InputFiles,
// JSDoc nodes
JSDocTypeExpression,
// The * type
@ -487,10 +480,8 @@ namespace ts {
JSDocTemplateTag,
JSDocTypedefTag,
JSDocPropertyTag,
// Synthesized list
SyntaxList,
// Transformation nodes
NotEmittedStatement,
PartiallyEmittedExpression,
@ -498,10 +489,8 @@ namespace ts {
MergeDeclarationMarker,
EndOfDeclarationMarker,
SyntheticReferenceExpression,
// Enum value count
Count,
// Markers
FirstAssignment = EqualsToken,
LastAssignment = CaretEqualsToken,
@ -690,6 +679,7 @@ namespace ts {
| ClassLikeDeclaration
| InterfaceDeclaration
| TypeAliasDeclaration
| PlaceholderTypeDeclaration
| EnumMember
| EnumDeclaration
| ModuleDeclaration
@ -713,6 +703,7 @@ namespace ts {
| MappedTypeNode
| AssertionExpression
| TypeAliasDeclaration
| PlaceholderTypeDeclaration
| JSDocTypeExpression
| JSDocNonNullableType
| JSDocNullableType
@ -2345,7 +2336,13 @@ namespace ts {
export type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode;
export type DeclarationWithTypeParameters = DeclarationWithTypeParameterChildren | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
export type DeclarationWithTypeParameterChildren = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
export type DeclarationWithTypeParameterChildren =
| SignatureDeclaration
| ClassLikeDeclaration
| InterfaceDeclaration
| TypeAliasDeclaration
| PlaceholderTypeDeclaration
| JSDocTemplateTag;
export interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
@ -2400,6 +2397,13 @@ namespace ts {
type: TypeNode;
}
export interface PlaceholderTypeDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.PlaceholderTypeDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
constraint?: TypeNode;
}
export interface EnumMember extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.EnumMember;
parent: EnumDeclaration;
@ -3895,6 +3899,7 @@ namespace ts {
| FunctionDeclaration
| ModuleDeclaration
| TypeAliasDeclaration
| PlaceholderTypeDeclaration // todo: what is this?
| InterfaceDeclaration
| EnumDeclaration;
@ -4037,15 +4042,17 @@ namespace ts {
Transient = 1 << 25, // Transient symbol (created during type check)
Assignment = 1 << 26, // Assignment treated as declaration (eg `this.prop = 1`)
ModuleExports = 1 << 27, // Symbol for CommonJS `module` of `module.exports`
PlaceholderType = 1 << 28, // A way to declare the existence of a type for forward declarations or opaque handles
/* @internal */
All = FunctionScopedVariable | BlockScopedVariable | Property | EnumMember | Function | Class | Interface | ConstEnum | RegularEnum | ValueModule | NamespaceModule | TypeLiteral
| ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias | ExportValue | Alias | Prototype | ExportStar | Optional | Transient,
| ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias | PlaceholderType | ExportValue | Alias | Prototype | ExportStar | Optional | Transient,
Enum = RegularEnum | ConstEnum,
Variable = FunctionScopedVariable | BlockScopedVariable,
Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias,
Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias | PlaceholderType,
NonPlaceholderType = Type & ~PlaceholderType,
Namespace = ValueModule | NamespaceModule | Enum,
Module = ValueModule | NamespaceModule,
Accessor = GetAccessor | SetAccessor,
@ -4060,19 +4067,20 @@ namespace ts {
ParameterExcludes = Value,
PropertyExcludes = None,
EnumMemberExcludes = Value | Type,
EnumMemberExcludes = Value | NonPlaceholderType,
FunctionExcludes = Value & ~(Function | ValueModule | Class),
ClassExcludes = (Value | Type) & ~(ValueModule | Interface | Function), // class-interface mergability done in checker.ts
InterfaceExcludes = Type & ~(Interface | Class),
RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules
ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums
ClassExcludes = (Value | NonPlaceholderType) & ~(ValueModule | Interface | Function), // class-interface mergability done in checker.ts
InterfaceExcludes = NonPlaceholderType & ~(Interface | Class),
RegularEnumExcludes = (Value | NonPlaceholderType) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules
ConstEnumExcludes = (Value | NonPlaceholderType) & ~ConstEnum, // const enums merge only with const enums
ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule),
NamespaceModuleExcludes = 0,
MethodExcludes = Value & ~Method,
GetAccessorExcludes = Value & ~SetAccessor,
SetAccessorExcludes = Value & ~GetAccessor,
TypeParameterExcludes = Type & ~TypeParameter,
TypeAliasExcludes = Type,
TypeAliasExcludes = NonPlaceholderType,
PlaceholderTypeExcludes = Alias | TypeParameter, // placeholder types are happy to merge with other types and placeholder types
AliasExcludes = Alias,
ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Alias,
@ -4353,6 +4361,7 @@ namespace ts {
Conditional = 1 << 24, // T extends U ? X : Y
Substitution = 1 << 25, // Type parameter substitution
NonPrimitive = 1 << 26, // intrinsic object type
Placeholder = 1 << 27, // type T extends Constraint
/* @internal */
AnyOrUnknown = Any | Unknown,
@ -4768,6 +4777,12 @@ namespace ts {
resolvedDefaultType?: Type;
}
// Placeholder Forward Declaration Types (TypeFlags.Placeholder)
export interface PlaceholderType extends InstantiableType {
// @internal
constraint?: Type;
}
// Indexed access types (TypeFlags.IndexedAccess)
// Possible forms are T[xxx], xxx[T], or xxx[keyof T], where T is a type variable
export interface IndexedAccessType extends InstantiableType {

View file

@ -1353,6 +1353,10 @@ namespace ts {
return node.kind === SyntaxKind.TypeAliasDeclaration;
}
export function isPlaceholderDeclaration(node: Node): node is PlaceholderTypeDeclaration {
return node.kind === SyntaxKind.PlaceholderTypeDeclaration;
}
export function isEnumDeclaration(node: Node): node is EnumDeclaration {
return node.kind === SyntaxKind.EnumDeclaration;
}