mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into typeParametersAsConstraints
Conflicts: tests/baselines/reference/functionConstraintSatisfaction2.errors.txt
This commit is contained in:
+315
-153
@@ -51,6 +51,7 @@ namespace ts {
|
||||
const emitResolver = createResolver();
|
||||
|
||||
const undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
|
||||
undefinedSymbol.declarations = [];
|
||||
const argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments");
|
||||
|
||||
const checker: TypeChecker = {
|
||||
@@ -141,9 +142,6 @@ namespace ts {
|
||||
let globalRegExpType: ObjectType;
|
||||
let globalTemplateStringsArrayType: ObjectType;
|
||||
let globalESSymbolType: ObjectType;
|
||||
let jsxElementType: ObjectType;
|
||||
/** Lazily loaded, use getJsxIntrinsicElementType() */
|
||||
let jsxIntrinsicElementsType: ObjectType;
|
||||
let globalIterableType: GenericType;
|
||||
let globalIteratorType: GenericType;
|
||||
let globalIterableIteratorType: GenericType;
|
||||
@@ -208,12 +206,17 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
|
||||
let jsxElementType: ObjectType;
|
||||
/** Things we lazy load from the JSX namespace */
|
||||
const jsxTypes: Map<ObjectType> = {};
|
||||
const JsxNames = {
|
||||
JSX: "JSX",
|
||||
IntrinsicElements: "IntrinsicElements",
|
||||
ElementClass: "ElementClass",
|
||||
ElementAttributesPropertyNameContainer: "ElementAttributesProperty",
|
||||
Element: "Element"
|
||||
Element: "Element",
|
||||
IntrinsicAttributes: "IntrinsicAttributes",
|
||||
IntrinsicClassAttributes: "IntrinsicClassAttributes"
|
||||
};
|
||||
|
||||
const subtypeRelation: Map<RelationComparisonResult> = {};
|
||||
@@ -232,6 +235,10 @@ namespace ts {
|
||||
ResolvedReturnType
|
||||
}
|
||||
|
||||
const builtinGlobals: SymbolTable = {
|
||||
[undefinedSymbol.name]: undefinedSymbol
|
||||
};
|
||||
|
||||
initializeTypeChecker();
|
||||
|
||||
return checker;
|
||||
@@ -358,6 +365,24 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function addToSymbolTable(target: SymbolTable, source: SymbolTable, message: DiagnosticMessage) {
|
||||
for (const id in source) {
|
||||
if (hasProperty(source, id)) {
|
||||
if (hasProperty(target, id)) {
|
||||
// Error on redeclarations
|
||||
forEach(target[id].declarations, addDeclarationDiagnostic(id, message));
|
||||
}
|
||||
else {
|
||||
target[id] = source[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addDeclarationDiagnostic(id: string, message: DiagnosticMessage) {
|
||||
return (declaration: Declaration) => diagnostics.add(createDiagnosticForNode(declaration, message, id));
|
||||
}
|
||||
}
|
||||
|
||||
function getSymbolLinks(symbol: Symbol): SymbolLinks {
|
||||
if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
|
||||
const id = getSymbolId(symbol);
|
||||
@@ -377,6 +402,14 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(<SourceFile>node);
|
||||
}
|
||||
|
||||
/** Is this type one of the apparent types created from the primitive types. */
|
||||
function isPrimitiveApparentType(type: Type): boolean {
|
||||
return type === globalStringType ||
|
||||
type === globalNumberType ||
|
||||
type === globalBooleanType ||
|
||||
type === globalESSymbolType;
|
||||
}
|
||||
|
||||
function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol {
|
||||
if (meaning && hasProperty(symbols, name)) {
|
||||
const symbol = symbols[name];
|
||||
@@ -1093,39 +1126,81 @@ namespace ts {
|
||||
return links.resolvedExports || (links.resolvedExports = getExportsForModule(moduleSymbol));
|
||||
}
|
||||
|
||||
function extendExportSymbols(target: SymbolTable, source: SymbolTable) {
|
||||
interface ExportCollisionTracker {
|
||||
specifierText: string;
|
||||
exportsWithDuplicate: ExportDeclaration[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument
|
||||
* Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables
|
||||
*/
|
||||
function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: Map<ExportCollisionTracker>, exportNode?: ExportDeclaration) {
|
||||
for (const id in source) {
|
||||
if (id !== "default" && !hasProperty(target, id)) {
|
||||
target[id] = source[id];
|
||||
if (lookupTable && exportNode) {
|
||||
lookupTable[id] = {
|
||||
specifierText: getTextOfNode(exportNode.moduleSpecifier)
|
||||
} as ExportCollisionTracker;
|
||||
}
|
||||
}
|
||||
else if (lookupTable && exportNode && id !== "default" && hasProperty(target, id) && resolveSymbol(target[id]) !== resolveSymbol(source[id])) {
|
||||
if (!lookupTable[id].exportsWithDuplicate) {
|
||||
lookupTable[id].exportsWithDuplicate = [exportNode];
|
||||
}
|
||||
else {
|
||||
lookupTable[id].exportsWithDuplicate.push(exportNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getExportsForModule(moduleSymbol: Symbol): SymbolTable {
|
||||
let result: SymbolTable;
|
||||
const visitedSymbols: Symbol[] = [];
|
||||
visit(moduleSymbol);
|
||||
return result || moduleSymbol.exports;
|
||||
return visit(moduleSymbol) || moduleSymbol.exports;
|
||||
|
||||
// The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
|
||||
// module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
|
||||
function visit(symbol: Symbol) {
|
||||
if (symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol)) {
|
||||
visitedSymbols.push(symbol);
|
||||
if (symbol !== moduleSymbol) {
|
||||
if (!result) {
|
||||
result = cloneSymbolTable(moduleSymbol.exports);
|
||||
}
|
||||
extendExportSymbols(result, symbol.exports);
|
||||
}
|
||||
// All export * declarations are collected in an __export symbol by the binder
|
||||
const exportStars = symbol.exports["__export"];
|
||||
if (exportStars) {
|
||||
for (const node of exportStars.declarations) {
|
||||
visit(resolveExternalModuleName(node, (<ExportDeclaration>node).moduleSpecifier));
|
||||
}
|
||||
}
|
||||
function visit(symbol: Symbol): SymbolTable {
|
||||
if (!(symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol))) {
|
||||
return;
|
||||
}
|
||||
visitedSymbols.push(symbol);
|
||||
const symbols = cloneSymbolTable(symbol.exports);
|
||||
// All export * declarations are collected in an __export symbol by the binder
|
||||
const exportStars = symbol.exports["__export"];
|
||||
if (exportStars) {
|
||||
const nestedSymbols: SymbolTable = {};
|
||||
const lookupTable: Map<ExportCollisionTracker> = {};
|
||||
for (const node of exportStars.declarations) {
|
||||
const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier);
|
||||
const exportedSymbols = visit(resolvedModule);
|
||||
extendExportSymbols(
|
||||
nestedSymbols,
|
||||
exportedSymbols,
|
||||
lookupTable,
|
||||
node as ExportDeclaration
|
||||
);
|
||||
}
|
||||
for (const id in lookupTable) {
|
||||
const { exportsWithDuplicate } = lookupTable[id];
|
||||
// It's not an error if the file with multiple `export *`s with duplicate names exports a member with that name itself
|
||||
if (id === "export=" || !(exportsWithDuplicate && exportsWithDuplicate.length) || hasProperty(symbols, id)) {
|
||||
continue;
|
||||
}
|
||||
for (const node of exportsWithDuplicate) {
|
||||
diagnostics.add(createDiagnosticForNode(
|
||||
node,
|
||||
Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity,
|
||||
lookupTable[id].specifierText,
|
||||
id
|
||||
));
|
||||
}
|
||||
}
|
||||
extendExportSymbols(symbols, nestedSymbols);
|
||||
}
|
||||
return symbols;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1519,9 +1594,9 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
|
||||
function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string {
|
||||
const writer = getSingleLineStringWriter();
|
||||
getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
|
||||
getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags, kind);
|
||||
const result = writer.string();
|
||||
releaseStringWriter(writer);
|
||||
|
||||
@@ -1873,7 +1948,7 @@ namespace ts {
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
|
||||
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
@@ -1885,7 +1960,7 @@ namespace ts {
|
||||
}
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
|
||||
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
@@ -1899,15 +1974,12 @@ namespace ts {
|
||||
writer.writeLine();
|
||||
writer.increaseIndent();
|
||||
for (const signature of resolved.callSignatures) {
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
for (const signature of resolved.constructSignatures) {
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, SignatureKind.Construct, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1948,7 +2020,7 @@ namespace ts {
|
||||
if (p.flags & SymbolFlags.Optional) {
|
||||
writePunctuation(writer, SyntaxKind.QuestionToken);
|
||||
}
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -2068,7 +2140,12 @@ namespace ts {
|
||||
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, symbolStack?: Symbol[]) {
|
||||
if (kind === SignatureKind.Construct) {
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
}
|
||||
|
||||
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
|
||||
// Instantiated signature, write type arguments instead
|
||||
// This is achieved by passing in the mapper separately
|
||||
@@ -2936,10 +3013,6 @@ namespace ts {
|
||||
return type.resolvedBaseConstructorType;
|
||||
}
|
||||
|
||||
function hasClassBaseType(type: InterfaceType): boolean {
|
||||
return !!forEach(getBaseTypes(type), t => !!(t.symbol.flags & SymbolFlags.Class));
|
||||
}
|
||||
|
||||
function getBaseTypes(type: InterfaceType): ObjectType[] {
|
||||
const isClass = type.symbol.flags & SymbolFlags.Class;
|
||||
const isInterface = type.symbol.flags & SymbolFlags.Interface;
|
||||
@@ -3373,11 +3446,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
|
||||
if (!hasClassBaseType(classType)) {
|
||||
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
|
||||
}
|
||||
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
|
||||
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
|
||||
if (baseSignatures.length === 0) {
|
||||
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
|
||||
}
|
||||
const baseTypeNode = getBaseTypeNodeOfClass(classType);
|
||||
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
|
||||
const typeArgCount = typeArguments ? typeArguments.length : 0;
|
||||
@@ -3595,7 +3668,7 @@ namespace ts {
|
||||
return <ResolvedType>type;
|
||||
}
|
||||
|
||||
// Return properties of an object type or an empty array for other types
|
||||
/** Return properties of an object type or an empty array for other types */
|
||||
function getPropertiesOfObjectType(type: Type): Symbol[] {
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
return resolveStructuredTypeMembers(<ObjectType>type).properties;
|
||||
@@ -3603,8 +3676,8 @@ namespace ts {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
// If the given type is an object type and that type has a property by the given name,
|
||||
// return the symbol for that property.Otherwise return undefined.
|
||||
/** If the given type is an object type and that type has a property by the given name,
|
||||
* return the symbol for that property. Otherwise return undefined. */
|
||||
function getPropertyOfObjectType(type: Type, name: string): Symbol {
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
@@ -5395,20 +5468,26 @@ namespace ts {
|
||||
|
||||
outer: for (const t of targetSignatures) {
|
||||
if (!t.hasStringLiterals || target.flags & TypeFlags.FromSignature) {
|
||||
let localErrors = reportErrors;
|
||||
const checkedAbstractAssignability = false;
|
||||
// Only elaborate errors from the first failure
|
||||
let shouldElaborateErrors = reportErrors;
|
||||
for (const s of sourceSignatures) {
|
||||
if (!s.hasStringLiterals || source.flags & TypeFlags.FromSignature) {
|
||||
const related = signatureRelatedTo(s, t, localErrors);
|
||||
const related = signatureRelatedTo(s, t, shouldElaborateErrors);
|
||||
if (related) {
|
||||
result &= related;
|
||||
errorInfo = saveErrorInfo;
|
||||
continue outer;
|
||||
}
|
||||
// Only report errors from the first failure
|
||||
localErrors = false;
|
||||
shouldElaborateErrors = false;
|
||||
}
|
||||
}
|
||||
// don't elaborate the primitive apparent types (like Number)
|
||||
// because the actual primitives will have already been reported.
|
||||
if (shouldElaborateErrors && !isPrimitiveApparentType(source)) {
|
||||
reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1,
|
||||
typeToString(source),
|
||||
signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
@@ -6038,14 +6117,25 @@ namespace ts {
|
||||
function inferFromTypes(source: Type, target: Type) {
|
||||
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
|
||||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
|
||||
// Source and target are both unions or both intersections. To improve the quality of
|
||||
// inferences we first reduce the types by removing constituents that are identically
|
||||
// matched by a constituent in the other type. For example, when inferring from
|
||||
// 'string | string[]' to 'string | T', we reduce the types to 'string[]' and 'T'.
|
||||
const reducedSource = reduceUnionOrIntersectionType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
|
||||
const reducedTarget = reduceUnionOrIntersectionType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
|
||||
source = reducedSource;
|
||||
target = reducedTarget;
|
||||
// Source and target are both unions or both intersections. First, find each
|
||||
// target constituent type that has an identically matching source constituent
|
||||
// type, and for each such target constituent type infer from the type to itself.
|
||||
// When inferring from a type to itself we effectively find all type parameter
|
||||
// occurrences within that type and infer themselves as their type arguments.
|
||||
let matchingTypes: Type[];
|
||||
for (const t of (<UnionOrIntersectionType>target).types) {
|
||||
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>source).types)) {
|
||||
(matchingTypes || (matchingTypes = [])).push(t);
|
||||
inferFromTypes(t, t);
|
||||
}
|
||||
}
|
||||
// Next, to improve the quality of inferences, reduce the source and target types by
|
||||
// removing the identically matched constituents. For example, when inferring from
|
||||
// 'string | string[]' to 'string | T' we reduce the types to 'string[]' and 'T'.
|
||||
if (matchingTypes) {
|
||||
source = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>source, matchingTypes);
|
||||
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>target, matchingTypes);
|
||||
}
|
||||
}
|
||||
if (target.flags & TypeFlags.TypeParameter) {
|
||||
// If target is a type parameter, make an inference, unless the source type contains
|
||||
@@ -6129,9 +6219,12 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
source = getApparentType(source);
|
||||
if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
|
||||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
|
||||
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
|
||||
if (source.flags & TypeFlags.ObjectType && (
|
||||
target.flags & TypeFlags.Reference && (<TypeReference>target).typeArguments ||
|
||||
target.flags & TypeFlags.Tuple ||
|
||||
target.flags & TypeFlags.Anonymous && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
|
||||
// If source is an object type, and target is a type reference with type arguments, a tuple type,
|
||||
// the type of a method, or a type literal, infer from members
|
||||
if (isInProcess(source, target)) {
|
||||
return;
|
||||
}
|
||||
@@ -6204,9 +6297,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function typeIdenticalToSomeType(source: Type, target: UnionOrIntersectionType): boolean {
|
||||
for (const t of target.types) {
|
||||
if (isTypeIdenticalTo(source, t)) {
|
||||
function typeIdenticalToSomeType(type: Type, types: Type[]): boolean {
|
||||
for (const t of types) {
|
||||
if (isTypeIdenticalTo(t, type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -6214,29 +6307,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the reduced form of the source type. This type is computed by by removing all source
|
||||
* constituents that have an identical match in the target type.
|
||||
* Return a new union or intersection type computed by removing a given set of types
|
||||
* from a given union or intersection type.
|
||||
*/
|
||||
function reduceUnionOrIntersectionType(source: UnionOrIntersectionType, target: UnionOrIntersectionType) {
|
||||
let sourceTypes = source.types;
|
||||
let sourceIndex = 0;
|
||||
let modified = false;
|
||||
while (sourceIndex < sourceTypes.length) {
|
||||
if (typeIdenticalToSomeType(sourceTypes[sourceIndex], target)) {
|
||||
if (!modified) {
|
||||
sourceTypes = sourceTypes.slice(0);
|
||||
modified = true;
|
||||
}
|
||||
sourceTypes.splice(sourceIndex, 1);
|
||||
}
|
||||
else {
|
||||
sourceIndex++;
|
||||
function removeTypesFromUnionOrIntersection(type: UnionOrIntersectionType, typesToRemove: Type[]) {
|
||||
const reducedTypes: Type[] = [];
|
||||
for (const t of type.types) {
|
||||
if (!typeIdenticalToSomeType(t, typesToRemove)) {
|
||||
reducedTypes.push(t);
|
||||
}
|
||||
}
|
||||
if (modified) {
|
||||
return source.flags & TypeFlags.Union ? getUnionType(sourceTypes, /*noSubtypeReduction*/ true) : getIntersectionType(sourceTypes);
|
||||
}
|
||||
return source;
|
||||
return type.flags & TypeFlags.Union ? getUnionType(reducedTypes, /*noSubtypeReduction*/ true) : getIntersectionType(reducedTypes);
|
||||
}
|
||||
|
||||
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
|
||||
@@ -7820,12 +7901,11 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
/// Returns the type JSX.IntrinsicElements. May return `unknownType` if that type is not present.
|
||||
function getJsxIntrinsicElementsType() {
|
||||
if (!jsxIntrinsicElementsType) {
|
||||
jsxIntrinsicElementsType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.IntrinsicElements) || unknownType;
|
||||
function getJsxType(name: string) {
|
||||
if (jsxTypes[name] === undefined) {
|
||||
return jsxTypes[name] = getExportedTypeFromNamespace(JsxNames.JSX, name) || unknownType;
|
||||
}
|
||||
return jsxIntrinsicElementsType;
|
||||
return jsxTypes[name];
|
||||
}
|
||||
|
||||
/// Given a JSX opening element or self-closing element, return the symbol of the property that the tag name points to if
|
||||
@@ -7848,7 +7928,7 @@ namespace ts {
|
||||
return links.resolvedSymbol;
|
||||
|
||||
function lookupIntrinsicTag(node: JsxOpeningLikeElement | JsxClosingElement): Symbol {
|
||||
const intrinsicElementsType = getJsxIntrinsicElementsType();
|
||||
const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements);
|
||||
if (intrinsicElementsType !== unknownType) {
|
||||
// Property case
|
||||
const intrinsicProp = getPropertyOfType(intrinsicElementsType, (<Identifier>node.tagName).text);
|
||||
@@ -7880,7 +7960,7 @@ namespace ts {
|
||||
|
||||
// Look up the value in the current scope
|
||||
if (valueSymbol && valueSymbol !== unknownSymbol) {
|
||||
links.jsxFlags |= JsxFlags.ClassElement;
|
||||
links.jsxFlags |= JsxFlags.ValueElement;
|
||||
if (valueSymbol.flags & SymbolFlags.Alias) {
|
||||
markAliasSymbolAsReferenced(valueSymbol);
|
||||
}
|
||||
@@ -7909,7 +7989,7 @@ namespace ts {
|
||||
function getJsxElementInstanceType(node: JsxOpeningLikeElement) {
|
||||
// There is no such thing as an instance type for a non-class element. This
|
||||
// line shouldn't be hit.
|
||||
Debug.assert(!!(getNodeLinks(node).jsxFlags & JsxFlags.ClassElement), "Should not call getJsxElementInstanceType on non-class Element");
|
||||
Debug.assert(!!(getNodeLinks(node).jsxFlags & JsxFlags.ValueElement), "Should not call getJsxElementInstanceType on non-class Element");
|
||||
|
||||
const classSymbol = getJsxElementTagSymbol(node);
|
||||
if (classSymbol === unknownSymbol) {
|
||||
@@ -7936,15 +8016,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const returnType = getUnionType(signatures.map(getReturnTypeOfSignature));
|
||||
|
||||
// Issue an error if this return type isn't assignable to JSX.ElementClass
|
||||
const elemClassType = getJsxGlobalElementClassType();
|
||||
if (elemClassType) {
|
||||
checkTypeRelatedTo(returnType, elemClassType, assignableRelation, node, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
|
||||
}
|
||||
|
||||
return returnType;
|
||||
return getUnionType(signatures.map(getReturnTypeOfSignature));
|
||||
}
|
||||
|
||||
/// e.g. "props" for React.d.ts,
|
||||
@@ -7993,9 +8065,31 @@ namespace ts {
|
||||
if (!links.resolvedJsxType) {
|
||||
const sym = getJsxElementTagSymbol(node);
|
||||
|
||||
if (links.jsxFlags & JsxFlags.ClassElement) {
|
||||
if (links.jsxFlags & JsxFlags.ValueElement) {
|
||||
// Get the element instance type (the result of newing or invoking this tag)
|
||||
const elemInstanceType = getJsxElementInstanceType(node);
|
||||
|
||||
// Is this is a stateless function component? See if its single signature is
|
||||
// assignable to the JSX Element Type
|
||||
const callSignature = getSingleCallSignature(getTypeOfSymbol(sym));
|
||||
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
|
||||
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
|
||||
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType) && (paramType.flags & TypeFlags.ObjectType)) {
|
||||
// Intersect in JSX.IntrinsicAttributes if it exists
|
||||
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
|
||||
if (intrinsicAttributes !== unknownType) {
|
||||
paramType = intersectTypes(intrinsicAttributes, paramType);
|
||||
}
|
||||
return paramType;
|
||||
}
|
||||
|
||||
// Issue an error if this return type isn't assignable to JSX.ElementClass
|
||||
const elemClassType = getJsxGlobalElementClassType();
|
||||
if (elemClassType) {
|
||||
checkTypeRelatedTo(elemInstanceType, elemClassType, assignableRelation, node, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements);
|
||||
}
|
||||
|
||||
|
||||
if (isTypeAny(elemInstanceType)) {
|
||||
return links.resolvedJsxType = elemInstanceType;
|
||||
}
|
||||
@@ -8017,14 +8111,36 @@ namespace ts {
|
||||
return links.resolvedJsxType = emptyObjectType;
|
||||
}
|
||||
else if (isTypeAny(attributesType) || (attributesType === unknownType)) {
|
||||
// Props is of type 'any' or unknown
|
||||
return links.resolvedJsxType = attributesType;
|
||||
}
|
||||
else if (!(attributesType.flags & TypeFlags.ObjectType)) {
|
||||
// Props is not an object type
|
||||
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_must_be_an_object_type, typeToString(attributesType));
|
||||
return links.resolvedJsxType = anyType;
|
||||
}
|
||||
else {
|
||||
return links.resolvedJsxType = attributesType;
|
||||
// Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
|
||||
let apparentAttributesType = attributesType;
|
||||
const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes);
|
||||
if (intrinsicClassAttribs !== unknownType) {
|
||||
const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol);
|
||||
if (typeParams) {
|
||||
if (typeParams.length === 1) {
|
||||
apparentAttributesType = intersectTypes(createTypeReference(<GenericType>intrinsicClassAttribs, [elemInstanceType]), apparentAttributesType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apparentAttributesType = intersectTypes(attributesType, intrinsicClassAttribs);
|
||||
}
|
||||
}
|
||||
|
||||
const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes);
|
||||
if (intrinsicAttribs !== unknownType) {
|
||||
apparentAttributesType = intersectTypes(intrinsicAttribs, apparentAttributesType);
|
||||
}
|
||||
|
||||
return links.resolvedJsxType = apparentAttributesType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8063,7 +8179,7 @@ namespace ts {
|
||||
|
||||
/// Returns all the properties of the Jsx.IntrinsicElements interface
|
||||
function getJsxIntrinsicTagNames(): Symbol[] {
|
||||
const intrinsics = getJsxIntrinsicElementsType();
|
||||
const intrinsics = getJsxType(JsxNames.IntrinsicElements);
|
||||
return intrinsics ? getPropertiesOfType(intrinsics) : emptyArray;
|
||||
}
|
||||
|
||||
@@ -9810,7 +9926,7 @@ namespace ts {
|
||||
return aggregatedTypes;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
*TypeScript Specification 1.0 (6.3) - July 2014
|
||||
* An explicitly typed function whose return type isn't the Void or the Any type
|
||||
* must have at least one return statement somewhere in its body.
|
||||
@@ -9823,31 +9939,39 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
|
||||
if (returnType && (returnType === voidType || isTypeAny(returnType))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
|
||||
if (!returnType && !compilerOptions.noImplicitReturns) {
|
||||
if (returnType === voidType || isTypeAny(returnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
|
||||
// also if HasImplicitReturnValue flags is not set this means that all codepaths in function body end with return of throw
|
||||
// also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw
|
||||
if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !(func.flags & NodeFlags.HasImplicitReturn)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
|
||||
if (compilerOptions.noImplicitReturns) {
|
||||
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This function does not conform to the specification.
|
||||
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
|
||||
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
|
||||
|
||||
if (returnType && !hasExplicitReturn) {
|
||||
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
|
||||
// this function does not conform to the specification.
|
||||
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
|
||||
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
|
||||
}
|
||||
else if (compilerOptions.noImplicitReturns) {
|
||||
if (!returnType) {
|
||||
// If return type annotation is omitted check if function has any explicit return statements.
|
||||
// If it does not have any - its inferred return type is void - don't do any checks.
|
||||
// Otherwise get inferred return type from function body and report error only if it is not void / anytype
|
||||
const inferredReturnType = hasExplicitReturn
|
||||
? getReturnTypeOfSignature(getSignatureFromDeclaration(func))
|
||||
: voidType;
|
||||
|
||||
if (inferredReturnType === voidType || isTypeAny(inferredReturnType)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
}
|
||||
}
|
||||
|
||||
function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type {
|
||||
@@ -11400,7 +11524,9 @@ namespace ts {
|
||||
seen = c === node;
|
||||
}
|
||||
});
|
||||
if (subsequentNode) {
|
||||
// We may be here because of some extra junk between overloads that could not be parsed into a valid node.
|
||||
// In this case the subsequent node is not really consecutive (.pos !== node.end), and we must ignore it here.
|
||||
if (subsequentNode && subsequentNode.pos === node.end) {
|
||||
if (subsequentNode.kind === node.kind) {
|
||||
const errorNode: Node = (<FunctionLikeDeclaration>subsequentNode).name || subsequentNode;
|
||||
// TODO(jfreeman): These are methods, so handle computed name case
|
||||
@@ -11873,6 +11999,9 @@ namespace ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
// If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
|
||||
checkReturnTypeAnnotationAsExpression(node);
|
||||
|
||||
// Validate the promise constructor type.
|
||||
const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
|
||||
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
|
||||
@@ -11881,11 +12010,11 @@ namespace ts {
|
||||
|
||||
// Verify there is no local declaration that could collide with the promise constructor.
|
||||
const promiseName = getEntityNameFromTypeNode(node.type);
|
||||
const root = getFirstIdentifier(promiseName);
|
||||
const rootSymbol = getSymbol(node.locals, root.text, SymbolFlags.Value);
|
||||
const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName);
|
||||
const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value);
|
||||
if (rootSymbol) {
|
||||
error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
|
||||
root.text,
|
||||
promiseNameOrNamespaceRoot.text,
|
||||
getFullyQualifiedName(promiseConstructor));
|
||||
return unknownType;
|
||||
}
|
||||
@@ -11969,24 +12098,12 @@ namespace ts {
|
||||
* Checks the type annotation of an accessor declaration or property declaration as
|
||||
* an expression if it is a type reference to a type with a value declaration.
|
||||
*/
|
||||
function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.Parameter:
|
||||
checkTypeNodeAsExpression((<ParameterDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
checkTypeNodeAsExpression((<MethodDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.GetAccessor:
|
||||
checkTypeNodeAsExpression((<AccessorDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.SetAccessor:
|
||||
checkTypeNodeAsExpression(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
|
||||
break;
|
||||
}
|
||||
function checkTypeAnnotationAsExpression(node: VariableLikeDeclaration) {
|
||||
checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
|
||||
}
|
||||
|
||||
function checkReturnTypeAnnotationAsExpression(node: FunctionLikeDeclaration) {
|
||||
checkTypeNodeAsExpression(node.type);
|
||||
}
|
||||
|
||||
/** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
|
||||
@@ -12024,11 +12141,12 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
|
||||
// fall-through
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
|
||||
checkReturnTypeAnnotationAsExpression(<FunctionLikeDeclaration>node);
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
|
||||
@@ -12078,8 +12196,8 @@ namespace ts {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
const localSymbol = node.localSymbol || symbol;
|
||||
|
||||
// Since the javascript won't do semantic analysis like typescript,
|
||||
// if the javascript file comes before the typescript file and both contain same name functions,
|
||||
// Since the javascript won't do semantic analysis like typescript,
|
||||
// if the javascript file comes before the typescript file and both contain same name functions,
|
||||
// checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function.
|
||||
const firstDeclaration = forEach(localSymbol.declarations,
|
||||
// Get first non javascript function declaration
|
||||
@@ -14056,8 +14174,29 @@ namespace ts {
|
||||
const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
|
||||
error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
|
||||
}
|
||||
// Checks for export * conflicts
|
||||
const exports = getExportsOfModule(moduleSymbol);
|
||||
for (const id in exports) {
|
||||
if (id === "__export") {
|
||||
continue;
|
||||
}
|
||||
const { declarations, flags } = exports[id];
|
||||
// ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. (TS Exceptions: namespaces, function overloads, enums, and interfaces)
|
||||
if (!(flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) && declarations.length > 1) {
|
||||
const exportedDeclarations: Declaration[] = filter(declarations, isNotOverload);
|
||||
if (exportedDeclarations.length > 1) {
|
||||
for (const declaration of exportedDeclarations) {
|
||||
diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
links.exportsChecked = true;
|
||||
}
|
||||
|
||||
function isNotOverload(declaration: Declaration): boolean {
|
||||
return declaration.kind !== SyntaxKind.FunctionDeclaration || !!(declaration as FunctionDeclaration).body;
|
||||
}
|
||||
}
|
||||
|
||||
function checkTypePredicate(node: TypePredicateNode) {
|
||||
@@ -14329,6 +14468,7 @@ namespace ts {
|
||||
emitExtends = false;
|
||||
emitDecorate = false;
|
||||
emitParam = false;
|
||||
emitAwaiter = false;
|
||||
potentialThisCollisions.length = 0;
|
||||
|
||||
forEach(node.statements, checkSourceElement);
|
||||
@@ -15191,10 +15331,12 @@ namespace ts {
|
||||
}
|
||||
});
|
||||
|
||||
// Setup global builtins
|
||||
addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
|
||||
|
||||
getSymbolLinks(undefinedSymbol).type = undefinedType;
|
||||
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
|
||||
getSymbolLinks(unknownSymbol).type = unknownType;
|
||||
globals[undefinedSymbol.name] = undefinedSymbol;
|
||||
|
||||
// Initialize special types
|
||||
globalArrayType = <GenericType>getGlobalType("Array", /*arity*/ 1);
|
||||
@@ -15888,13 +16030,27 @@ namespace ts {
|
||||
if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
|
||||
const variableList = <VariableDeclarationList>forInOrOfStatement.initializer;
|
||||
if (!checkGrammarVariableDeclarationList(variableList)) {
|
||||
if (variableList.declarations.length > 1) {
|
||||
const declarations = variableList.declarations;
|
||||
|
||||
// declarations.length can be zero if there is an error in variable declaration in for-of or for-in
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements for details
|
||||
// For example:
|
||||
// var let = 10;
|
||||
// for (let of [1,2,3]) {} // this is invalid ES6 syntax
|
||||
// for (let in [1,2,3]) {} // this is invalid ES6 syntax
|
||||
// We will then want to skip on grammar checking on variableList declaration
|
||||
if (!declarations.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (declarations.length > 1) {
|
||||
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
|
||||
? Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
|
||||
: Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
|
||||
return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
|
||||
}
|
||||
const firstDeclaration = variableList.declarations[0];
|
||||
const firstDeclaration = declarations[0];
|
||||
|
||||
if (firstDeclaration.initializer) {
|
||||
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
|
||||
? Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
|
||||
@@ -16093,7 +16249,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const checkLetConstNames = languageVersion >= ScriptTarget.ES6 && (isLet(node) || isConst(node));
|
||||
const checkLetConstNames = (isLet(node) || isConst(node));
|
||||
|
||||
// 1. LexicalDeclaration : LetOrConst BindingList ;
|
||||
// It is a Syntax Error if the BoundNames of BindingList contains "let".
|
||||
@@ -16107,7 +16263,7 @@ namespace ts {
|
||||
|
||||
function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
if ((<Identifier>name).text === "let") {
|
||||
if ((<Identifier>name).originalKeywordKind === SyntaxKind.LetKeyword) {
|
||||
return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
|
||||
}
|
||||
}
|
||||
@@ -16235,11 +16391,17 @@ namespace ts {
|
||||
if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol)) {
|
||||
return true;
|
||||
}
|
||||
if (node.initializer) {
|
||||
return grammarErrorOnNode(node.initializer, Diagnostics.An_interface_property_cannot_have_an_initializer);
|
||||
}
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.TypeLiteral) {
|
||||
if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol)) {
|
||||
return true;
|
||||
}
|
||||
if (node.initializer) {
|
||||
return grammarErrorOnNode(node.initializer, Diagnostics.A_type_literal_property_cannot_have_an_initializer);
|
||||
}
|
||||
}
|
||||
|
||||
if (isInAmbientContext(node) && node.initializer) {
|
||||
|
||||
@@ -356,6 +356,33 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the properties of a map.
|
||||
*
|
||||
* @param map The map to reduce
|
||||
* @param callback An aggregation function that is called for each entry in the map
|
||||
* @param initial The initial value for the reduction.
|
||||
*/
|
||||
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
if (map) {
|
||||
for (const key in map) {
|
||||
if (hasProperty(map, key)) {
|
||||
result = callback(result, map[key], String(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a value is an array.
|
||||
*/
|
||||
export function isArray(value: any): value is any[] {
|
||||
return Array.isArray ? Array.isArray(value) : value instanceof Array;
|
||||
}
|
||||
|
||||
export function memoize<T>(callback: () => T): () => T {
|
||||
let value: T;
|
||||
return () => {
|
||||
|
||||
@@ -1675,7 +1675,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) {
|
||||
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit);
|
||||
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath);
|
||||
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
|
||||
if (!emitSkipped) {
|
||||
const declarationOutput = emitDeclarationResult.referencePathsOutput
|
||||
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
|
||||
|
||||
@@ -783,6 +783,14 @@
|
||||
"category": "Error",
|
||||
"code": 1245
|
||||
},
|
||||
"An interface property cannot have an initializer.": {
|
||||
"category": "Error",
|
||||
"code": 1246
|
||||
},
|
||||
"A type literal property cannot have an initializer.": {
|
||||
"category": "Error",
|
||||
"code": 1247
|
||||
},
|
||||
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
@@ -836,6 +844,10 @@
|
||||
"category": "Error",
|
||||
"code": 2307
|
||||
},
|
||||
"Module {0} has already exported a member named '{1}'. Consider explicitly re-exporting to resolve the ambiguity.": {
|
||||
"category": "Error",
|
||||
"code": 2308
|
||||
},
|
||||
"An export assignment cannot be used in a module with other exported elements.": {
|
||||
"category": "Error",
|
||||
"code": 2309
|
||||
@@ -892,6 +904,10 @@
|
||||
"category": "Error",
|
||||
"code": 2322
|
||||
},
|
||||
"Cannot redeclare exported variable '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2323
|
||||
},
|
||||
"Property '{0}' is missing in type '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2324
|
||||
@@ -1172,6 +1188,10 @@
|
||||
"category": "Error",
|
||||
"code": 2396
|
||||
},
|
||||
"Declaration name conflicts with built-in global identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2397
|
||||
},
|
||||
"Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.": {
|
||||
"category": "Error",
|
||||
"code": 2399
|
||||
@@ -1724,6 +1744,10 @@
|
||||
"category": "Error",
|
||||
"code": 2657
|
||||
},
|
||||
"Type '{0}' provides no match for the signature '{1}'": {
|
||||
"category": "Error",
|
||||
"code": 2658
|
||||
},
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
@@ -2430,7 +2454,7 @@
|
||||
"Not all code paths return a value.": {
|
||||
"category": "Error",
|
||||
"code": 7030
|
||||
},
|
||||
},
|
||||
"You cannot rename this element.": {
|
||||
"category": "Error",
|
||||
"code": 8000
|
||||
|
||||
+139
-529
File diff suppressed because it is too large
Load Diff
+24
-13
@@ -2259,6 +2259,14 @@ namespace ts {
|
||||
property.name = name;
|
||||
property.questionToken = questionToken;
|
||||
property.type = parseTypeAnnotation();
|
||||
|
||||
if (token === SyntaxKind.EqualsToken) {
|
||||
// Although type literal properties cannot not have initializers, we attempt
|
||||
// to parse an initializer so we can report in the checker that an interface
|
||||
// property or type literal property cannot have an initializer.
|
||||
property.initializer = parseNonParameterInitializer();
|
||||
}
|
||||
|
||||
parseTypeMemberSemicolon();
|
||||
return finishNode(property);
|
||||
}
|
||||
@@ -4902,7 +4910,7 @@ namespace ts {
|
||||
|
||||
if (!decorators) {
|
||||
decorators = <NodeArray<Decorator>>[];
|
||||
decorators.pos = scanner.getStartPos();
|
||||
decorators.pos = decoratorStart;
|
||||
}
|
||||
|
||||
const decorator = <Decorator>createNode(SyntaxKind.Decorator, decoratorStart);
|
||||
@@ -5302,16 +5310,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parseModuleSpecifier(): Expression {
|
||||
// We allow arbitrary expressions here, even though the grammar only allows string
|
||||
// literals. We check to ensure that it is only a string literal later in the grammar
|
||||
// walker.
|
||||
const result = parseExpression();
|
||||
// Ensure the string being required is in our 'identifier' table. This will ensure
|
||||
// that features like 'find refs' will look inside this file when search for its name.
|
||||
if (result.kind === SyntaxKind.StringLiteral) {
|
||||
if (token === SyntaxKind.StringLiteral) {
|
||||
const result = parseLiteralNode();
|
||||
internIdentifier((<LiteralExpression>result).text);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
// We allow arbitrary expressions here, even though the grammar only allows string
|
||||
// literals. We check to ensure that it is only a string literal later in the grammar
|
||||
// check pass.
|
||||
return parseExpression();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseNamespaceImport(): NamespaceImport {
|
||||
@@ -5428,11 +5437,13 @@ namespace ts {
|
||||
// reference comment.
|
||||
while (true) {
|
||||
const kind = triviaScanner.scan();
|
||||
if (kind === SyntaxKind.WhitespaceTrivia || kind === SyntaxKind.NewLineTrivia || kind === SyntaxKind.MultiLineCommentTrivia) {
|
||||
continue;
|
||||
}
|
||||
if (kind !== SyntaxKind.SingleLineCommentTrivia) {
|
||||
break;
|
||||
if (isTrivia(kind)) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
|
||||
|
||||
@@ -661,19 +661,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
// For JavaScript files, we don't want to report the normal typescript semantic errors.
|
||||
// Instead, we just report errors for using TypeScript-only constructs from within a
|
||||
// JavaScript file.
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
return getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken);
|
||||
}
|
||||
|
||||
return runWithCancellationToken(() => {
|
||||
const typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
|
||||
Debug.assert(!!sourceFile.bindDiagnostics);
|
||||
const bindDiagnostics = sourceFile.bindDiagnostics;
|
||||
const checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken);
|
||||
// For JavaScript files, we don't want to report the normal typescript semantic errors.
|
||||
// Instead, we just report errors for using TypeScript-only constructs from within a
|
||||
// JavaScript file.
|
||||
const checkDiagnostics = isSourceFileJavaScript(sourceFile) ?
|
||||
getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) :
|
||||
typeChecker.getDiagnostics(sourceFile, cancellationToken);
|
||||
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
|
||||
@@ -1079,6 +1077,8 @@ namespace ts {
|
||||
const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /*isDefaultLib*/ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
|
||||
|
||||
if (importedFile && resolution.isExternalLibraryImport) {
|
||||
// Since currently irrespective of allowJs, we only look for supportedTypeScript extension external module files,
|
||||
// this check is ok. Otherwise this would be never true for javascript file
|
||||
if (!isExternalModule(importedFile)) {
|
||||
const start = getTokenPosOfNode(file.imports[i], file);
|
||||
fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_file_0_is_not_a_module_Please_contact_the_package_author_to_update_the_package_definition, importedFile.fileName));
|
||||
|
||||
@@ -425,6 +425,12 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
|
||||
// Using ! with a greater than test is a fast way of testing the following conditions:
|
||||
// pos === undefined || pos === null || isNaN(pos) || pos < 0;
|
||||
if (!(pos >= 0)) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
// Keep in sync with couldStartTrivia
|
||||
while (true) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
@@ -567,12 +573,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract comments from text prefixing the token closest following `pos`.
|
||||
* Extract comments from text prefixing the token closest following `pos`.
|
||||
* The return value is an array containing a TextRange for each comment.
|
||||
* Single-line comment ranges include the beginning '//' characters but not the ending line break.
|
||||
* Multi - line comment ranges include the beginning '/* and ending '<asterisk>/' characters.
|
||||
* The return value is undefined if no comments were found.
|
||||
* @param trailing
|
||||
* @param trailing
|
||||
* If false, whitespace is skipped until the first line break and comments between that location
|
||||
* and the next token are returned.
|
||||
* If true, comments occurring between the given position and the next line break are returned.
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/// <reference path="checker.ts"/>
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export interface SourceMapWriter {
|
||||
getSourceMapData(): SourceMapData;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitPos(pos: number): void;
|
||||
emitStart(range: TextRange): void;
|
||||
emitEnd(range: TextRange): void;
|
||||
getText(): string;
|
||||
getSourceMappingURL(): string;
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
const nop = <(...args: any[]) => any>Function.prototype;
|
||||
let nullSourceMapWriter: SourceMapWriter;
|
||||
|
||||
export function getNullSourceMapWriter(): SourceMapWriter {
|
||||
if (nullSourceMapWriter === undefined) {
|
||||
nullSourceMapWriter = {
|
||||
getSourceMapData(): SourceMapData { return undefined; },
|
||||
setSourceFile(sourceFile: SourceFile): void { },
|
||||
emitStart(range: TextRange): void { },
|
||||
emitEnd(range: TextRange): void { },
|
||||
emitPos(pos: number): void { },
|
||||
getText(): string { return undefined; },
|
||||
getSourceMappingURL(): string { return undefined; },
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
|
||||
reset(): void { },
|
||||
};
|
||||
}
|
||||
|
||||
return nullSourceMapWriter;
|
||||
}
|
||||
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
let currentSourceFile: SourceFile;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
let sourceMapSourceIndex: number;
|
||||
|
||||
// Last recorded and encoded spans
|
||||
let lastRecordedSourceMapSpan: SourceMapSpan;
|
||||
let lastEncodedSourceMapSpan: SourceMapSpan;
|
||||
let lastEncodedNameIndex: number;
|
||||
|
||||
// Source map data
|
||||
let sourceMapData: SourceMapData;
|
||||
|
||||
return {
|
||||
getSourceMapData: () => sourceMapData,
|
||||
setSourceFile,
|
||||
emitPos,
|
||||
emitStart,
|
||||
emitEnd,
|
||||
getText,
|
||||
getSourceMappingURL,
|
||||
initialize,
|
||||
reset,
|
||||
};
|
||||
|
||||
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
if (sourceMapData) {
|
||||
reset();
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
sourceMapSourceIndex = -1;
|
||||
|
||||
// Last recorded and encoded spans
|
||||
lastRecordedSourceMapSpan = undefined;
|
||||
lastEncodedSourceMapSpan = {
|
||||
emittedLine: 1,
|
||||
emittedColumn: 1,
|
||||
sourceLine: 1,
|
||||
sourceColumn: 1,
|
||||
sourceIndex: 0
|
||||
};
|
||||
lastEncodedNameIndex = 0;
|
||||
|
||||
// Initialize source map data
|
||||
sourceMapData = {
|
||||
sourceMapFilePath: sourceMapFilePath,
|
||||
jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined,
|
||||
sourceMapFile: getBaseFileName(normalizeSlashes(filePath)),
|
||||
sourceMapSourceRoot: compilerOptions.sourceRoot || "",
|
||||
sourceMapSources: [],
|
||||
inputSourceFileNames: [],
|
||||
sourceMapNames: [],
|
||||
sourceMapMappings: "",
|
||||
sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined,
|
||||
sourceMapDecodedMappings: []
|
||||
};
|
||||
|
||||
// Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
|
||||
// relative paths of the sources list in the sourcemap
|
||||
sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
|
||||
if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
|
||||
sourceMapData.sourceMapSourceRoot += directorySeparator;
|
||||
}
|
||||
|
||||
if (compilerOptions.mapRoot) {
|
||||
sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
|
||||
if (!isBundledEmit) { // emitting single module file
|
||||
Debug.assert(sourceFiles.length === 1);
|
||||
// For modules or multiple emit files the mapRoot will have directory structure like the sources
|
||||
// So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
|
||||
sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir));
|
||||
}
|
||||
|
||||
if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
|
||||
// The relative paths are relative to the common directory
|
||||
sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
|
||||
sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
|
||||
getDirectoryPath(normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath
|
||||
combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
}
|
||||
else {
|
||||
sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sourceMapDir = getDirectoryPath(normalizePath(filePath));
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
currentSourceFile = undefined;
|
||||
sourceMapDir = undefined;
|
||||
sourceMapSourceIndex = undefined;
|
||||
lastRecordedSourceMapSpan = undefined;
|
||||
lastEncodedSourceMapSpan = undefined;
|
||||
lastEncodedNameIndex = undefined;
|
||||
sourceMapData = undefined;
|
||||
}
|
||||
|
||||
// Encoding for sourcemap span
|
||||
function encodeLastRecordedSourceMapSpan() {
|
||||
if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
|
||||
return;
|
||||
}
|
||||
|
||||
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
|
||||
// Line/Comma delimiters
|
||||
if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
|
||||
// Emit comma to separate the entry
|
||||
if (sourceMapData.sourceMapMappings) {
|
||||
sourceMapData.sourceMapMappings += ",";
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Emit line delimiters
|
||||
for (let encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
|
||||
sourceMapData.sourceMapMappings += ";";
|
||||
}
|
||||
prevEncodedEmittedColumn = 1;
|
||||
}
|
||||
|
||||
// 1. Relative Column 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
|
||||
|
||||
// 2. Relative sourceIndex
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
|
||||
|
||||
// 3. Relative sourceLine 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
|
||||
|
||||
// 4. Relative sourceColumn 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
|
||||
|
||||
// 5. Relative namePosition 0 based
|
||||
if (lastRecordedSourceMapSpan.nameIndex >= 0) {
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
|
||||
lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
|
||||
}
|
||||
|
||||
lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
|
||||
sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
|
||||
}
|
||||
|
||||
function emitPos(pos: number) {
|
||||
if (pos === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
|
||||
// Convert the location to be one-based.
|
||||
sourceLinePos.line++;
|
||||
sourceLinePos.character++;
|
||||
|
||||
const emittedLine = writer.getLine();
|
||||
const emittedColumn = writer.getColumn();
|
||||
|
||||
// If this location wasn't recorded or the location in source is going backwards, record the span
|
||||
if (!lastRecordedSourceMapSpan ||
|
||||
lastRecordedSourceMapSpan.emittedLine !== emittedLine ||
|
||||
lastRecordedSourceMapSpan.emittedColumn !== emittedColumn ||
|
||||
(lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
|
||||
(lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
|
||||
(lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
|
||||
|
||||
// Encode the last recordedSpan before assigning new
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
// New span
|
||||
lastRecordedSourceMapSpan = {
|
||||
emittedLine: emittedLine,
|
||||
emittedColumn: emittedColumn,
|
||||
sourceLine: sourceLinePos.line,
|
||||
sourceColumn: sourceLinePos.character,
|
||||
sourceIndex: sourceMapSourceIndex
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Take the new pos instead since there is no change in emittedLine and column since last location
|
||||
lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
|
||||
lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
|
||||
lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
|
||||
}
|
||||
}
|
||||
|
||||
function emitStart(range: TextRange) {
|
||||
const rangeHasDecorators = !!(range as Node).decorators;
|
||||
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1);
|
||||
}
|
||||
|
||||
function emitEnd(range: TextRange) {
|
||||
emitPos(range.end);
|
||||
}
|
||||
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
currentSourceFile = sourceFile;
|
||||
|
||||
// Add the file to tsFilePaths
|
||||
// If sourceroot option: Use the relative path corresponding to the common directory path
|
||||
// otherwise source locations relative to map file location
|
||||
const sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
|
||||
|
||||
const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
|
||||
currentSourceFile.fileName,
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
|
||||
sourceMapSourceIndex = indexOf(sourceMapData.sourceMapSources, source);
|
||||
if (sourceMapSourceIndex === -1) {
|
||||
sourceMapSourceIndex = sourceMapData.sourceMapSources.length;
|
||||
sourceMapData.sourceMapSources.push(source);
|
||||
|
||||
// The one that can be used from program to get the actual source file
|
||||
sourceMapData.inputSourceFileNames.push(sourceFile.fileName);
|
||||
|
||||
if (compilerOptions.inlineSources) {
|
||||
sourceMapData.sourceMapSourcesContent.push(sourceFile.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getText() {
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
return stringify({
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sourceRoot: sourceMapData.sourceMapSourceRoot,
|
||||
sources: sourceMapData.sourceMapSources,
|
||||
names: sourceMapData.sourceMapNames,
|
||||
mappings: sourceMapData.sourceMapMappings,
|
||||
sourcesContent: sourceMapData.sourceMapSourcesContent,
|
||||
});
|
||||
}
|
||||
|
||||
function getSourceMappingURL() {
|
||||
if (compilerOptions.inlineSourceMap) {
|
||||
// Encode the sourceMap into the sourceMap url
|
||||
const base64SourceMapText = convertToBase64(getText());
|
||||
return sourceMapData.jsSourceMappingURL = `data:application/json;base64,${base64SourceMapText}`;
|
||||
}
|
||||
else {
|
||||
return sourceMapData.jsSourceMappingURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
function base64FormatEncode(inValue: number) {
|
||||
if (inValue < 64) {
|
||||
return base64Chars.charAt(inValue);
|
||||
}
|
||||
|
||||
throw TypeError(inValue + ": not a 64 based value");
|
||||
}
|
||||
|
||||
function base64VLQFormatEncode(inValue: number) {
|
||||
// Add a new least significant bit that has the sign of the value.
|
||||
// if negative number the least significant bit that gets added to the number has value 1
|
||||
// else least significant bit value that gets added is 0
|
||||
// eg. -1 changes to binary : 01 [1] => 3
|
||||
// +1 changes to binary : 01 [0] => 2
|
||||
if (inValue < 0) {
|
||||
inValue = ((-inValue) << 1) + 1;
|
||||
}
|
||||
else {
|
||||
inValue = inValue << 1;
|
||||
}
|
||||
|
||||
// Encode 5 bits at a time starting from least significant bits
|
||||
let encodedStr = "";
|
||||
do {
|
||||
let currentDigit = inValue & 31; // 11111
|
||||
inValue = inValue >> 5;
|
||||
if (inValue > 0) {
|
||||
// There are still more digits to decode, set the msb (6th bit)
|
||||
currentDigit = currentDigit | 32;
|
||||
}
|
||||
encodedStr = encodedStr + base64FormatEncode(currentDigit);
|
||||
} while (inValue > 0);
|
||||
|
||||
return encodedStr;
|
||||
}
|
||||
}
|
||||
+54
-2
@@ -47,6 +47,21 @@ namespace ts {
|
||||
constructor(o: any);
|
||||
}
|
||||
|
||||
declare var ChakraHost: {
|
||||
args: string[];
|
||||
currentDirectory: string;
|
||||
executingFile: string;
|
||||
echo(s: string): void;
|
||||
quit(exitCode?: number): void;
|
||||
fileExists(path: string): boolean;
|
||||
directoryExists(path: string): boolean;
|
||||
createDirectory(path: string): void;
|
||||
resolvePath(path: string): string;
|
||||
readFile(path: string): string;
|
||||
writeFile(path: string, contents: string): void;
|
||||
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
|
||||
};
|
||||
|
||||
export var sys: System = (function () {
|
||||
|
||||
function getWScriptSystem(): System {
|
||||
@@ -194,6 +209,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getNodeSystem(): System {
|
||||
const _fs = require("fs");
|
||||
const _path = require("path");
|
||||
@@ -281,7 +297,7 @@ namespace ts {
|
||||
// REVIEW: for now this implementation uses polling.
|
||||
// The advantage of polling is that it works reliably
|
||||
// on all os and with network mounted files.
|
||||
// For 90 referenced files, the average time to detect
|
||||
// For 90 referenced files, the average time to detect
|
||||
// changes is 2*msInterval (by default 5 seconds).
|
||||
// The overhead of this is .04 percent (1/2500) with
|
||||
// average pause of < 1 millisecond (and max
|
||||
@@ -406,7 +422,7 @@ namespace ts {
|
||||
};
|
||||
},
|
||||
watchDirectory: (path, callback, recursive) => {
|
||||
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
|
||||
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
|
||||
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
|
||||
return _fs.watch(
|
||||
path,
|
||||
@@ -454,6 +470,37 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getChakraSystem(): System {
|
||||
|
||||
return {
|
||||
newLine: "\r\n",
|
||||
args: ChakraHost.args,
|
||||
useCaseSensitiveFileNames: false,
|
||||
write: ChakraHost.echo,
|
||||
readFile(path: string, encoding?: string) {
|
||||
// encoding is automatically handled by the implementation in ChakraHost
|
||||
return ChakraHost.readFile(path);
|
||||
},
|
||||
writeFile(path: string, data: string, writeByteOrderMark?: boolean) {
|
||||
// If a BOM is required, emit one
|
||||
if (writeByteOrderMark) {
|
||||
data = "\uFEFF" + data;
|
||||
}
|
||||
|
||||
ChakraHost.writeFile(path, data);
|
||||
},
|
||||
resolvePath: ChakraHost.resolvePath,
|
||||
fileExists: ChakraHost.fileExists,
|
||||
directoryExists: ChakraHost.directoryExists,
|
||||
createDirectory: ChakraHost.createDirectory,
|
||||
getExecutingFilePath: () => ChakraHost.executingFile,
|
||||
getCurrentDirectory: () => ChakraHost.currentDirectory,
|
||||
readDirectory: ChakraHost.readDirectory,
|
||||
exit: ChakraHost.quit,
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
|
||||
return getWScriptSystem();
|
||||
}
|
||||
@@ -462,8 +509,13 @@ namespace ts {
|
||||
// process.browser check excludes webpack and browserify
|
||||
return getNodeSystem();
|
||||
}
|
||||
else if (typeof ChakraHost !== "undefined") {
|
||||
return getChakraSystem();
|
||||
}
|
||||
else {
|
||||
return undefined; // Unsupported host
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -439,12 +439,16 @@ namespace ts {
|
||||
|
||||
export const enum JsxFlags {
|
||||
None = 0,
|
||||
/** An element from a named property of the JSX.IntrinsicElements interface */
|
||||
IntrinsicNamedElement = 1 << 0,
|
||||
/** An element inferred from the string index signature of the JSX.IntrinsicElements interface */
|
||||
IntrinsicIndexedElement = 1 << 1,
|
||||
ClassElement = 1 << 2,
|
||||
UnknownElement = 1 << 3,
|
||||
/** An element backed by a class, class-like, or function value */
|
||||
ValueElement = 1 << 2,
|
||||
/** Element resolution failed */
|
||||
UnknownElement = 1 << 4,
|
||||
|
||||
IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement
|
||||
IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement,
|
||||
}
|
||||
|
||||
|
||||
@@ -587,6 +591,7 @@ namespace ts {
|
||||
name: PropertyName; // Declared property name
|
||||
questionToken?: Node; // Present on optional property
|
||||
type?: TypeNode; // Optional type annotation
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.PropertyDeclaration)
|
||||
@@ -1752,7 +1757,7 @@ namespace ts {
|
||||
export interface SymbolDisplayBuilder {
|
||||
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
|
||||
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void;
|
||||
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
|
||||
|
||||
+53
-19
@@ -906,23 +906,6 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function childIsDecorated(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function nodeOrChildIsDecorated(node: Node): boolean {
|
||||
return nodeIsDecorated(node) || childIsDecorated(node);
|
||||
}
|
||||
|
||||
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
|
||||
return node.kind === SyntaxKind.PropertyAccessExpression;
|
||||
}
|
||||
@@ -1906,8 +1889,10 @@ namespace ts {
|
||||
* Resolves a local path to a path which is absolute to the base of the emit
|
||||
*/
|
||||
export function getExternalModuleNameFromPath(host: EmitHost, fileName: string): string {
|
||||
const dir = toPath(host.getCommonSourceDirectory(), host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
|
||||
const relativePath = getRelativePathToDirectoryOrUrl(dir, fileName, dir, f => host.getCanonicalFileName(f), /*isAbsolutePathAnUrl*/ false);
|
||||
const getCanonicalFileName = (f: string) => host.getCanonicalFileName(f);
|
||||
const dir = toPath(host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
|
||||
const filePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
|
||||
const relativePath = getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
|
||||
return removeFileExtension(relativePath);
|
||||
}
|
||||
|
||||
@@ -2411,6 +2396,55 @@ namespace ts {
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an object graph into a JSON string. This is intended only for use on an acyclic graph
|
||||
* as the fallback implementation does not check for circular references by default.
|
||||
*/
|
||||
export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify
|
||||
? JSON.stringify
|
||||
: stringifyFallback;
|
||||
|
||||
/**
|
||||
* Serialize an object graph into a JSON string.
|
||||
*/
|
||||
function stringifyFallback(value: any): string {
|
||||
// JSON.stringify returns `undefined` here, instead of the string "undefined".
|
||||
return value === undefined ? undefined : stringifyValue(value);
|
||||
}
|
||||
|
||||
function stringifyValue(value: any): string {
|
||||
return typeof value === "string" ? `"${escapeString(value)}"`
|
||||
: typeof value === "number" ? isFinite(value) ? String(value) : "null"
|
||||
: typeof value === "boolean" ? value ? "true" : "false"
|
||||
: typeof value === "object" && value ? isArray(value) ? cycleCheck(stringifyArray, value) : cycleCheck(stringifyObject, value)
|
||||
: /*fallback*/ "null";
|
||||
}
|
||||
|
||||
function cycleCheck(cb: (value: any) => string, value: any) {
|
||||
Debug.assert(!value.hasOwnProperty("__cycle"), "Converting circular structure to JSON");
|
||||
value.__cycle = true;
|
||||
const result = cb(value);
|
||||
delete value.__cycle;
|
||||
return result;
|
||||
}
|
||||
|
||||
function stringifyArray(value: any) {
|
||||
return `[${reduceLeft(value, stringifyElement, "")}]`;
|
||||
}
|
||||
|
||||
function stringifyElement(memo: string, value: any) {
|
||||
return (memo ? memo + "," : memo) + stringifyValue(value);
|
||||
}
|
||||
|
||||
function stringifyObject(value: any) {
|
||||
return `{${reduceProperties(value, stringifyProperty, "")}}`;
|
||||
}
|
||||
|
||||
function stringifyProperty(memo: string, value: any, key: string) {
|
||||
return value === undefined || typeof value === "function" || key === "__cycle" ? memo
|
||||
: (memo ? memo + "," : memo) + `"${escapeString(key)}":${stringifyValue(value)}`;
|
||||
}
|
||||
|
||||
const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
/**
|
||||
|
||||
@@ -142,7 +142,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
|
||||
it("Correct JS output for " + fileName, () => {
|
||||
if (hasNonDtsFiles && this.emit) {
|
||||
if (result.files.length === 0 && result.errors.length === 0) {
|
||||
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
|
||||
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
|
||||
}
|
||||
|
||||
|
||||
+12
-4
@@ -908,6 +908,7 @@ namespace Harness {
|
||||
useCaseSensitiveFileNames?: boolean;
|
||||
includeBuiltFile?: string;
|
||||
baselineFile?: string;
|
||||
libFiles?: string;
|
||||
}
|
||||
|
||||
// Additional options not already in ts.optionDeclarations
|
||||
@@ -917,6 +918,7 @@ namespace Harness {
|
||||
{ name: "baselineFile", type: "string" },
|
||||
{ name: "includeBuiltFile", type: "string" },
|
||||
{ name: "fileName", type: "string" },
|
||||
{ name: "libFiles", type: "string" },
|
||||
{ name: "noErrorTruncation", type: "boolean" }
|
||||
];
|
||||
|
||||
@@ -995,14 +997,11 @@ namespace Harness {
|
||||
currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory();
|
||||
|
||||
// Parse settings
|
||||
let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames();
|
||||
if (harnessSettings) {
|
||||
setCompilerOptionsFromHarnessSetting(harnessSettings, options);
|
||||
}
|
||||
if (options.useCaseSensitiveFileNames !== undefined) {
|
||||
useCaseSensitiveFileNames = options.useCaseSensitiveFileNames;
|
||||
}
|
||||
|
||||
const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames();
|
||||
const programFiles: TestFile[] = inputFiles.slice();
|
||||
// Files from built\local that are requested by test "@includeBuiltFiles" to be in the context.
|
||||
// Treat them as library files, so include them in build, but not in baselines.
|
||||
@@ -1017,6 +1016,15 @@ namespace Harness {
|
||||
|
||||
const fileOutputs: GeneratedFile[] = [];
|
||||
|
||||
// Files from tests\lib that are requested by "@libFiles"
|
||||
if (options.libFiles) {
|
||||
for (const fileName of options.libFiles.split(",")) {
|
||||
const libFileName = "tests/lib/" + fileName;
|
||||
programFiles.push({ unitName: libFileName, content: normalizeLineEndings(IO.readFile(libFileName), Harness.IO.newLine()) });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const programFileNames = programFiles.map(file => file.unitName);
|
||||
|
||||
const compilerHost = createCompilerHost(
|
||||
|
||||
@@ -172,7 +172,6 @@ namespace Harness.SourceMapRecoder {
|
||||
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
|
||||
}
|
||||
// 5. Check if there is name:
|
||||
decodeOfEncodedMapping.nameIndex = -1;
|
||||
if (!isSourceMappingSegmentEnd()) {
|
||||
prevNameIndex += base64VLQFormatDecode();
|
||||
decodeOfEncodedMapping.nameIndex = prevNameIndex;
|
||||
@@ -249,7 +248,7 @@ namespace Harness.SourceMapRecoder {
|
||||
mapString += " name (" + sourceMapNames[mapEntry.nameIndex] + ")";
|
||||
}
|
||||
else {
|
||||
if (mapEntry.nameIndex !== -1 || getAbsentNameIndex) {
|
||||
if ((mapEntry.nameIndex && mapEntry.nameIndex !== -1) || getAbsentNameIndex) {
|
||||
mapString += " nameIndex (" + mapEntry.nameIndex + ")";
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+13
-10
@@ -2058,6 +2058,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven
|
||||
* Gets or sets the version attribute specified in the declaration of an XML document.
|
||||
*/
|
||||
xmlVersion: string;
|
||||
currentScript: HTMLScriptElement;
|
||||
adoptNode(source: Node): Node;
|
||||
captureEvents(): void;
|
||||
clear(): void;
|
||||
@@ -2977,6 +2978,7 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
|
||||
webkitRequestFullScreen(): void;
|
||||
webkitRequestFullscreen(): void;
|
||||
getElementsByClassName(classNames: string): NodeListOf<Element>;
|
||||
matches(selector: string): boolean;
|
||||
addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void;
|
||||
@@ -3961,7 +3963,6 @@ interface HTMLElement extends Element {
|
||||
title: string;
|
||||
blur(): void;
|
||||
click(): void;
|
||||
contains(child: HTMLElement): boolean;
|
||||
dragDrop(): boolean;
|
||||
focus(): void;
|
||||
insertAdjacentElement(position: string, insertedElement: Element): Element;
|
||||
@@ -6135,7 +6136,7 @@ interface HTMLSelectElement extends HTMLElement {
|
||||
* Sets or retrieves the name of the object.
|
||||
*/
|
||||
name: string;
|
||||
options: HTMLSelectElement;
|
||||
options: HTMLCollection;
|
||||
/**
|
||||
* When present, marks an element that can't be submitted without a value.
|
||||
*/
|
||||
@@ -6421,19 +6422,19 @@ interface HTMLTableElement extends HTMLElement {
|
||||
/**
|
||||
* Creates an empty caption element in the table.
|
||||
*/
|
||||
createCaption(): HTMLElement;
|
||||
createCaption(): HTMLTableCaptionElement;
|
||||
/**
|
||||
* Creates an empty tBody element in the table.
|
||||
*/
|
||||
createTBody(): HTMLElement;
|
||||
createTBody(): HTMLTableSectionElement;
|
||||
/**
|
||||
* Creates an empty tFoot element in the table.
|
||||
*/
|
||||
createTFoot(): HTMLElement;
|
||||
createTFoot(): HTMLTableSectionElement;
|
||||
/**
|
||||
* Returns the tHead element object if successful, or null otherwise.
|
||||
*/
|
||||
createTHead(): HTMLElement;
|
||||
createTHead(): HTMLTableSectionElement;
|
||||
/**
|
||||
* Deletes the caption element and its contents from the table.
|
||||
*/
|
||||
@@ -6455,7 +6456,7 @@ interface HTMLTableElement extends HTMLElement {
|
||||
* Creates a new row (tr) in the table, and adds the row to the rows collection.
|
||||
* @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
|
||||
*/
|
||||
insertRow(index?: number): HTMLElement;
|
||||
insertRow(index?: number): HTMLTableRowElement;
|
||||
}
|
||||
|
||||
declare var HTMLTableElement: {
|
||||
@@ -6506,7 +6507,7 @@ interface HTMLTableRowElement extends HTMLElement, HTMLTableAlignment {
|
||||
* Creates a new cell in the table row, and adds the cell to the cells collection.
|
||||
* @param index Number that specifies where to insert the cell in the tr. The default value is -1, which appends the new cell to the end of the cells collection.
|
||||
*/
|
||||
insertCell(index?: number): HTMLElement;
|
||||
insertCell(index?: number): HTMLTableCellElement;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -6533,7 +6534,7 @@ interface HTMLTableSectionElement extends HTMLElement, HTMLTableAlignment {
|
||||
* Creates a new row (tr) in the table, and adds the row to the rows collection.
|
||||
* @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.
|
||||
*/
|
||||
insertRow(index?: number): HTMLElement;
|
||||
insertRow(index?: number): HTMLTableRowElement;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -7071,7 +7072,7 @@ declare var IDBVersionChangeEvent: {
|
||||
}
|
||||
|
||||
interface ImageData {
|
||||
data: number[];
|
||||
data: Uint8ClampedArray;
|
||||
height: number;
|
||||
width: number;
|
||||
}
|
||||
@@ -7869,6 +7870,7 @@ interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorConte
|
||||
getGamepads(): Gamepad[];
|
||||
javaEnabled(): boolean;
|
||||
msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;
|
||||
vibrate(pattern: number | number[]): boolean;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -7909,6 +7911,7 @@ interface Node extends EventTarget {
|
||||
normalize(): void;
|
||||
removeChild(oldChild: Node): Node;
|
||||
replaceChild(newChild: Node, oldChild: Node): Node;
|
||||
contains(node: Node): boolean;
|
||||
ATTRIBUTE_NODE: number;
|
||||
CDATA_SECTION_NODE: number;
|
||||
COMMENT_NODE: number;
|
||||
|
||||
Vendored
+1
-1
@@ -460,7 +460,7 @@ declare var IDBVersionChangeEvent: {
|
||||
}
|
||||
|
||||
interface ImageData {
|
||||
data: number[];
|
||||
data: Uint8ClampedArray;
|
||||
height: number;
|
||||
width: number;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace ts.BreakpointResolver {
|
||||
|
||||
let tokenAtLocation = getTokenAtPosition(sourceFile, position);
|
||||
let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
|
||||
// Get previous token if the token is returned starts on new line
|
||||
// eg: let x =10; |--- cursor is here
|
||||
// let y = 10;
|
||||
@@ -39,16 +39,23 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(tokenAtLocation);
|
||||
|
||||
function textSpan(startNode: Node, endNode?: Node) {
|
||||
return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
|
||||
const start = startNode.decorators ?
|
||||
skipTrivia(sourceFile.text, startNode.decorators.end) :
|
||||
startNode.getStart(sourceFile);
|
||||
return createTextSpanFromBounds(start, (endNode || startNode).getEnd());
|
||||
}
|
||||
|
||||
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
|
||||
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
|
||||
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
|
||||
return spanInNode(node);
|
||||
}
|
||||
return spanInNode(otherwiseOnNode);
|
||||
}
|
||||
|
||||
function spanInNodeArray<T>(nodeArray: NodeArray<T>) {
|
||||
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
|
||||
}
|
||||
|
||||
function spanInPreviousNode(node: Node): TextSpan {
|
||||
return spanInNode(findPrecedingToken(node.pos, sourceFile));
|
||||
}
|
||||
@@ -65,6 +72,11 @@ namespace ts.BreakpointResolver {
|
||||
return spanInPreviousNode(node);
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.Decorator) {
|
||||
// Set breakpoint on the decorator emit
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.ForStatement) {
|
||||
// For now lets set the span on this expression, fix it later
|
||||
return textSpan(node);
|
||||
@@ -207,6 +219,9 @@ namespace ts.BreakpointResolver {
|
||||
// span in statement
|
||||
return spanInNode((<WithStatement>node).statement);
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
return spanInNodeArray(node.parent.decorators);
|
||||
|
||||
// No breakpoint in interface, type alias
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
|
||||
+24
-21
@@ -1901,7 +1901,7 @@ namespace ts {
|
||||
sourceMapText = text;
|
||||
}
|
||||
else {
|
||||
Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: " + name);
|
||||
Debug.assert(outputText === undefined, `Unexpected multiple outputs for the file: '${name}'`);
|
||||
outputText = text;
|
||||
}
|
||||
},
|
||||
@@ -4248,28 +4248,31 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// Method/function type parameter
|
||||
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));
|
||||
let declaration = <Node>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter);
|
||||
Debug.assert(declaration !== undefined);
|
||||
declaration = declaration.parent;
|
||||
|
||||
if (declaration) {
|
||||
if (isFunctionLikeKind(declaration.kind)) {
|
||||
const signature = typeChecker.getSignatureFromDeclaration(<SignatureDeclaration>declaration);
|
||||
if (declaration.kind === SyntaxKind.ConstructSignature) {
|
||||
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
|
||||
displayParts.push(spacePart());
|
||||
}
|
||||
else if (declaration.kind !== SyntaxKind.CallSignature && (<SignatureDeclaration>declaration).name) {
|
||||
addFullSymbolName(declaration.symbol);
|
||||
}
|
||||
addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature));
|
||||
}
|
||||
else {
|
||||
// Type alias type parameter
|
||||
// For example
|
||||
// type list<T> = T[]; // Both T will go through same code path
|
||||
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));
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user