Merge branch 'master' into cleanHarnessOptionLoading

Conflicts:
	src/harness/harness.ts
This commit is contained in:
Mohamed Hegazy
2015-09-14 16:53:08 -07:00
241 changed files with 6819 additions and 1563 deletions
+5 -1
View File
@@ -973,6 +973,10 @@ namespace ts {
else {
let bindingName = node.name ? node.name.text : "__class";
bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName);
// Add name of class expression into the map for semantic classifier
if (node.name) {
classifiableNames[node.name.text] = node.name.text;
}
}
let symbol = node.symbol;
@@ -1062,4 +1066,4 @@ namespace ts {
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
}
}
}
}
+86 -105
View File
@@ -1893,7 +1893,7 @@ namespace ts {
function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags) {
let targetSymbol = getTargetSymbol(symbol);
if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface) {
if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface || targetSymbol.flags & SymbolFlags.TypeAlias) {
buildDisplayForTypeParametersAndDelimiters(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), writer, enclosingDeclaraiton, flags);
}
}
@@ -3119,7 +3119,7 @@ namespace ts {
}
function resolveTupleTypeMembers(type: TupleType) {
let arrayType = resolveStructuredTypeMembers(createArrayType(getUnionType(type.elementTypes)));
let arrayType = resolveStructuredTypeMembers(createArrayType(getUnionType(type.elementTypes, /*noSubtypeReduction*/ true)));
let members = createTupleTypeMemberSymbols(type.elementTypes);
addInheritedMembers(members, arrayType.properties);
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
@@ -3451,29 +3451,6 @@ namespace ts {
return undefined;
}
// Check if a property with the given name is known anywhere in the given type. In an object
// type, a property is considered known if the object type is empty, if it has any index
// signatures, or if the property is actually declared in the type. In a union or intersection
// type, a property is considered known if it is known in any constituent type.
function isKnownProperty(type: Type, name: string): boolean {
if (type.flags & TypeFlags.ObjectType && type !== globalObjectType) {
const resolved = resolveStructuredTypeMembers(type);
return !!(resolved.properties.length === 0 ||
resolved.stringIndexType ||
resolved.numberIndexType ||
getPropertyOfType(type, name));
}
if (type.flags & TypeFlags.UnionOrIntersection) {
for (let t of (<UnionOrIntersectionType>type).types) {
if (isKnownProperty(t, name)) {
return true;
}
}
return false;
}
return true;
}
function getSignaturesOfStructuredType(type: Type, kind: SignatureKind): Signature[] {
if (type.flags & TypeFlags.StructuredType) {
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
@@ -4036,7 +4013,7 @@ namespace ts {
*/
function createTypedPropertyDescriptorType(propertyType: Type): Type {
let globalTypedPropertyDescriptorType = getGlobalTypedPropertyDescriptorType();
return globalTypedPropertyDescriptorType !== emptyObjectType
return globalTypedPropertyDescriptorType !== emptyGenericType
? createTypeReference(<GenericType>globalTypedPropertyDescriptorType, [propertyType])
: emptyObjectType;
}
@@ -4103,73 +4080,20 @@ namespace ts {
}
}
function isObjectLiteralTypeDuplicateOf(source: ObjectType, target: ObjectType): boolean {
let sourceProperties = getPropertiesOfObjectType(source);
let targetProperties = getPropertiesOfObjectType(target);
if (sourceProperties.length !== targetProperties.length) {
return false;
}
for (let sourceProp of sourceProperties) {
let targetProp = getPropertyOfObjectType(target, sourceProp.name);
if (!targetProp ||
getDeclarationFlagsFromSymbol(targetProp) & (NodeFlags.Private | NodeFlags.Protected) ||
!isTypeDuplicateOf(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp))) {
return false;
}
}
return true;
}
function isTupleTypeDuplicateOf(source: TupleType, target: TupleType): boolean {
let sourceTypes = source.elementTypes;
let targetTypes = target.elementTypes;
if (sourceTypes.length !== targetTypes.length) {
return false;
}
for (var i = 0; i < sourceTypes.length; i++) {
if (!isTypeDuplicateOf(sourceTypes[i], targetTypes[i])) {
return false;
}
}
return true;
}
// Returns true if the source type is a duplicate of the target type. A source type is a duplicate of
// a target type if the the two are identical, with the exception that the source type may have null or
// undefined in places where the target type doesn't. This is by design an asymmetric relationship.
function isTypeDuplicateOf(source: Type, target: Type): boolean {
if (source === target) {
return true;
}
if (source.flags & TypeFlags.Undefined || source.flags & TypeFlags.Null && !(target.flags & TypeFlags.Undefined)) {
return true;
}
if (source.flags & TypeFlags.ObjectLiteral && target.flags & TypeFlags.ObjectType) {
return isObjectLiteralTypeDuplicateOf(<ObjectType>source, <ObjectType>target);
}
if (isArrayType(source) && isArrayType(target)) {
return isTypeDuplicateOf((<TypeReference>source).typeArguments[0], (<TypeReference>target).typeArguments[0]);
}
if (isTupleType(source) && isTupleType(target)) {
return isTupleTypeDuplicateOf(<TupleType>source, <TupleType>target);
}
return isTypeIdenticalTo(source, target);
}
function isTypeDuplicateOfSomeType(candidate: Type, types: Type[]): boolean {
for (let type of types) {
if (candidate !== type && isTypeDuplicateOf(candidate, type)) {
function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
for (let i = 0, len = types.length; i < len; i++) {
if (candidate !== types[i] && isTypeSubtypeOf(candidate, types[i])) {
return true;
}
}
return false;
}
function removeDuplicateTypes(types: Type[]) {
function removeSubtypes(types: Type[]) {
let i = types.length;
while (i > 0) {
i--;
if (isTypeDuplicateOfSomeType(types[i], types)) {
if (isSubtypeOfAny(types[i], types)) {
types.splice(i, 1);
}
}
@@ -4194,12 +4118,14 @@ namespace ts {
}
}
// We always deduplicate the constituent type set based on object identity, but we'll also deduplicate
// based on the structure of the types unless the noDeduplication flag is true, which is the case when
// creating a union type from a type node and when instantiating a union type. In both of those cases,
// structural deduplication has to be deferred to properly support recursive union types. For example,
// a type of the form "type Item = string | (() => Item)" cannot be deduplicated during its declaration.
function getUnionType(types: Type[], noDeduplication?: boolean): Type {
// We reduce the constituent type set to only include types that aren't subtypes of other types, unless
// the noSubtypeReduction flag is specified, in which case we perform a simple deduplication based on
// object identity. Subtype reduction is possible only when union types are known not to circularly
// reference themselves (as is the case with union types created by expression constructs such as array
// literals and the || and ?: operators). Named types can circularly reference themselves and therefore
// cannot be deduplicated during their declaration. For example, "type Item = string | (() => Item" is
// a named type that circularly references itself.
function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type {
if (types.length === 0) {
return emptyObjectType;
}
@@ -4208,12 +4134,12 @@ namespace ts {
if (containsTypeAny(typeSet)) {
return anyType;
}
if (noDeduplication) {
if (noSubtypeReduction) {
removeAllButLast(typeSet, undefinedType);
removeAllButLast(typeSet, nullType);
}
else {
removeDuplicateTypes(typeSet);
removeSubtypes(typeSet);
}
if (typeSet.length === 1) {
return typeSet[0];
@@ -4230,7 +4156,7 @@ namespace ts {
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
let links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noDeduplication*/ true);
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noSubtypeReduction*/ true);
}
return links.resolvedType;
}
@@ -4487,6 +4413,15 @@ namespace ts {
}
function instantiateAnonymousType(type: ObjectType, mapper: TypeMapper): ObjectType {
if (mapper.instantiations) {
let cachedType = mapper.instantiations[type.id];
if (cachedType) {
return cachedType;
}
}
else {
mapper.instantiations = [];
}
// Mark the anonymous type as instantiated such that our infinite instantiation detection logic can recognize it
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated, type.symbol);
result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
@@ -4497,6 +4432,7 @@ namespace ts {
let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
if (stringIndexType) result.stringIndexType = instantiateType(stringIndexType, mapper);
if (numberIndexType) result.numberIndexType = instantiateType(numberIndexType, mapper);
mapper.instantiations[type.id] = result;
return result;
}
@@ -4516,7 +4452,7 @@ namespace ts {
return createTupleType(instantiateList((<TupleType>type).elementTypes, mapper, instantiateType));
}
if (type.flags & TypeFlags.Union) {
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noDeduplication*/ true);
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noSubtypeReduction*/ true);
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType));
@@ -4612,7 +4548,7 @@ namespace ts {
* @param target The right-hand-side of the relation.
* @param relation The relation considered. One of 'identityRelation', 'assignableRelation', or 'subTypeRelation'.
* Used as both to determine which checks are performed and as a cache of previously computed results.
* @param errorNode The node upon which all errors will be reported, if defined.
* @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used.
* @param headMessage If the error chain should be prepended by a head message, then headMessage will be used.
* @param containingMessageChain A chain of errors to prepend any new errors found.
*/
@@ -4803,11 +4739,41 @@ namespace ts {
return Ternary.False;
}
// Check if a property with the given name is known anywhere in the given type. In an object type, a property
// is considered known if the object type is empty and the check is for assignability, if the object type has
// index signatures, or if the property is actually declared in the object type. In a union or intersection
// type, a property is considered known if it is known in any constituent type.
function isKnownProperty(type: Type, name: string): boolean {
if (type.flags & TypeFlags.ObjectType) {
const resolved = resolveStructuredTypeMembers(type);
if (relation === assignableRelation && (type === globalObjectType || resolved.properties.length === 0) ||
resolved.stringIndexType || resolved.numberIndexType || getPropertyOfType(type, name)) {
return true;
}
return false;
}
if (type.flags & TypeFlags.UnionOrIntersection) {
for (let t of (<UnionOrIntersectionType>type).types) {
if (isKnownProperty(t, name)) {
return true;
}
}
return false;
}
return true;
}
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
for (let prop of getPropertiesOfObjectType(source)) {
if (!isKnownProperty(target, prop.name)) {
if (reportErrors) {
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(prop), typeToString(target));
// We know *exactly* where things went wrong when comparing the types.
// Use this property as the error node as this will be more helpful in
// reasoning about what went wrong.
errorNode = prop.valueDeclaration
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
symbolToString(prop),
typeToString(target));
}
return true;
}
@@ -5584,7 +5550,7 @@ namespace ts {
return getWidenedTypeOfObjectLiteral(type);
}
if (type.flags & TypeFlags.Union) {
return getUnionType(map((<UnionType>type).types, getWidenedType));
return getUnionType(map((<UnionType>type).types, getWidenedType), /*noSubtypeReduction*/ true);
}
if (isArrayType(type)) {
return createArrayType(getWidenedType((<TypeReference>type).typeArguments[0]));
@@ -7151,7 +7117,7 @@ namespace ts {
let propertiesTable: SymbolTable = {};
let propertiesArray: Symbol[] = [];
let contextualType = getContextualType(node);
let typeFlags: TypeFlags;
let typeFlags: TypeFlags = 0;
for (let memberDecl of node.properties) {
let member = memberDecl.symbol;
@@ -7200,7 +7166,8 @@ namespace ts {
let stringIndexType = getIndexType(IndexKind.String);
let numberIndexType = getIndexType(IndexKind.Number);
let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.FreshObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.PropagatingFlags);
let freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshObjectLiteral;
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
return result;
function getIndexType(kind: IndexKind) {
@@ -9165,7 +9132,7 @@ namespace ts {
function createPromiseType(promisedType: Type): Type {
// creates a `Promise<T>` type where `T` is the promisedType argument
let globalPromiseType = getGlobalPromiseType();
if (globalPromiseType !== emptyObjectType) {
if (globalPromiseType !== emptyGenericType) {
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
promisedType = getAwaitedType(promisedType);
return createTypeReference(<GenericType>globalPromiseType, [promisedType]);
@@ -11384,9 +11351,16 @@ namespace ts {
// serialize the type metadata.
if (node && node.kind === SyntaxKind.TypeReference) {
let root = getFirstIdentifier((<TypeReferenceNode>node).typeName);
let rootSymbol = resolveName(root, root.text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
markAliasSymbolAsReferenced(rootSymbol);
let meaning = root.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
// Resolve type so we know which symbol is referenced
let rootSymbol = resolveName(root, root.text, meaning | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
// Resolved symbol is alias
if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias) {
let aliasTarget = resolveAlias(rootSymbol);
// If alias has value symbol - mark alias as referenced
if (aliasTarget.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
markAliasSymbolAsReferenced(rootSymbol);
}
}
}
}
@@ -12596,6 +12570,7 @@ namespace ts {
if (baseTypes.length && produceDiagnostics) {
let baseType = baseTypes[0];
let staticBaseType = getBaseConstructorTypeOfClass(type);
checkSourceElement(baseTypeNode.expression);
if (baseTypeNode.typeArguments) {
forEach(baseTypeNode.typeArguments, checkSourceElement);
for (let constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments)) {
@@ -13046,7 +13021,7 @@ namespace ts {
// illegal case: forward reference
if (!isDefinedBefore(propertyDecl, member)) {
reportError = false;
error(e, Diagnostics.A_member_initializer_in_a_const_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_const_enums);
error(e, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums);
return undefined;
}
@@ -13665,6 +13640,8 @@ namespace ts {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.VariableDeclarationList:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.HeritageClause:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
case SyntaxKind.ExportAssignment:
@@ -14402,6 +14379,10 @@ namespace ts {
// Resolve the symbol as a type so that we can provide a more useful hint for the type serializer.
let typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true);
// We might not be able to resolve type symbol so use unknown type in that case (eg error case)
if (!typeSymbol) {
return TypeReferenceSerializationKind.ObjectType;
}
let type = getDeclaredTypeOfSymbol(typeSymbol);
if (type === unknownType) {
return TypeReferenceSerializationKind.Unknown;
@@ -14608,7 +14589,7 @@ namespace ts {
function createInstantiatedPromiseLikeType(): ObjectType {
let promiseLikeType = getGlobalPromiseLikeType();
if (promiseLikeType !== emptyObjectType) {
if (promiseLikeType !== emptyGenericType) {
return createTypeReference(<GenericType>promiseLikeType, [anyType]);
}
+49 -11
View File
@@ -30,6 +30,11 @@ namespace ts {
type: "boolean",
description: Diagnostics.Print_this_message,
},
{
name: "init",
type: "boolean",
description: Diagnostics.Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file,
},
{
name: "inlineSourceMap",
type: "boolean",
@@ -179,6 +184,12 @@ namespace ts {
description: Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
paramType: Diagnostics.LOCATION,
},
{
name: "suppressExcessPropertyErrors",
type: "boolean",
description: Diagnostics.Suppress_excess_property_checks_for_object_literals,
experimental: true
},
{
name: "suppressImplicitAnyIndexErrors",
type: "boolean",
@@ -225,22 +236,49 @@ namespace ts {
type: "boolean",
experimental: true,
description: Diagnostics.Enables_experimental_support_for_emitting_type_metadata_for_decorators
}
},
{
name: "moduleResolution",
type: {
"node": ModuleResolutionKind.NodeJs,
"classic": ModuleResolutionKind.Classic
},
description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_or_classic_TypeScript_pre_1_6
}
];
export function parseCommandLine(commandLine: string[]): ParsedCommandLine {
let options: CompilerOptions = {};
let fileNames: string[] = [];
let errors: Diagnostic[] = [];
let shortOptionNames: Map<string> = {};
let optionNameMap: Map<CommandLineOption> = {};
/* @internal */
export interface OptionNameMap {
optionNameMap: Map<CommandLineOption>;
shortOptionNames: Map<string>;
}
let optionNameMapCache: OptionNameMap;
/* @internal */
export function getOptionNameMap(): OptionNameMap {
if (optionNameMapCache) {
return optionNameMapCache;
}
let optionNameMap: Map<CommandLineOption> = {};
let shortOptionNames: Map<string> = {};
forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option;
if (option.shortName) {
shortOptionNames[option.shortName] = option.name;
}
});
optionNameMapCache = { optionNameMap, shortOptionNames };
return optionNameMapCache;
}
export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine {
let options: CompilerOptions = {};
let fileNames: string[] = [];
let errors: Diagnostic[] = [];
let { optionNameMap, shortOptionNames } = getOptionNameMap();
parseStrings(commandLine);
return {
options,
@@ -304,7 +342,7 @@ namespace ts {
}
function parseResponseFile(fileName: string) {
let text = sys.readFile(fileName);
let text = readFile ? readFile(fileName) : sys.readFile(fileName);
if (!text) {
errors.push(createCompilerDiagnostic(Diagnostics.File_0_not_found, fileName));
@@ -341,10 +379,10 @@ namespace ts {
* Read tsconfig.json file
* @param fileName The path to the config file
*/
export function readConfigFile(fileName: string): { config?: any; error?: Diagnostic } {
export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } {
let text = "";
try {
text = sys.readFile(fileName);
text = readFile(fileName);
}
catch (e) {
return { error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
@@ -457,4 +495,4 @@ namespace ts {
return fileNames;
}
}
}
}
+4 -4
View File
@@ -287,14 +287,14 @@ namespace ts {
return <T>result;
}
export function extend<T>(first: Map<T>, second: Map<T>): Map<T> {
let result: Map<T> = {};
export function extend<T1, T2>(first: Map<T1>, second: Map<T2>): Map<T1 & T2> {
let result: Map<T1 & T2> = {};
for (let id in first) {
result[id] = first[id];
(result as any)[id] = first[id];
}
for (let id in second) {
if (!hasProperty(result, id)) {
result[id] = second[id];
(result as any)[id] = second[id];
}
}
return result;
+3
View File
@@ -896,6 +896,9 @@ namespace ts {
if (isSupportedExpressionWithTypeArguments(node)) {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
}
else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) {
write("null");
}
function getHeritageClauseVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage: DiagnosticMessage;
@@ -244,7 +244,7 @@ namespace ts {
Property_0_does_not_exist_on_type_1: { code: 2339, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on type '{1}'." },
Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword: { code: 2340, category: DiagnosticCategory.Error, key: "Only public and protected methods of the base class are accessible via the 'super' keyword." },
Property_0_is_private_and_only_accessible_within_class_1: { code: 2341, category: DiagnosticCategory.Error, key: "Property '{0}' is private and only accessible within class '{1}'." },
An_index_expression_argument_must_be_of_type_string_number_symbol_or_any: { code: 2342, category: DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', 'symbol, or 'any'." },
An_index_expression_argument_must_be_of_type_string_number_symbol_or_any: { code: 2342, category: DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', 'symbol', or 'any'." },
Type_0_does_not_satisfy_the_constraint_1: { code: 2344, category: DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}'." },
Argument_of_type_0_is_not_assignable_to_parameter_of_type_1: { code: 2345, category: DiagnosticCategory.Error, key: "Argument of type '{0}' is not assignable to parameter of type '{1}'." },
Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: DiagnosticCategory.Error, key: "Supplied parameters do not match any signature of call target." },
@@ -425,7 +425,7 @@ namespace ts {
JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property: { code: 2607, category: DiagnosticCategory.Error, key: "JSX element class does not support attributes because it does not have a '{0}' property" },
The_global_type_JSX_0_may_not_have_more_than_one_property: { code: 2608, category: DiagnosticCategory.Error, key: "The global type 'JSX.{0}' may not have more than one property" },
Cannot_emit_namespaced_JSX_elements_in_React: { code: 2650, category: DiagnosticCategory.Error, key: "Cannot emit namespaced JSX elements in React" },
A_member_initializer_in_a_const_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_const_enums: { code: 2651, category: DiagnosticCategory.Error, key: "A member initializer in a 'const' enum declaration cannot reference members declared after it, including members defined in other 'const' enums." },
A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums: { code: 2651, category: DiagnosticCategory.Error, key: "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums." },
Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead: { code: 2652, category: DiagnosticCategory.Error, key: "Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead." },
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
@@ -511,6 +511,7 @@ namespace ts {
Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided: { code: 5051, category: DiagnosticCategory.Error, key: "Option 'inlineSources' can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided." },
Option_0_cannot_be_specified_without_specifying_option_1: { code: 5052, category: DiagnosticCategory.Error, key: "Option '{0}' cannot be specified without specifying option '{1}'." },
Option_0_cannot_be_specified_with_option_1: { code: 5053, category: DiagnosticCategory.Error, key: "Option '{0}' cannot be specified with option '{1}'." },
A_tsconfig_json_file_is_already_defined_at_Colon_0: { code: 5053, category: DiagnosticCategory.Error, key: "A 'tsconfig.json' file is already defined at: '{0}'." },
Concatenate_and_emit_output_to_single_file: { code: 6001, category: DiagnosticCategory.Message, key: "Concatenate and emit output to single file." },
Generates_corresponding_d_ts_file: { code: 6002, category: DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." },
Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." },
@@ -565,6 +566,10 @@ namespace ts {
Enables_experimental_support_for_emitting_type_metadata_for_decorators: { code: 6066, category: DiagnosticCategory.Message, key: "Enables experimental support for emitting type metadata for decorators." },
Option_experimentalAsyncFunctions_cannot_be_specified_when_targeting_ES5_or_lower: { code: 6067, category: DiagnosticCategory.Message, key: "Option 'experimentalAsyncFunctions' cannot be specified when targeting ES5 or lower." },
Enables_experimental_support_for_ES7_async_functions: { code: 6068, category: DiagnosticCategory.Message, key: "Enables experimental support for ES7 async functions." },
Specifies_module_resolution_strategy_Colon_node_Node_or_classic_TypeScript_pre_1_6: { code: 6069, category: DiagnosticCategory.Message, key: "Specifies module resolution strategy: 'node' (Node) or 'classic' (TypeScript pre 1.6) ." },
Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file: { code: 6070, category: DiagnosticCategory.Message, key: "Initializes a TypeScript project and creates a tsconfig.json file." },
Successfully_created_a_tsconfig_json_file: { code: 6071, category: DiagnosticCategory.Message, key: "Successfully created a tsconfig.json file." },
Suppress_excess_property_checks_for_object_literals: { code: 6072, category: DiagnosticCategory.Message, key: "Suppress excess property checks for object literals." },
Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
+25 -5
View File
@@ -161,7 +161,7 @@
},
"Type '{0}' is not a valid async function return type.": {
"category": "Error",
"code": 1055
"code": 1055
},
"Accessors are only available when targeting ECMAScript 5 and higher.": {
"category": "Error",
@@ -965,7 +965,7 @@
"category": "Error",
"code": 2341
},
"An index expression argument must be of type 'string', 'number', 'symbol, or 'any'.": {
"An index expression argument must be of type 'string', 'number', 'symbol', or 'any'.": {
"category": "Error",
"code": 2342
},
@@ -1689,7 +1689,7 @@
"category": "Error",
"code": 2650
},
"A member initializer in a 'const' enum declaration cannot reference members declared after it, including members defined in other 'const' enums.": {
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
"category": "Error",
"code": 2651
},
@@ -2033,7 +2033,11 @@
"category": "Error",
"code": 5053
},
"A 'tsconfig.json' file is already defined at: '{0}'.": {
"category": "Error",
"code": 5053
},
"Concatenate and emit output to single file.": {
"category": "Message",
"code": 6001
@@ -2250,7 +2254,23 @@
"category": "Message",
"code": 6068
},
"Specifies module resolution strategy: 'node' (Node) or 'classic' (TypeScript pre 1.6) .": {
"category": "Message",
"code": 6069
},
"Initializes a TypeScript project and creates a tsconfig.json file.": {
"category": "Message",
"code": 6070
},
"Successfully created a tsconfig.json file.": {
"category": "Message",
"code": 6071
},
"Suppress excess property checks for object literals.": {
"category": "Message",
"code": 6072
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
+126 -117
View File
@@ -124,11 +124,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitJavaScript(jsFilePath: string, root?: SourceFile) {
let writer = createTextWriter(newLine);
let write = writer.write;
let writeTextOfNode = writer.writeTextOfNode;
let writeLine = writer.writeLine;
let increaseIndent = writer.increaseIndent;
let decreaseIndent = writer.decreaseIndent;
let { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer;
let currentSourceFile: SourceFile;
// name of an exporter function if file is a System external module
@@ -1181,9 +1177,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function emitJsxElement(openingNode: JsxOpeningLikeElement, children?: JsxChild[]) {
let syntheticReactRef = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
syntheticReactRef.text = 'React';
syntheticReactRef.parent = openingNode;
// Call React.createElement(tag, ...
emitLeadingComments(openingNode);
write("React.createElement(");
emitExpressionIdentifier(syntheticReactRef);
write(".createElement(");
emitTagName(openingNode.tagName);
write(", ");
@@ -1197,7 +1198,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// a call to React.__spread
let attrs = openingNode.attributes;
if (forEach(attrs, attr => attr.kind === SyntaxKind.JsxSpreadAttribute)) {
write("React.__spread(");
emitExpressionIdentifier(syntheticReactRef);
write(".__spread(");
let haveOpenedObjectLiteral = false;
for (let i = 0; i < attrs.length; i++) {
@@ -1519,7 +1521,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return;
}
}
writeTextOfNode(currentSourceFile, node);
if (nodeIsSynthesized(node)) {
write(node.text);
}
else {
writeTextOfNode(currentSourceFile, node);
}
}
function isNameOfNestedRedeclaration(node: Identifier) {
@@ -1546,6 +1554,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
else if (isNameOfNestedRedeclaration(node)) {
write(getGeneratedNameForNode(node));
}
else if (nodeIsSynthesized(node)) {
write(node.text);
}
else {
writeTextOfNode(currentSourceFile, node);
}
@@ -2105,7 +2116,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emit(node.name);
decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
}
function emitQualifiedName(node: QualifiedName) {
emit(node.left);
write(".");
@@ -2128,12 +2139,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
else {
emitEntityNameAsExpression(node.left, /*useFallback*/ false);
}
write(".");
emit(node.right);
}
function emitEntityNameAsExpression(node: EntityName, useFallback: boolean) {
function emitEntityNameAsExpression(node: EntityName, useFallback: boolean) {
switch (node.kind) {
case SyntaxKind.Identifier:
if (useFallback) {
@@ -2141,10 +2152,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitExpressionIdentifier(<Identifier>node);
write(" !== 'undefined' && ");
}
emitExpressionIdentifier(<Identifier>node);
break;
case SyntaxKind.QualifiedName:
emitQualifiedNameAsExpression(<QualifiedName>node, useFallback);
break;
@@ -3055,7 +3066,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (compilerOptions.module === ModuleKind.CommonJS || compilerOptions.module === ModuleKind.AMD || compilerOptions.module === ModuleKind.UMD) {
if (!currentSourceFile.symbol.exports["___esModule"]) {
if (languageVersion === ScriptTarget.ES5) {
// default value of configurable, enumerable, writable are `false`.
// default value of configurable, enumerable, writable are `false`.
write("Object.defineProperty(exports, \"__esModule\", { value: true });");
writeLine();
}
@@ -4311,7 +4322,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (ctor) {
// Emit all the directive prologues (like "use strict"). These have to come before
// any other preamble code we write (like parameter initializers).
startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true);
startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true);
emitDetachedComments(ctor.body.statements);
}
emitCaptureThisForNodeIfNecessary(node);
@@ -4883,7 +4894,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
return false;
}
/** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */
function emitSerializedTypeOfNode(node: Node) {
// serialization of the type of a declaration uses the following rules:
@@ -4894,100 +4905,98 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter.
// * The serialized type of any other FunctionLikeDeclaration is "Function".
// * The serialized type of any other node is "void 0".
//
//
// For rules on serializing type annotations, see `serializeTypeNode`.
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
write("Function");
return;
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertyDeclaration:
emitSerializedTypeNode((<PropertyDeclaration>node).type);
return;
case SyntaxKind.Parameter:
case SyntaxKind.Parameter:
emitSerializedTypeNode((<ParameterDeclaration>node).type);
return;
case SyntaxKind.GetAccessor:
case SyntaxKind.GetAccessor:
emitSerializedTypeNode((<AccessorDeclaration>node).type);
return;
case SyntaxKind.SetAccessor:
case SyntaxKind.SetAccessor:
emitSerializedTypeNode(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
return;
}
if (isFunctionLike(node)) {
write("Function");
return;
}
write("void 0");
}
function emitSerializedTypeNode(node: TypeNode) {
if (!node) {
return;
if (node) {
switch (node.kind) {
case SyntaxKind.VoidKeyword:
write("void 0");
return;
case SyntaxKind.ParenthesizedType:
emitSerializedTypeNode((<ParenthesizedTypeNode>node).type);
return;
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
write("Function");
return;
case SyntaxKind.ArrayType:
case SyntaxKind.TupleType:
write("Array");
return;
case SyntaxKind.TypePredicate:
case SyntaxKind.BooleanKeyword:
write("Boolean");
return;
case SyntaxKind.StringKeyword:
case SyntaxKind.StringLiteral:
write("String");
return;
case SyntaxKind.NumberKeyword:
write("Number");
return;
case SyntaxKind.SymbolKeyword:
write("Symbol");
return;
case SyntaxKind.TypeReference:
emitSerializedTypeReferenceNode(<TypeReferenceNode>node);
return;
case SyntaxKind.TypeQuery:
case SyntaxKind.TypeLiteral:
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
case SyntaxKind.AnyKeyword:
break;
default:
Debug.fail("Cannot serialize unexpected type node.");
break;
}
}
switch (node.kind) {
case SyntaxKind.VoidKeyword:
write("void 0");
return;
case SyntaxKind.ParenthesizedType:
emitSerializedTypeNode((<ParenthesizedTypeNode>node).type);
return;
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
write("Function");
return;
case SyntaxKind.ArrayType:
case SyntaxKind.TupleType:
write("Array");
return;
case SyntaxKind.TypePredicate:
case SyntaxKind.BooleanKeyword:
write("Boolean");
return;
case SyntaxKind.StringKeyword:
case SyntaxKind.StringLiteral:
write("String");
return;
case SyntaxKind.NumberKeyword:
write("Number");
return;
case SyntaxKind.SymbolKeyword:
write("Symbol");
return;
case SyntaxKind.TypeReference:
emitSerializedTypeReferenceNode(<TypeReferenceNode>node);
return;
case SyntaxKind.TypeQuery:
case SyntaxKind.TypeLiteral:
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
case SyntaxKind.AnyKeyword:
break;
default:
Debug.fail("Cannot serialize unexpected type node.");
break;
}
write("Object");
}
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
function emitSerializedTypeReferenceNode(node: TypeReferenceNode) {
let location: Node = node.parent;
@@ -5015,27 +5024,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue:
emitEntityNameAsExpression(typeName, /*useFallback*/ false);
break;
case TypeReferenceSerializationKind.VoidType:
write("void 0");
break;
case TypeReferenceSerializationKind.BooleanType:
write("Boolean");
break;
case TypeReferenceSerializationKind.NumberLikeType:
write("Number");
break;
case TypeReferenceSerializationKind.StringLikeType:
write("String");
break;
case TypeReferenceSerializationKind.ArrayLikeType:
write("Array");
break;
case TypeReferenceSerializationKind.ESSymbolType:
if (languageVersion < ScriptTarget.ES6) {
write("typeof Symbol === 'function' ? Symbol : Object");
@@ -5044,24 +5053,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write("Symbol");
}
break;
case TypeReferenceSerializationKind.TypeWithCallSignature:
write("Function");
break;
case TypeReferenceSerializationKind.ObjectType:
write("Object");
break;
}
}
/** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
function emitSerializedParameterTypesOfNode(node: Node) {
// serialization of parameter types uses the following rules:
//
// * If the declaration is a class, the parameters of the first constructor with a body are used.
// * If the declaration is function-like and has a body, the parameters of the function are used.
//
//
// For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
if (node) {
let valueDeclaration: FunctionLikeDeclaration;
@@ -5071,7 +5080,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
else if (isFunctionLike(node) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
valueDeclaration = <FunctionLikeDeclaration>node;
}
if (valueDeclaration) {
const parameters = valueDeclaration.parameters;
const parameterCount = parameters.length;
@@ -5080,7 +5089,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (i > 0) {
write(", ");
}
if (parameters[i].dotDotDotToken) {
let parameterType = parameters[i].type;
if (parameterType.kind === SyntaxKind.ArrayType) {
@@ -5092,7 +5101,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
else {
parameterType = undefined;
}
emitSerializedTypeNode(parameterType);
}
else {
@@ -5103,18 +5112,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}
}
/** Serializes the return type of function. Used by the __metadata decorator for a method. */
function emitSerializedReturnTypeOfNode(node: Node): string | string[] {
if (node && isFunctionLike(node) && (<FunctionLikeDeclaration>node).type) {
emitSerializedTypeNode((<FunctionLikeDeclaration>node).type);
return;
}
write("void 0");
}
function emitSerializedTypeMetadata(node: Declaration, writeComma: boolean): number {
// This method emits the serialized type metadata for a decorator target.
// The caller should have already tested whether the node has decorators.
@@ -5144,7 +5153,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (writeComma || argumentsWritten) {
write(", ");
}
writeLine();
write("__metadata('design:returntype', ");
emitSerializedReturnTypeOfNode(node);
@@ -5152,10 +5161,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
argumentsWritten++;
}
}
return argumentsWritten;
}
function emitInterfaceDeclaration(node: InterfaceDeclaration) {
emitOnlyPinnedOrTripleSlashComments(node);
}
@@ -5521,18 +5530,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
(!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
emitLeadingComments(node);
emitStart(node);
// variable declaration for import-equals declaration can be hoisted in system modules
// in this case 'var' should be omitted and emit should contain only initialization
let variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true);
// is it top level export import v = a.b.c in system module?
// if yes - it needs to be rewritten as exporter('v', v = a.b.c)
let isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true);
if (!variableDeclarationIsHoisted) {
Debug.assert(!isExported);
if (isES6ExportedDeclaration(node)) {
write("export ");
write("var ");
@@ -5541,8 +5550,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write("var ");
}
}
if (isExported) {
write(`${exportFunctionForFile}("`);
emitNodeWithoutSourceMap(node.name);
@@ -5556,8 +5565,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (isExported) {
write(")");
}
write(";");
write(";");
emitEnd(node);
emitExportImportAssignments(node);
emitTrailingComments(node);
@@ -6079,12 +6088,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
return;
}
if (isInternalModuleImportEqualsDeclaration(node)) {
if (!hoistedVars) {
hoistedVars = [];
}
hoistedVars.push(node.name);
return;
}
+4 -1
View File
@@ -4941,12 +4941,15 @@ namespace ts {
function parseModuleOrNamespaceDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, flags: NodeFlags): ModuleDeclaration {
let node = <ModuleDeclaration>createNode(SyntaxKind.ModuleDeclaration, fullStart);
// If we are parsing a dotted namespace name, we want to
// propagate the 'Namespace' flag across the names if set.
let namespaceFlag = flags & NodeFlags.Namespace;
node.decorators = decorators;
setModifiers(node, modifiers);
node.flags |= flags;
node.name = parseIdentifier();
node.body = parseOptional(SyntaxKind.DotToken)
? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.Export)
? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.Export | namespaceFlag)
: parseModuleBlock();
return finishNode(node);
}
+153 -3
View File
@@ -1,5 +1,6 @@
/// <reference path="sys.ts" />
/// <reference path="emitter.ts" />
/// <reference path="core.ts" />
namespace ts {
/* @internal */ export let programTime = 0;
@@ -36,11 +37,150 @@ namespace ts {
}
export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModule {
// TODO: use different resolution strategy based on compiler options
return legacyNameResolver(moduleName, containingFile, compilerOptions, host);
let moduleResolution = compilerOptions.moduleResolution !== undefined
? compilerOptions.moduleResolution
: compilerOptions.module === ModuleKind.CommonJS ? ModuleResolutionKind.NodeJs : ModuleResolutionKind.Classic;
switch (moduleResolution) {
case ModuleResolutionKind.NodeJs: return nodeModuleNameResolver(moduleName, containingFile, host);
case ModuleResolutionKind.Classic: return classicNameResolver(moduleName, containingFile, compilerOptions, host);
}
}
export function nodeModuleNameResolver(moduleName: string, containingFile: string, host: ModuleResolutionHost): ResolvedModule {
let containingDirectory = getDirectoryPath(containingFile);
if (getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) {
let failedLookupLocations: string[] = [];
let candidate = normalizePath(combinePaths(containingDirectory, moduleName));
let resolvedFileName = loadNodeModuleFromFile(candidate, /* loadOnlyDts */ false, failedLookupLocations, host);
if (resolvedFileName) {
return { resolvedFileName, failedLookupLocations };
}
resolvedFileName = loadNodeModuleFromDirectory(candidate, /* loadOnlyDts */ false, failedLookupLocations, host);
return { resolvedFileName, failedLookupLocations };
}
else {
return loadModuleFromNodeModules(moduleName, containingDirectory, host);
}
}
function loadNodeModuleFromFile(candidate: string, loadOnlyDts: boolean, failedLookupLocation: string[], host: ModuleResolutionHost): string {
if (loadOnlyDts) {
return tryLoad(".d.ts");
}
else {
return forEach(supportedExtensions, tryLoad);
}
function tryLoad(ext: string): string {
let fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
if (host.fileExists(fileName)) {
return fileName;
}
else {
failedLookupLocation.push(fileName);
return undefined;
}
}
}
function loadNodeModuleFromDirectory(candidate: string, loadOnlyDts: boolean, failedLookupLocation: string[], host: ModuleResolutionHost): string {
let packageJsonPath = combinePaths(candidate, "package.json");
if (host.fileExists(packageJsonPath)) {
let jsonContent: { typings?: string };
try {
let jsonText = host.readFile(packageJsonPath);
jsonContent = jsonText ? <{ typings?: string }>JSON.parse(jsonText) : { typings: undefined };
}
catch (e) {
// gracefully handle if readFile fails or returns not JSON
jsonContent = { typings: undefined };
}
if (jsonContent.typings) {
let result = loadNodeModuleFromFile(normalizePath(combinePaths(candidate, jsonContent.typings)), loadOnlyDts, failedLookupLocation, host);
if (result) {
return result;
}
}
}
else {
// record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results
failedLookupLocation.push(packageJsonPath);
}
return loadNodeModuleFromFile(combinePaths(candidate, "index"), loadOnlyDts, failedLookupLocation, host);
}
function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost): ResolvedModule {
let failedLookupLocations: string[] = [];
directory = normalizeSlashes(directory);
while (true) {
let baseName = getBaseFileName(directory);
if (baseName !== "node_modules") {
let nodeModulesFolder = combinePaths(directory, "node_modules");
let candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
let result = loadNodeModuleFromFile(candidate, /* loadOnlyDts */ true, failedLookupLocations, host);
if (result) {
return { resolvedFileName: result, failedLookupLocations };
}
result = loadNodeModuleFromDirectory(candidate, /* loadOnlyDts */ true, failedLookupLocations, host);
if (result) {
return { resolvedFileName: result, failedLookupLocations };
}
}
let parentPath = getDirectoryPath(directory);
if (parentPath === directory) {
break;
}
directory = parentPath;
}
return { resolvedFileName: undefined, failedLookupLocations };
}
export function baseUrlModuleNameResolver(moduleName: string, containingFile: string, baseUrl: string, host: ModuleResolutionHost): ResolvedModule {
Debug.assert(baseUrl !== undefined);
let normalizedModuleName = normalizeSlashes(moduleName);
let basePart = useBaseUrl(moduleName) ? baseUrl : getDirectoryPath(containingFile);
let candidate = normalizePath(combinePaths(basePart, moduleName));
let failedLookupLocations: string[] = [];
return forEach(supportedExtensions, ext => tryLoadFile(candidate + ext)) || { resolvedFileName: undefined, failedLookupLocations };
function tryLoadFile(location: string): ResolvedModule {
if (host.fileExists(location)) {
return { resolvedFileName: location, failedLookupLocations };
}
else {
failedLookupLocations.push(location);
return undefined;
}
}
}
function nameStartsWithDotSlashOrDotDotSlash(name: string) {
let i = name.lastIndexOf("./", 1);
return i === 0 || (i === 1 && name.charCodeAt(0) === CharacterCodes.dot);
}
function useBaseUrl(moduleName: string): boolean {
// path is not rooted
// module name does not start with './' or '../'
return getRootLength(moduleName) === 0 && !nameStartsWithDotSlashOrDotDotSlash(moduleName);
}
function legacyNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModule {
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModule {
// module names that contain '!' are used to reference resources and are not resolved to actual files on disk
if (moduleName.indexOf('!') != -1) {
@@ -85,6 +225,16 @@ namespace ts {
return { resolvedFileName: referencedSourceFile, failedLookupLocations };
}
/* @internal */
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES3,
noImplicitAny: false,
outDir: "built",
rootDir: ".",
sourceMap: false,
};
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
let currentDirectory: string;
let existingDirectories: Map<boolean> = {};
+70 -1
View File
@@ -159,6 +159,11 @@ namespace ts {
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
if (commandLine.options.init) {
writeConfigFile(commandLine.options, commandLine.fileNames);
return sys.exit(ExitStatus.Success);
}
if (commandLine.options.version) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version));
return sys.exit(ExitStatus.Success);
@@ -211,7 +216,7 @@ namespace ts {
if (!cachedProgram) {
if (configFileName) {
let result = readConfigFile(configFileName);
let result = readConfigFile(configFileName, sys.readFile);
if (result.error) {
reportDiagnostic(result.error);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
@@ -489,6 +494,70 @@ namespace ts {
return Array(paddingLength + 1).join(" ");
}
}
function writeConfigFile(options: CompilerOptions, fileNames: string[]) {
let currentDirectory = sys.getCurrentDirectory();
let file = combinePaths(currentDirectory, 'tsconfig.json');
if (sys.fileExists(file)) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file));
}
else {
let compilerOptions = extend(options, defaultInitCompilerOptions);
let configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions),
exclude: ["node_modules"]
};
if (fileNames && fileNames.length) {
// only set the files property if we have at least one file
configurations.files = fileNames;
}
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file));
}
return;
function serializeCompilerOptions(options: CompilerOptions): Map<string|number|boolean> {
let result: Map<string|number|boolean> = {};
let optionsNameMap = getOptionNameMap().optionNameMap;
for (let name in options) {
if (hasProperty(options, name)) {
let value = options[name];
switch (name) {
case "init":
case "watch":
case "version":
case "help":
case "project":
break;
default:
let optionDefinition = optionsNameMap[name.toLowerCase()];
if (optionDefinition) {
if (typeof optionDefinition.type === "string") {
// string, number or boolean
result[name] = value;
}
else {
// Enum
let typeMap = <Map<number>>optionDefinition.type;
for (let key in typeMap) {
if (hasProperty(typeMap, key)) {
if (typeMap[key] === value)
result[name] = key;
}
}
}
}
break;
}
}
}
return result;
}
}
}
ts.executeCommandLine(ts.sys.args);
+12 -3
View File
@@ -1552,8 +1552,8 @@ namespace ts {
export interface SymbolAccessiblityResult extends SymbolVisibilityResult {
errorModuleName?: string; // If the symbol is not visible from module, module's name
}
/** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator
/** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator
* metadata */
/* @internal */
export enum TypeReferenceSerializationKind {
@@ -1953,6 +1953,7 @@ namespace ts {
/* @internal */
export interface TypeMapper {
(t: TypeParameter): Type;
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
context?: InferenceContext; // The inference context this mapper was created from.
// Only inference mappers have this set (in createInferenceMapper).
// The identity mapper and regular instantiation mappers do not need it.
@@ -2009,7 +2010,12 @@ namespace ts {
Error,
Message,
}
export const enum ModuleResolutionKind {
Classic = 1,
NodeJs = 2
}
export interface CompilerOptions {
allowNonTsExtensions?: boolean;
charset?: string;
@@ -2017,6 +2023,7 @@ namespace ts {
diagnostics?: boolean;
emitBOM?: boolean;
help?: boolean;
init?: boolean;
inlineSourceMap?: boolean;
inlineSources?: boolean;
jsx?: JsxEmit;
@@ -2041,6 +2048,7 @@ namespace ts {
rootDir?: string;
sourceMap?: boolean;
sourceRoot?: string;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
version?: boolean;
@@ -2049,6 +2057,7 @@ namespace ts {
experimentalDecorators?: boolean;
experimentalAsyncFunctions?: boolean;
emitDecoratorMetadata?: boolean;
moduleResolution?: ModuleResolutionKind
/* @internal */ stripInternal?: boolean;
// Skip checking lib.d.ts to help speed up tests.
+2 -2
View File
@@ -611,11 +611,11 @@ namespace ts {
return false;
}
export function isAccessor(node: Node): boolean {
export function isAccessor(node: Node): node is AccessorDeclaration {
return node && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor);
}
export function isClassLike(node: Node): boolean {
export function isClassLike(node: Node): node is ClassLikeDeclaration {
return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression);
}
+29 -10
View File
@@ -425,6 +425,9 @@ module Harness {
listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[];
log(text: string): void;
getMemoryUsage?(): number;
args(): string[];
getExecutingFilePath(): string;
exit(exitCode?: number): void;
}
export var IO: IO;
@@ -446,7 +449,10 @@ module Harness {
} else {
fso = {};
}
export const args = () => ts.sys.args;
export const getExecutingFilePath = () => ts.sys.getExecutingFilePath();
export const exit = (exitCode: number) => ts.sys.exit(exitCode);
export const resolvePath = (path: string) => ts.sys.resolvePath(path);
export const getCurrentDirectory = () => ts.sys.getCurrentDirectory();
export const newLine = () => harnessNewLine;
@@ -517,6 +523,9 @@ module Harness {
export const getCurrentDirectory = () => ts.sys.getCurrentDirectory();
export const newLine = () => harnessNewLine;
export const useCaseSensitiveFileNames = () => ts.sys.useCaseSensitiveFileNames;
export const args = () => ts.sys.args;
export const getExecutingFilePath = () => ts.sys.getExecutingFilePath();
export const exit = (exitCode: number) => ts.sys.exit(exitCode);
export const readFile: typeof IO.readFile = path => ts.sys.readFile(path);
export const writeFile: typeof IO.writeFile = (path, content) => ts.sys.writeFile(path, content);
@@ -589,6 +598,10 @@ module Harness {
export const newLine = () => harnessNewLine;
export const useCaseSensitiveFileNames = () => false;
export const getCurrentDirectory = () => "";
export const args = () => <string[]>[];
export const getExecutingFilePath = () => "";
export const exit = (exitCode: number) => {};
let supportsCodePage = () => false;
module Http {
@@ -1195,8 +1208,8 @@ module Harness {
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) {
diagnostics.sort(ts.compareDiagnostics);
let outputLines: string[] = [];
// Count up all the errors we find so we don't miss any
let totalErrorsReported = 0;
// Count up all errors that were found in files other than lib.d.ts so we don't miss any
let totalErrorsReportedInNonLibraryFiles = 0;
function outputErrorText(error: ts.Diagnostic) {
let message = ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine());
@@ -1207,8 +1220,15 @@ module Harness {
.filter(s => s.length > 0)
.map(s => "!!! " + ts.DiagnosticCategory[error.category].toLowerCase() + " TS" + error.code + ": " + s);
errLines.forEach(e => outputLines.push(e));
totalErrorsReported++;
// do not count errors from lib.d.ts here, they are computed separately as numLibraryDiagnostics
// if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers)
// then they will be added twice thus triggering 'total errors' assertion with condition
// 'totalErrorsReportedInNonLibraryFiles + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length
if (!error.file || !isLibraryFile(error.file.fileName)) {
totalErrorsReportedInNonLibraryFiles++;
}
}
// Report global errors
@@ -1293,7 +1313,7 @@ module Harness {
});
// Verify we didn't miss any errors in total
assert.equal(totalErrorsReported + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length, "total number of errors");
assert.equal(totalErrorsReportedInNonLibraryFiles + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length, "total number of errors");
return minimalDiagnosticsToString(diagnostics) +
Harness.IO.newLine() + Harness.IO.newLine() + outputLines.join("\r\n");
@@ -1432,7 +1452,6 @@ module Harness {
let optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
function extractCompilerSettings(content: string): CompilerSettings {
let opts: CompilerSettings = {};
let match: RegExpExecArray;
@@ -1660,11 +1679,11 @@ module Harness {
return filePath.indexOf(Harness.libFolder) === 0;
}
export function getDefaultLibraryFile(): { unitName: string, content: string } {
let libFile = Harness.userSpecifiedRoot + Harness.libFolder + "/" + "lib.d.ts";
export function getDefaultLibraryFile(io: Harness.IO): { unitName: string, content: string } {
let libFile = Harness.userSpecifiedRoot + Harness.libFolder + "lib.d.ts";
return {
unitName: libFile,
content: IO.readFile(libFile)
content: io.readFile(libFile)
};
}
+20 -14
View File
@@ -93,7 +93,7 @@ module Playback {
return run;
}
export interface PlaybackSystem extends ts.System, PlaybackControl { }
export interface PlaybackIO extends Harness.IO, PlaybackControl { }
function createEmptyLog(): IOLog {
return {
@@ -223,8 +223,8 @@ module Playback {
// console.log("Swallowed write operation during replay: " + name);
}
export function wrapSystem(underlying: ts.System): PlaybackSystem {
let wrapper: PlaybackSystem = <any>{};
export function wrapIO(underlying: Harness.IO): PlaybackIO {
let wrapper: PlaybackIO = <any>{};
initWrapper(wrapper, underlying);
wrapper.startReplayFromFile = logFn => {
@@ -239,18 +239,24 @@ module Playback {
recordLog = undefined;
}
};
Object.defineProperty(wrapper, "args", {
get() {
if (replayLog !== undefined) {
return replayLog.arguments;
} else if (recordLog !== undefined) {
recordLog.arguments = underlying.args;
}
return underlying.args;
wrapper.args = () => {
if (replayLog !== undefined) {
return replayLog.arguments;
} else if (recordLog !== undefined) {
recordLog.arguments = underlying.args();
}
});
return underlying.args();
}
wrapper.newLine = () => underlying.newLine();
wrapper.useCaseSensitiveFileNames = () => underlying.useCaseSensitiveFileNames();
wrapper.directoryName = (path): string => { throw new Error("NotSupported"); };
wrapper.createDirectory = path => { throw new Error("NotSupported"); };
wrapper.directoryExists = (path): boolean => { throw new Error("NotSupported"); };
wrapper.deleteFile = path => { throw new Error("NotSupported"); };
wrapper.listFiles = (path, filter, options): string[] => { throw new Error("NotSupported"); };
wrapper.log = text => underlying.log(text);
wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)(
(path) => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path: path }),
+1
View File
@@ -163,6 +163,7 @@ class ProjectRunner extends RunnerBase {
mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? Harness.IO.resolvePath(testCase.mapRoot) : testCase.mapRoot,
sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? Harness.IO.resolvePath(testCase.sourceRoot) : testCase.sourceRoot,
module: moduleKind,
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
noResolve: testCase.noResolve,
rootDir: testCase.rootDir
};
+17 -17
View File
@@ -4,18 +4,18 @@
/// <reference path="..\compiler\commandLineParser.ts"/>
module RWC {
function runWithIOLog(ioLog: IOLog, fn: () => void) {
let oldSys = ts.sys;
function runWithIOLog(ioLog: IOLog, fn: (oldIO: Harness.IO) => void) {
let oldIO = Harness.IO;
let wrappedSys = Playback.wrapSystem(ts.sys);
wrappedSys.startReplayFromData(ioLog);
ts.sys = wrappedSys;
let wrappedIO = Playback.wrapIO(oldIO);
wrappedIO.startReplayFromData(ioLog);
Harness.IO = wrappedIO;
try {
fn();
fn(oldIO);
} finally {
wrappedSys.endReplay();
ts.sys = oldSys;
wrappedIO.endReplay();
Harness.IO = oldIO;
}
}
@@ -32,7 +32,6 @@ module RWC {
let baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2];
let currentDirectory: string;
let useCustomLibraryFile: boolean;
after(() => {
// Mocha holds onto the closure environment of the describe callback even after the test is done.
// Therefore we have to clean out large objects after the test is done.
@@ -57,7 +56,7 @@ module RWC {
currentDirectory = ioLog.currentDirectory;
useCustomLibraryFile = ioLog.useCustomLibraryFile;
runWithIOLog(ioLog, () => {
opts = ts.parseCommandLine(ioLog.arguments);
opts = ts.parseCommandLine(ioLog.arguments, fileName => Harness.IO.readFile(fileName));
assert.equal(opts.errors.length, 0);
// To provide test coverage of output javascript file,
@@ -65,7 +64,7 @@ module RWC {
opts.options.noEmitOnError = false;
});
runWithIOLog(ioLog, () => {
runWithIOLog(ioLog, oldIO => {
harnessCompiler.reset();
// Load the files
@@ -77,7 +76,7 @@ module RWC {
let isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath;
for (let fileRead of ioLog.filesRead) {
// Check if the file is already added into the set of input files.
const resolvedPath = ts.normalizeSlashes(ts.sys.resolvePath(fileRead.path));
const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path));
let inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath));
if (!Harness.isLibraryFile(fileRead.path)) {
@@ -97,7 +96,8 @@ module RWC {
inputFiles.push(getHarnessCompilerInputUnit(fileRead.path));
}
else {
inputFiles.push(Harness.getDefaultLibraryFile());
// set the flag to put default library to the beginning of the list
inputFiles.unshift(Harness.getDefaultLibraryFile(oldIO));
}
}
}
@@ -118,13 +118,13 @@ module RWC {
});
function getHarnessCompilerInputUnit(fileName: string) {
let unitName = ts.normalizeSlashes(ts.sys.resolvePath(fileName));
let unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName));
let content: string = null;
try {
content = ts.sys.readFile(unitName);
content = Harness.IO.readFile(unitName);
}
catch (e) {
content = ts.sys.readFile(fileName);
content = Harness.IO.readFile(fileName);
}
return { unitName, content };
}
@@ -187,7 +187,7 @@ module RWC {
}
return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) +
ts.sys.newLine + ts.sys.newLine +
Harness.IO.newLine() + Harness.IO.newLine() +
Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
}, false, baselineOpts);
}
+18 -4
View File
@@ -7706,7 +7706,7 @@ interface MessageEvent extends Event {
declare var MessageEvent: {
prototype: MessageEvent;
new(): MessageEvent;
new(type: string, eventInitDict?: MessageEventInit): MessageEvent;
}
interface MessagePort extends EventTarget {
@@ -8448,7 +8448,7 @@ interface ProgressEvent extends Event {
declare var ProgressEvent: {
prototype: ProgressEvent;
new(): ProgressEvent;
new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent;
}
interface Range {
@@ -12615,7 +12615,6 @@ interface NodeListOf<TNode extends Node> extends NodeList {
[index: number]: TNode;
}
interface BlobPropertyBag {
type?: string;
endings?: string;
@@ -12632,6 +12631,21 @@ interface EventListenerObject {
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface MessageEventInit extends EventInit {
data?: any;
origin?: string;
lastEventId?: string;
channel?: string;
source?: any;
ports?: MessagePort[];
}
interface ProgressEventInit extends EventInit {
lengthComputable?: boolean;
loaded?: number;
total?: number;
}
interface ErrorEventHandler {
(message: string, filename?: string, lineno?: number, colno?: number, error?:Error): void;
}
@@ -12961,4 +12975,4 @@ declare function addEventListener(type: "unload", listener: (ev: Event) => any,
declare function addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
declare function addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
declare function addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
+30 -2
View File
@@ -88,6 +88,7 @@ declare module Intl {
timeZoneName?: string;
formatMatcher?: string;
hour12?: boolean;
timeZone?: string;
}
interface ResolvedDateTimeFormatOptions {
@@ -157,17 +158,44 @@ interface Number {
interface Date {
/**
* Converts a date to a string by using the current or specified locale.
* Converts a date and time to a string by using the current or specified locale.
* @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
* @param options An object that contains one or more properties that specify comparison options.
*/
toLocaleString(locales?: string[], options?: Intl.DateTimeFormatOptions): string;
/**
* Converts a date to a string by using the current or specified locale.
* @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
* @param options An object that contains one or more properties that specify comparison options.
*/
toLocaleDateString(locales?: string[], options?: Intl.DateTimeFormatOptions): string;
/**
* Converts a time to a string by using the current or specified locale.
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
* @param options An object that contains one or more properties that specify comparison options.
*/
toLocaleTimeString(locale?: string[], options?: Intl.DateTimeFormatOptions): string;
/**
* Converts a date and time to a string by using the current or specified locale.
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
* @param options An object that contains one or more properties that specify comparison options.
*/
toLocaleString(locale?: string, options?: Intl.DateTimeFormatOptions): string;
/**
* Converts a date to a string by using the current or specified locale.
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
* @param options An object that contains one or more properties that specify comparison options.
*/
toLocaleString(locale?: string, options?: Intl.DateTimeFormatOptions): string;
toLocaleDateString(locale?: string, options?: Intl.DateTimeFormatOptions): string;
/**
* Converts a time to a string by using the current or specified locale.
* @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used.
* @param options An object that contains one or more properties that specify comparison options.
*/
toLocaleTimeString(locale?: string, options?: Intl.DateTimeFormatOptions): string;
}
+18 -3
View File
@@ -587,7 +587,7 @@ interface MessageEvent extends Event {
declare var MessageEvent: {
prototype: MessageEvent;
new(): MessageEvent;
new(type: string, eventInitDict?: MessageEventInit): MessageEvent;
}
interface MessagePort extends EventTarget {
@@ -640,7 +640,7 @@ interface ProgressEvent extends Event {
declare var ProgressEvent: {
prototype: ProgressEvent;
new(): ProgressEvent;
new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent;
}
interface WebSocket extends EventTarget {
@@ -911,6 +911,21 @@ interface EventListenerObject {
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface MessageEventInit extends EventInit {
data?: any;
origin?: string;
lastEventId?: string;
channel?: string;
source?: any;
ports?: MessagePort[];
}
interface ProgressEventInit extends EventInit {
lengthComputable?: boolean;
loaded?: number;
total?: number;
}
interface ErrorEventHandler {
(message: string, filename?: string, lineno?: number, colno?: number, error?:Error): void;
}
@@ -967,4 +982,4 @@ declare function postMessage(data: any): void;
declare var console: Console;
declare function addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
declare function addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
+31 -31
View File
@@ -614,30 +614,30 @@ namespace ts.server {
}
this.configuredProjects = configuredProjects;
}
removeConfiguredProject(project: Project) {
project.projectFileWatcher.close();
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
let fileNames = project.getFileNames();
for (let fileName of fileNames) {
let info = this.getScriptInfo(fileName);
if (info.defaultProject == project){
info.defaultProject = undefined;
}
removeConfiguredProject(project: Project) {
project.projectFileWatcher.close();
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
let fileNames = project.getFileNames();
for (let fileName of fileNames) {
let info = this.getScriptInfo(fileName);
if (info.defaultProject == project) {
info.defaultProject = undefined;
}
}
}
setConfiguredProjectRoot(info: ScriptInfo) {
for (var i = 0, len = this.configuredProjects.length; i < len; i++) {
let configuredProject = this.configuredProjects[i];
if (configuredProject.isRoot(info)) {
info.defaultProject = configuredProject;
configuredProject.addOpenRef();
return true;
}
}
return false;
for (var i = 0, len = this.configuredProjects.length; i < len; i++) {
let configuredProject = this.configuredProjects[i];
if (configuredProject.isRoot(info)) {
info.defaultProject = configuredProject;
configuredProject.addOpenRef();
return true;
}
}
return false;
}
addOpenFile(info: ScriptInfo) {
@@ -785,7 +785,7 @@ namespace ts.server {
updateProjectStructure() {
this.log("updating project structure from ...", "Info");
this.printProjects();
let unattachedOpenFiles: ScriptInfo[] = [];
let openFileRootsConfigured: ScriptInfo[] = [];
for (let info of this.openFileRootsConfigured) {
@@ -921,10 +921,10 @@ namespace ts.server {
this.printProjects();
return info;
}
openOrUpdateConfiguredProjectForFile(fileName: string) {
let searchPath = ts.normalizePath(getDirectoryPath(fileName));
this.log("Search path: " + searchPath,"Info");
this.log("Search path: " + searchPath, "Info");
let configFileName = this.findConfigFile(searchPath);
if (configFileName) {
this.log("Config file name: " + configFileName, "Info");
@@ -935,7 +935,7 @@ namespace ts.server {
this.log("Error opening config file " + configFileName + " " + configResult.errorMsg);
}
else {
this.log("Opened configuration file " + configFileName,"Info");
this.log("Opened configuration file " + configFileName, "Info");
this.configuredProjects.push(configResult.project);
}
}
@@ -1000,7 +1000,7 @@ namespace ts.server {
for (var i = 0, len = this.configuredProjects.length; i < len; i++) {
var project = this.configuredProjects[i];
project.updateGraph();
this.psLogger.info("Project (configured) " + (i+this.inferredProjects.length).toString());
this.psLogger.info("Project (configured) " + (i + this.inferredProjects.length).toString());
this.psLogger.info(project.filesToString());
this.psLogger.info("-----------------------------------------------");
}
@@ -1048,10 +1048,10 @@ namespace ts.server {
else {
var parsedCommandLine = ts.parseConfigFile(rawConfig.config, this.host, dirPath);
if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) {
return { succeeded: false, error: { errorMsg: "tsconfig option errors" }};
return { succeeded: false, error: { errorMsg: "tsconfig option errors" } };
}
else if (parsedCommandLine.fileNames == null) {
return { succeeded: false, error: { errorMsg: "no files found" }}
return { succeeded: false, error: { errorMsg: "no files found" } }
}
else {
var projectOptions: ProjectOptions = {
@@ -1068,7 +1068,7 @@ namespace ts.server {
let { succeeded, projectOptions, error } = this.configFileToProjectOptions(configFilename);
if (!succeeded) {
return error;
}
}
else {
let proj = this.createProject(configFilename, projectOptions);
for (let i = 0, len = projectOptions.files.length; i < len; i++) {
@@ -1086,7 +1086,7 @@ namespace ts.server {
return { success: true, project: proj };
}
}
updateConfiguredProject(project: Project) {
if (!this.host.fileExists(project.projectFilename)) {
this.log("Config file deleted");
@@ -1098,16 +1098,16 @@ namespace ts.server {
return error;
}
else {
let oldFileNames = project.compilerService.host.roots.map(info => info.fileName);
let oldFileNames = project.compilerService.host.roots.map(info => info.fileName);
let newFileNames = projectOptions.files;
let fileNamesToRemove = oldFileNames.filter(f => newFileNames.indexOf(f) < 0);
let fileNamesToAdd = newFileNames.filter(f => oldFileNames.indexOf(f) < 0);
for (let fileName of fileNamesToRemove) {
let info = this.getScriptInfo(fileName);
project.removeRoot(info);
}
for (let fileName of fileNamesToAdd) {
let info = this.getScriptInfo(fileName);
if (!info) {
+12 -8
View File
@@ -32,7 +32,7 @@ namespace ts.formatting {
*/
interface DynamicIndentation {
getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind): number;
getIndentationForComment(owningToken: SyntaxKind): number;
getIndentationForComment(owningToken: SyntaxKind, tokenIndentation: number): number;
/**
* Indentation for open and close tokens of the node if it is block or another node that needs special indentation
* ... {
@@ -455,7 +455,7 @@ namespace ts.formatting {
function getDynamicIndentation(node: Node, nodeStartLine: number, indentation: number, delta: number): DynamicIndentation {
return {
getIndentationForComment: kind => {
getIndentationForComment: (kind, tokenIndentation) => {
switch (kind) {
// preceding comment to the token that closes the indentation scope inherits the indentation from the scope
// .. {
@@ -463,9 +463,10 @@ namespace ts.formatting {
// }
case SyntaxKind.CloseBraceToken:
case SyntaxKind.CloseBracketToken:
case SyntaxKind.CloseParenToken:
return indentation + delta;
}
return indentation;
return tokenIndentation !== Constants.Unknown ? tokenIndentation : indentation;
},
getIndentationForToken: (line, kind) => {
if (nodeStartLine !== line && node.decorators) {
@@ -716,8 +717,14 @@ namespace ts.formatting {
}
if (indentToken) {
let indentNextTokenOrTrivia = true;
let tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ?
dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind) :
Constants.Unknown;
if (currentTokenInfo.leadingTrivia) {
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation);
let indentNextTokenOrTrivia = true;
for (let triviaItem of currentTokenInfo.leadingTrivia) {
if (!rangeContainsRange(originalRange, triviaItem)) {
continue;
@@ -725,13 +732,11 @@ namespace ts.formatting {
switch (triviaItem.kind) {
case SyntaxKind.MultiLineCommentTrivia:
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia);
indentNextTokenOrTrivia = false;
break;
case SyntaxKind.SingleLineCommentTrivia:
if (indentNextTokenOrTrivia) {
let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false);
indentNextTokenOrTrivia = false;
}
@@ -744,8 +749,7 @@ namespace ts.formatting {
}
// indent token only if is it is in target range and does not overlap with any error ranges
if (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) {
let tokenIndentation = dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind);
if (tokenIndentation !== Constants.Unknown) {
insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
lastIndentedLine = tokenStart.line;
+23 -2
View File
@@ -17,7 +17,8 @@ namespace ts.formatting {
Scan,
RescanGreaterThanToken,
RescanSlashToken,
RescanTemplateToken
RescanTemplateToken,
RescanJsxIdentifier
}
export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
@@ -108,6 +109,20 @@ namespace ts.formatting {
return false;
}
function shouldRescanJsxIdentifier(node: Node): boolean {
if (node.parent) {
switch(node.parent.kind) {
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
return node.kind === SyntaxKind.Identifier;
}
}
return false;
}
function shouldRescanSlashToken(container: Node): boolean {
return container.kind === SyntaxKind.RegularExpressionLiteral;
@@ -141,7 +156,9 @@ namespace ts.formatting {
? ScanAction.RescanSlashToken
: shouldRescanTemplateToken(n)
? ScanAction.RescanTemplateToken
: ScanAction.Scan
: shouldRescanJsxIdentifier(n)
? ScanAction.RescanJsxIdentifier
: ScanAction.Scan
if (lastTokenInfo && expectedScanAction === lastScanAction) {
// readTokenInfo was called before with the same expected scan action.
@@ -176,6 +193,10 @@ namespace ts.formatting {
currentToken = scanner.reScanTemplateToken();
lastScanAction = ScanAction.RescanTemplateToken;
}
else if (expectedScanAction === ScanAction.RescanJsxIdentifier && currentToken === SyntaxKind.Identifier) {
currentToken = scanner.scanJsxIdentifier();
lastScanAction = ScanAction.RescanJsxIdentifier;
}
else {
lastScanAction = ScanAction.Scan;
}
+52 -1
View File
@@ -213,6 +213,28 @@ namespace ts.formatting {
public NoSpaceBetweenYieldKeywordAndStar: Rule;
public SpaceBetweenYieldOrYieldStarAndOperand: Rule;
// Async-await
public SpaceBetweenAsyncAndFunctionKeyword: Rule;
public NoSpaceBetweenAsyncAndFunctionKeyword: Rule;
public SpaceAfterAwaitKeyword: Rule;
public NoSpaceAfterAwaitKeyword: Rule;
// Type alias declaration
public SpaceAfterTypeKeyword: Rule;
public NoSpaceAfterTypeKeyword: Rule;
// Tagged template string
public SpaceBetweenTagAndTemplateString: Rule;
public NoSpaceBetweenTagAndTemplateString: Rule;
// Type operation
public SpaceBeforeBar: Rule;
public NoSpaceBeforeBar: Rule;
public SpaceAfterBar: Rule;
public NoSpaceAfterBar: Rule;
public SpaceBeforeAmpersand: Rule;
public SpaceAfterAmpersand: Rule;
constructor() {
///
/// Common Rules
@@ -252,7 +274,7 @@ namespace ts.formatting {
this.SpaceBeforeOpenBraceInFunction = new Rule(RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines);
// Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc)
this.TypeScriptOpenBraceLeftTokenRange = Shared.TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.MultiLineCommentTrivia]);
this.TypeScriptOpenBraceLeftTokenRange = Shared.TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.ClassKeyword]);
this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new Rule(RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines);
// Place a space before open brace in a control flow construct
@@ -360,6 +382,28 @@ namespace ts.formatting {
this.NoSpaceBetweenYieldKeywordAndStar = new Rule(RuleDescriptor.create1(SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), RuleAction.Delete));
this.SpaceBetweenYieldOrYieldStarAndOperand = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), RuleAction.Space));
// Async-await
this.SpaceBetweenAsyncAndFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.NoSpaceBetweenAsyncAndFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
this.SpaceAfterAwaitKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.AwaitKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.NoSpaceAfterAwaitKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.AwaitKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
// Type alias declaration
this.SpaceAfterTypeKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.TypeKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.NoSpaceAfterTypeKeyword = new Rule(RuleDescriptor.create3(SyntaxKind.TypeKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
// template string
this.SpaceBetweenTagAndTemplateString = new Rule(RuleDescriptor.create3(SyntaxKind.Identifier, Shared.TokenRange.FromTokens([SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.NoSpaceBetweenTagAndTemplateString = new Rule(RuleDescriptor.create3(SyntaxKind.Identifier, Shared.TokenRange.FromTokens([SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
// type operation
this.SpaceBeforeBar = new Rule(RuleDescriptor.create3(SyntaxKind.BarToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.NoSpaceBeforeBar = new Rule(RuleDescriptor.create3(SyntaxKind.BarToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
this.SpaceAfterBar = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.BarToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.NoSpaceAfterBar = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.BarToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
this.SpaceBeforeAmpersand = new Rule(RuleDescriptor.create3(SyntaxKind.AmpersandToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
this.SpaceAfterAmpersand = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.AmpersandToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
// These rules are higher in priority than user-configurable rules.
this.HighPriorityCommonRules =
[
@@ -386,6 +430,12 @@ namespace ts.formatting {
this.NoSpaceBeforeOpenParenInFuncCall,
this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator,
this.SpaceAfterVoidOperator,
this.SpaceBetweenAsyncAndFunctionKeyword, this.NoSpaceBetweenAsyncAndFunctionKeyword,
this.SpaceAfterAwaitKeyword, this.NoSpaceAfterAwaitKeyword,
this.SpaceAfterTypeKeyword, this.NoSpaceAfterTypeKeyword,
this.SpaceBetweenTagAndTemplateString, this.NoSpaceBetweenTagAndTemplateString,
this.SpaceBeforeBar, this.NoSpaceBeforeBar, this.SpaceAfterBar, this.NoSpaceAfterBar,
this.SpaceBeforeAmpersand, this.SpaceAfterAmpersand,
// TypeScript-specific rules
this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
@@ -617,6 +667,7 @@ namespace ts.formatting {
static NodeIsTypeScriptDeclWithBlockContext(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.TypeLiteral:
+12 -2
View File
@@ -406,8 +406,10 @@ namespace ts.formatting {
function nodeContentIsAlwaysIndented(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.Block:
case SyntaxKind.ModuleBlock:
@@ -429,6 +431,16 @@ namespace ts.formatting {
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.MethodSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.Parameter:
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.ParenthesizedType:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.AwaitExpression:
return true;
}
return false;
@@ -448,8 +460,6 @@ namespace ts.formatting {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
+42 -16
View File
@@ -1866,7 +1866,7 @@ namespace ts {
let sourceMapText: string;
// Create a compilerHost object to allow the compiler to read and write files
let compilerHost: CompilerHost = {
getSourceFile: (fileName, target) => fileName === inputFileName ? sourceFile : undefined,
getSourceFile: (fileName, target) => fileName === normalizeSlashes(inputFileName) ? sourceFile : undefined,
writeFile: (name, text, writeByteOrderMark) => {
if (fileExtensionIs(name, ".map")) {
Debug.assert(sourceMapText === undefined, `Unexpected multiple source map outputs for the file '${name}'`);
@@ -3589,10 +3589,11 @@ namespace ts {
containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { foo, |
isFunction(containingNodeKind) ||
containingNodeKind === SyntaxKind.ClassDeclaration || // class A<T, |
containingNodeKind === SyntaxKind.FunctionDeclaration || // function A<T, |
containingNodeKind === SyntaxKind.ClassExpression || // var C = class D<T, |
containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A<T, |
containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [x, y|
containingNodeKind === SyntaxKind.ArrayBindingPattern || // var [x, y|
containingNodeKind === SyntaxKind.TypeAliasDeclaration; // type Map, K, |
case SyntaxKind.DotToken:
return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [.|
@@ -3619,8 +3620,9 @@ namespace ts {
case SyntaxKind.LessThanToken:
return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< |
containingNodeKind === SyntaxKind.FunctionDeclaration || // function A< |
containingNodeKind === SyntaxKind.ClassExpression || // var C = class D< |
containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A< |
containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type List< |
isFunction(containingNodeKind);
case SyntaxKind.StaticKeyword:
@@ -4181,6 +4183,7 @@ namespace ts {
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
displayParts.push(spacePart());
addFullSymbolName(symbol);
writeTypeParametersOfSymbol(symbol, sourceFile);
displayParts.push(spacePart());
displayParts.push(operatorPart(SyntaxKind.EqualsToken));
displayParts.push(spacePart());
@@ -4221,16 +4224,29 @@ namespace ts {
}
else {
// Method/function type parameter
let signatureDeclaration = <SignatureDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent;
let signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration);
if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) {
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
let container = getContainingFunction(location);
if (container) {
let signatureDeclaration = <SignatureDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent;
let signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration);
if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) {
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
displayParts.push(spacePart());
}
else if (signatureDeclaration.kind !== SyntaxKind.CallSignature && signatureDeclaration.name) {
addFullSymbolName(signatureDeclaration.symbol);
}
addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature));
}
else {
// Type aliash type parameter
// For example
// type list<T> = T[]; // Both T will go through same code path
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent;
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
displayParts.push(spacePart());
addFullSymbolName(declaration.symbol);
writeTypeParametersOfSymbol(declaration.symbol, sourceFile);
}
else if (signatureDeclaration.kind !== SyntaxKind.CallSignature && signatureDeclaration.name) {
addFullSymbolName(signatureDeclaration.symbol);
}
addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature));
}
}
if (symbolFlags & SymbolFlags.EnumMember) {
@@ -4464,10 +4480,19 @@ namespace ts {
// and in either case the symbol has a construct signature definition, i.e. class
if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) {
if (symbol.flags & SymbolFlags.Class) {
let classDeclaration = <ClassDeclaration>symbol.getDeclarations()[0];
Debug.assert(classDeclaration && classDeclaration.kind === SyntaxKind.ClassDeclaration);
// Find the first class-like declaration and try to get the construct signature.
for (let declaration of symbol.getDeclarations()) {
if (isClassLike(declaration)) {
return tryAddSignature(declaration.members,
/*selectConstructors*/ true,
symbolKind,
symbolName,
containerName,
result);
}
}
return tryAddSignature(classDeclaration.members, /*selectConstructors*/ true, symbolKind, symbolName, containerName, result);
Debug.fail("Expected declaration to have at least one class-like declaration");
}
}
return false;
@@ -5860,6 +5885,7 @@ namespace ts {
result.push(getReferenceEntryFromNode(node));
}
break;
case SyntaxKind.ClassExpression:
case SyntaxKind.ClassDeclaration:
// Make sure the container belongs to the same class
// and has the appropriate static modifier from the original container.
+25 -14
View File
@@ -360,7 +360,7 @@ namespace ts {
return find(startNode || sourceFile);
function findRightmostToken(n: Node): Node {
if (isToken(n)) {
if (isToken(n) || n.kind === SyntaxKind.JsxText) {
return n;
}
@@ -371,24 +371,35 @@ namespace ts {
}
function find(n: Node): Node {
if (isToken(n)) {
if (isToken(n) || n.kind === SyntaxKind.JsxText) {
return n;
}
let children = n.getChildren();
const children = n.getChildren();
for (let i = 0, len = children.length; i < len; i++) {
let child = children[i];
if (nodeHasTokens(child)) {
if (position <= child.end) {
if (child.getStart(sourceFile) >= position) {
// actual start of the node is past the position - previous token should be at the end of previous child
let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
return candidate && findRightmostToken(candidate)
}
else {
// candidate should be in this node
return find(child);
}
// condition 'position < child.end' checks if child node end after the position
// in the example below this condition will be false for 'aaaa' and 'bbbb' and true for 'ccc'
// aaaa___bbbb___$__ccc
// after we found child node with end after the position we check if start of the node is after the position.
// if yes - then position is in the trivia and we need to look into the previous child to find the token in question.
// if no - position is in the node itself so we should recurse in it.
// NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia).
// if this is the case - then we should assume that token in question is located in previous child.
if (position < child.end && (nodeHasTokens(child) || child.kind === SyntaxKind.JsxText)) {
const start = child.getStart(sourceFile);
const lookInPreviousChild =
(start >= position) || // cursor in the leading trivia
(child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText
if (lookInPreviousChild) {
// actual start of the node is past the position - previous token should be at the end of previous child
let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
return candidate && findRightmostToken(candidate)
}
else {
// candidate should be in this node
return find(child);
}
}
}