merge with origin/release-2.0

This commit is contained in:
Vladimir Matveev
2016-08-29 14:13:22 -07:00
117 changed files with 18337 additions and 11729 deletions
+148 -110
View File
@@ -106,7 +106,7 @@ namespace ts {
isOptionalParameter
};
const tupleTypes = createMap<TupleType>();
const tupleTypes: GenericType[] = [];
const unionTypes = createMap<UnionType>();
const intersectionTypes = createMap<IntersectionType>();
const stringLiteralTypes = createMap<LiteralType>();
@@ -1023,8 +1023,8 @@ namespace ts {
}
}
function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration {
return findMap(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined);
function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined {
return forEach(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined);
}
function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration): Symbol {
@@ -1126,13 +1126,13 @@ namespace ts {
else {
symbolFromVariable = getPropertyOfVariable(targetSymbol, name.text);
}
// If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default
if (!symbolFromVariable && allowSyntheticDefaultImports && name.text === "default") {
symbolFromVariable = resolveExternalModuleSymbol(moduleSymbol) || resolveSymbol(moduleSymbol);
}
// if symbolFromVariable is export - get its final target
symbolFromVariable = resolveSymbol(symbolFromVariable);
const symbolFromModule = getExportOfModule(targetSymbol, name.text);
let symbolFromModule = getExportOfModule(targetSymbol, name.text);
// If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default
if (!symbolFromModule && allowSyntheticDefaultImports && name.text === "default") {
symbolFromModule = resolveExternalModuleSymbol(moduleSymbol) || resolveSymbol(moduleSymbol);
}
const symbol = symbolFromModule && symbolFromVariable ?
combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) :
symbolFromModule || symbolFromVariable;
@@ -1191,6 +1191,7 @@ namespace ts {
if (!links.target) {
links.target = resolvingSymbol;
const node = getDeclarationOfAliasSymbol(symbol);
Debug.assert(!!node);
const target = getTargetOfAliasDeclaration(node);
if (links.target === resolvingSymbol) {
links.target = target || unknownSymbol;
@@ -1226,6 +1227,7 @@ namespace ts {
if (!links.referenced) {
links.referenced = true;
const node = getDeclarationOfAliasSymbol(symbol);
Debug.assert(!!node);
if (node.kind === SyntaxKind.ExportAssignment) {
// export default <symbol>
checkExpressionCached((<ExportAssignment>node).expression);
@@ -2145,9 +2147,6 @@ namespace ts {
// The specified symbol flags need to be reinterpreted as type flags
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
}
else if (type.flags & TypeFlags.Tuple) {
writeTupleType(<TupleType>type);
}
else if (!(flags & TypeFormatFlags.InTypeAlias) && type.flags & (TypeFlags.Anonymous | TypeFlags.UnionOrIntersection) && type.aliasSymbol) {
const typeArguments = type.aliasTypeArguments;
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
@@ -2214,6 +2213,11 @@ namespace ts {
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
}
else if (type.target.flags & TypeFlags.Tuple) {
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writeTypeList(type.typeArguments.slice(0, getTypeReferenceArity(type)), SyntaxKind.CommaToken);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
}
else {
// Write the type reference in the format f<A>.g<B>.C<X, Y> where A and B are type arguments
// for outer type parameters, and f and g are the respective declaring containers of those
@@ -2242,12 +2246,6 @@ namespace ts {
}
}
function writeTupleType(type: TupleType) {
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writeTypeList(type.elementTypes, SyntaxKind.CommaToken);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
}
function writeUnionOrIntersectionType(type: UnionOrIntersectionType, flags: TypeFormatFlags) {
if (flags & TypeFormatFlags.InElementType) {
writePunctuation(writer, SyntaxKind.OpenParenToken);
@@ -2958,7 +2956,7 @@ namespace ts {
: elementType;
if (!type) {
if (isTupleType(parentType)) {
error(declaration, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), (<TupleType>parentType).elementTypes.length, pattern.elements.length);
error(declaration, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), getTypeReferenceArity(<TypeReference>parentType), pattern.elements.length);
}
else {
error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName);
@@ -3070,9 +3068,14 @@ namespace ts {
}
}
// Use contextual parameter type if one is available
const type = declaration.symbol.name === "this"
? getContextuallyTypedThisType(func)
: getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
let type: Type;
if (declaration.symbol.name === "this") {
const thisParameter = getContextualThisParameter(func);
type = thisParameter ? getTypeOfSymbol(thisParameter) : undefined;
}
else {
type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
}
if (type) {
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
}
@@ -3150,12 +3153,13 @@ namespace ts {
}
// If the pattern has at least one element, and no rest element, then it should imply a tuple type.
const elementTypes = map(elements, e => e.kind === SyntaxKind.OmittedExpression ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors));
let result = createTupleType(elementTypes);
if (includePatternInType) {
const result = createNewTupleType(elementTypes);
result = cloneTypeReference(result);
result.pattern = pattern;
return result;
}
return createTupleType(elementTypes);
return result;
}
// Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself
@@ -3564,18 +3568,21 @@ namespace ts {
}
function getBaseTypes(type: InterfaceType): ObjectType[] {
const isClass = type.symbol.flags & SymbolFlags.Class;
const isInterface = type.symbol.flags & SymbolFlags.Interface;
if (!type.resolvedBaseTypes) {
if (!isClass && !isInterface) {
if (type.flags & TypeFlags.Tuple) {
type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))];
}
else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
if (type.symbol.flags & SymbolFlags.Class) {
resolveBaseTypesOfClass(type);
}
if (type.symbol.flags & SymbolFlags.Interface) {
resolveBaseTypesOfInterface(type);
}
}
else {
Debug.fail("type must be class or interface");
}
if (isClass) {
resolveBaseTypesOfClass(type);
}
if (isInterface) {
resolveBaseTypesOfInterface(type);
}
}
return type.resolvedBaseTypes;
}
@@ -4001,20 +4008,25 @@ namespace ts {
return createTypeReference((<TypeReference>type).target,
concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
}
if (type.flags & TypeFlags.Tuple) {
return createTupleType((type as TupleType).elementTypes, thisArgument);
}
return type;
}
function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: TypeParameter[], typeArguments: Type[]) {
let mapper = identityMapper;
let members = source.symbol.members;
let callSignatures = source.declaredCallSignatures;
let constructSignatures = source.declaredConstructSignatures;
let stringIndexInfo = source.declaredStringIndexInfo;
let numberIndexInfo = source.declaredNumberIndexInfo;
if (!rangeEquals(typeParameters, typeArguments, 0, typeParameters.length)) {
let mapper: TypeMapper;
let members: SymbolTable;
let callSignatures: Signature[];
let constructSignatures: Signature[];
let stringIndexInfo: IndexInfo;
let numberIndexInfo: IndexInfo;
if (rangeEquals(typeParameters, typeArguments, 0, typeParameters.length)) {
mapper = identityMapper;
members = source.symbol ? source.symbol.members : createSymbolTable(source.declaredProperties);
callSignatures = source.declaredCallSignatures;
constructSignatures = source.declaredConstructSignatures;
stringIndexInfo = source.declaredStringIndexInfo;
numberIndexInfo = source.declaredNumberIndexInfo;
}
else {
mapper = createTypeMapper(typeParameters, typeArguments);
members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1);
callSignatures = instantiateList(source.declaredCallSignatures, mapper, instantiateSignature);
@@ -4024,7 +4036,7 @@ namespace ts {
}
const baseTypes = getBaseTypes(source);
if (baseTypes.length) {
if (members === source.symbol.members) {
if (source.symbol && members === source.symbol.members) {
members = createSymbolTable(source.declaredProperties);
}
const thisArgument = lastOrUndefined(typeArguments);
@@ -4094,26 +4106,6 @@ namespace ts {
return result;
}
function createTupleTypeMemberSymbols(memberTypes: Type[]): SymbolTable {
const members = createMap<Symbol>();
for (let i = 0; i < memberTypes.length; i++) {
const symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "" + i);
symbol.type = memberTypes[i];
members[i] = symbol;
}
return members;
}
function resolveTupleTypeMembers(type: TupleType) {
const arrayElementType = getUnionType(type.elementTypes);
// Make the tuple type itself the 'this' type by including an extra type argument
// (Unless it's provided in the case that the tuple is a type parameter constraint)
const arrayType = resolveStructuredTypeMembers(createTypeFromGenericGlobalType(globalArrayType, [arrayElementType, type.thisType || type]));
const members = createTupleTypeMemberSymbols(type.elementTypes);
addInheritedMembers(members, arrayType.properties);
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexInfo, arrayType.numberIndexInfo);
}
function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature {
for (const s of signatureList) {
if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, compareTypesIdentical)) {
@@ -4292,9 +4284,6 @@ namespace ts {
else if (type.flags & TypeFlags.Anonymous) {
resolveAnonymousTypeMembers(<AnonymousType>type);
}
else if (type.flags & TypeFlags.Tuple) {
resolveTupleTypeMembers(<TupleType>type);
}
else if (type.flags & TypeFlags.Union) {
resolveUnionTypeMembers(<UnionType>type);
}
@@ -4694,6 +4683,9 @@ namespace ts {
if (isJSConstructSignature) {
minArgumentCount--;
}
if (!thisParameter && isObjectLiteralMethod(declaration)) {
thisParameter = getContextualThisParameter(declaration);
}
const classType = declaration.kind === SyntaxKind.Constructor ?
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
@@ -4992,6 +4984,17 @@ namespace ts {
return type;
}
function cloneTypeReference(source: TypeReference): TypeReference {
const type = <TypeReference>createObjectType(source.flags, source.symbol);
type.target = source.target;
type.typeArguments = source.typeArguments;
return type;
}
function getTypeReferenceArity(type: TypeReference): number {
return type.target.typeParameters ? type.target.typeParameters.length : 0;
}
// Get type from reference to class or interface
function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
const type = <InterfaceType>getDeclaredTypeOfSymbol(getMergedSymbol(symbol));
@@ -5234,17 +5237,47 @@ namespace ts {
return links.resolvedType;
}
function createTupleType(elementTypes: Type[], thisType?: Type) {
const id = getTypeListId(elementTypes) + "," + (thisType ? thisType.id : 0);
return tupleTypes[id] || (tupleTypes[id] = createNewTupleType(elementTypes, thisType));
// We represent tuple types as type references to synthesized generic interface types created by
// this function. The types are of the form:
//
// interface Tuple<T0, T1, T2, ...> extends Array<T0 | T1 | T2 | ...> { 0: T0, 1: T1, 2: T2, ... }
//
// Note that the generic type created by this function has no symbol associated with it. The same
// is true for each of the synthesized type parameters.
function createTupleTypeOfArity(arity: number): GenericType {
const typeParameters: TypeParameter[] = [];
const properties: Symbol[] = [];
for (let i = 0; i < arity; i++) {
const typeParameter = <TypeParameter>createType(TypeFlags.TypeParameter);
typeParameters.push(typeParameter);
const property = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "" + i);
property.type = typeParameter;
properties.push(property);
}
const type = <GenericType & InterfaceTypeWithDeclaredMembers>createObjectType(TypeFlags.Tuple | TypeFlags.Reference);
type.typeParameters = typeParameters;
type.outerTypeParameters = undefined;
type.localTypeParameters = typeParameters;
type.instantiations = createMap<TypeReference>();
type.instantiations[getTypeListId(type.typeParameters)] = <GenericType>type;
type.target = <GenericType>type;
type.typeArguments = type.typeParameters;
type.thisType = <TypeParameter>createType(TypeFlags.TypeParameter | TypeFlags.ThisType);
type.thisType.constraint = type;
type.declaredProperties = properties;
type.declaredCallSignatures = emptyArray;
type.declaredConstructSignatures = emptyArray;
type.declaredStringIndexInfo = undefined;
type.declaredNumberIndexInfo = undefined;
return type;
}
function createNewTupleType(elementTypes: Type[], thisType?: Type) {
const propagatedFlags = getPropagatingFlagsOfTypes(elementTypes, /*excludeKinds*/ 0);
const type = <TupleType>createObjectType(TypeFlags.Tuple | propagatedFlags);
type.elementTypes = elementTypes;
type.thisType = thisType;
return type;
function getTupleTypeOfArity(arity: number): GenericType {
return tupleTypes[arity] || (tupleTypes[arity] = createTupleTypeOfArity(arity));
}
function createTupleType(elementTypes: Type[]) {
return createTypeReference(getTupleTypeOfArity(elementTypes.length), elementTypes);
}
function getTypeFromTupleTypeNode(node: TupleTypeNode): Type {
@@ -5552,6 +5585,12 @@ namespace ts {
return nullType;
case SyntaxKind.NeverKeyword:
return neverType;
case SyntaxKind.JSDocNullKeyword:
return nullType;
case SyntaxKind.JSDocUndefinedKeyword:
return undefinedType;
case SyntaxKind.JSDocNeverKeyword:
return neverType;
case SyntaxKind.ThisType:
case SyntaxKind.ThisKeyword:
return getTypeFromThisTypeNode(node);
@@ -5845,9 +5884,6 @@ namespace ts {
if (type.flags & TypeFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType));
}
if (type.flags & TypeFlags.Tuple) {
return createTupleType(instantiateList((<TupleType>type).elementTypes, mapper, instantiateType));
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*subtypeReduction*/ false, type.aliasSymbol, mapper.targetTypes);
}
@@ -6267,6 +6303,18 @@ namespace ts {
reportError(message, sourceType, targetType);
}
function tryElaborateErrorsForPrimitivesAndObjects(source: Type, target: Type) {
const sourceType = typeToString(source);
const targetType = typeToString(target);
if ((globalStringType === source && stringType === target) ||
(globalNumberType === source && numberType === target) ||
(globalBooleanType === source && booleanType === target) ||
(getGlobalESSymbolType() === source && esSymbolType === target)) {
reportError(Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType);
}
}
// Compare two types and return
// Ternary.True if they are related with no assumptions,
// Ternary.Maybe if they are related with assumptions of other relationships, or
@@ -6390,6 +6438,9 @@ namespace ts {
}
if (reportErrors) {
if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.Primitive) {
tryElaborateErrorsForPrimitivesAndObjects(source, target);
}
reportRelationError(headMessage, source, target);
}
return Ternary.False;
@@ -7168,8 +7219,8 @@ namespace ts {
* Check if a Type was written as a tuple type literal.
* Prefer using isTupleLikeType() unless the use of `elementTypes` is required.
*/
function isTupleType(type: Type): type is TupleType {
return !!(type.flags & TypeFlags.Tuple);
function isTupleType(type: Type): boolean {
return !!(type.flags & TypeFlags.Reference && (<TypeReference>type).target.flags & TypeFlags.Tuple);
}
function getFalsyFlagsOfTypes(types: Type[]): TypeFlags {
@@ -7301,11 +7352,8 @@ namespace ts {
if (type.flags & TypeFlags.Union) {
return getUnionType(map((<UnionType>type).types, getWidenedConstituentType));
}
if (isArrayType(type)) {
return createArrayType(getWidenedType((<TypeReference>type).typeArguments[0]));
}
if (isTupleType(type)) {
return createTupleType(map(type.elementTypes, getWidenedType));
if (isArrayType(type) || isTupleType(type)) {
return createTypeReference((<TypeReference>type).target, map((<TypeReference>type).typeArguments, getWidenedType));
}
}
return type;
@@ -7331,11 +7379,8 @@ namespace ts {
}
}
}
if (isArrayType(type)) {
return reportWideningErrorsInType((<TypeReference>type).typeArguments[0]);
}
if (isTupleType(type)) {
for (const t of type.elementTypes) {
if (isArrayType(type) || isTupleType(type)) {
for (const t of (<TypeReference>type).typeArguments) {
if (reportWideningErrorsInType(t)) {
errorReported = true;
}
@@ -7445,7 +7490,6 @@ namespace ts {
function couldContainTypeParameters(type: Type): boolean {
return !!(type.flags & TypeFlags.TypeParameter ||
type.flags & TypeFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
type.flags & TypeFlags.Tuple && forEach((<TupleType>type).elementTypes, couldContainTypeParameters) ||
type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<UnionOrIntersectionType>type));
}
@@ -7548,14 +7592,6 @@ namespace ts {
inferFromTypes(sourceTypes[i], targetTypes[i]);
}
}
else if (source.flags & TypeFlags.Tuple && target.flags & TypeFlags.Tuple && (<TupleType>source).elementTypes.length === (<TupleType>target).elementTypes.length) {
// If source and target are tuples of the same size, infer from element types
const sourceTypes = (<TupleType>source).elementTypes;
const targetTypes = (<TupleType>target).elementTypes;
for (let i = 0; i < sourceTypes.length; i++) {
inferFromTypes(sourceTypes[i], targetTypes[i]);
}
}
else if (target.flags & TypeFlags.UnionOrIntersection) {
const targetTypes = (<UnionOrIntersectionType>target).types;
let typeParameterCount = 0;
@@ -9100,10 +9136,6 @@ namespace ts {
return getInferredClassType(classSymbol);
}
}
const type = getContextuallyTypedThisType(container);
if (type) {
return type;
}
const thisType = getThisTypeOfDeclaration(container);
if (thisType) {
@@ -9344,11 +9376,11 @@ namespace ts {
}
}
function getContextuallyTypedThisType(func: FunctionLikeDeclaration): Type {
function getContextualThisParameter(func: FunctionLikeDeclaration): Symbol {
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
const contextualSignature = getContextualSignature(func);
if (contextualSignature) {
return getThisTypeOfSignature(contextualSignature);
return contextualSignature.thisParameter;
}
}
@@ -9913,7 +9945,7 @@ namespace ts {
// If array literal is actually a destructuring pattern, mark it as an implied type. We do this such
// that we get the same behavior for "var [x, y] = []" and "[x, y] = []".
if (inDestructuringPattern && elementTypes.length) {
const type = createNewTupleType(elementTypes);
const type = cloneTypeReference(createTupleType(elementTypes));
type.pattern = node;
return type;
}
@@ -9927,7 +9959,7 @@ namespace ts {
for (let i = elementTypes.length; i < patternElements.length; i++) {
const patternElement = patternElements[i];
if (hasDefaultValue(patternElement)) {
elementTypes.push((<TupleType>contextualType).elementTypes[i]);
elementTypes.push((<TypeReference>contextualType).typeArguments[i]);
}
else {
if (patternElement.kind !== SyntaxKind.OmittedExpression) {
@@ -12291,6 +12323,12 @@ namespace ts {
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
if (context.thisParameter) {
if (!signature.thisParameter) {
signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
}
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
}
for (let i = 0; i < len; i++) {
const parameter = signature.parameters[i];
const contextualParameterType = getTypeAtPosition(context, i);
@@ -13038,7 +13076,7 @@ namespace ts {
// such as NodeCheckFlags.LexicalThis on "this"expression.
checkExpression(element);
if (isTupleType(sourceType)) {
error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), (<TupleType>sourceType).elementTypes.length, elements.length);
error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), getTypeReferenceArity(<TypeReference>sourceType), elements.length);
}
else {
error(element, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
@@ -18515,7 +18553,7 @@ namespace ts {
else if (isTypeOfKind(type, TypeFlags.StringLike)) {
return TypeReferenceSerializationKind.StringLikeType;
}
else if (isTypeOfKind(type, TypeFlags.Tuple)) {
else if (isTupleType(type)) {
return TypeReferenceSerializationKind.ArrayLikeType;
}
else if (isTypeOfKind(type, TypeFlags.ESSymbol)) {
+4 -4
View File
@@ -672,10 +672,10 @@ namespace ts {
* @param fileName The path to the config file
* @param jsonText The text of the config file
*/
export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
export function parseConfigFileTextToJson(fileName: string, jsonText: string, stripComments = true): { config?: any; error?: Diagnostic } {
try {
const jsonTextWithoutComments = removeComments(jsonText);
return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} };
const jsonTextToParse = stripComments ? removeComments(jsonText) : jsonText;
return { config: /\S/.test(jsonTextToParse) ? JSON.parse(jsonTextToParse) : {} };
}
catch (e) {
return { error: createCompilerDiagnostic(Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) };
@@ -901,7 +901,7 @@ namespace ts {
function convertCompilerOptionsFromJsonWorker(jsonOptions: any,
basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions {
const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true } : {};
const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true, maxNodeModuleJsDepth: 2 } : {};
convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors);
return options;
}
+4 -2
View File
@@ -2091,8 +2091,10 @@ namespace ts {
const typesFile = tryReadTypesSection(packageJsonPath, candidate, state);
if (typesFile) {
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(typesFile), state.host);
// The package.json "typings" property must specify the file with extension, so just try that exact filename.
const result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures, state);
// A package.json "typings" may specify an exact filename, or may choose to omit an extension.
const result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures, state) ||
tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures, state);
if (result) {
return result;
}
+4 -2
View File
@@ -1132,8 +1132,10 @@ namespace ts {
// it if it's not a well known symbol. In that case, the text of the name will be exactly
// what we want, namely the name expression enclosed in brackets.
writeTextOfNode(currentText, node.name);
// If optional property emit ?
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.Parameter) && hasQuestionToken(node)) {
// If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor
// we don't want to emit property declaration with "?"
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature ||
(node.kind === SyntaxKind.Parameter && !isParameterPropertyDeclaration(node))) && hasQuestionToken(node)) {
write("?");
}
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
+4
View File
@@ -1955,6 +1955,10 @@
"category": "Error",
"code": 2691
},
"'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible.": {
"category": "Error",
"code": 2692
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
+4
View File
@@ -1817,6 +1817,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
else if (node.parent.kind === SyntaxKind.ConditionalExpression && (<ConditionalExpression>node.parent).condition === node) {
return true;
}
else if (node.parent.kind === SyntaxKind.PrefixUnaryExpression || node.parent.kind === SyntaxKind.DeleteExpression ||
node.parent.kind === SyntaxKind.TypeOfExpression || node.parent.kind === SyntaxKind.VoidExpression) {
return true;
}
return false;
}
+39 -17
View File
@@ -913,7 +913,7 @@ namespace ts {
// Note: it is not actually necessary to save/restore the context flags here. That's
// because the saving/restoring of these flags happens naturally through the recursive
// descent nature of our parser. However, we still store this here just so we can
// assert that that invariant holds.
// assert that invariant holds.
const saveContextFlags = contextFlags;
// If we're only looking ahead, then tell the scanner to only lookahead as well.
@@ -2766,7 +2766,7 @@ namespace ts {
// Note: for ease of implementation we treat productions '2' and '3' as the same thing.
// (i.e. they're both BinaryExpressions with an assignment operator in it).
// First, do the simple check if we have a YieldExpression (production '5').
// First, do the simple check if we have a YieldExpression (production '6').
if (isYieldExpression()) {
return parseYieldExpression();
}
@@ -3374,24 +3374,40 @@ namespace ts {
}
/**
* Parse ES7 unary expression and await expression
* Parse ES7 exponential expression and await expression
*
* ES7 ExponentiationExpression:
* 1) UnaryExpression[?Yield]
* 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
*
* ES7 UnaryExpression:
* 1) SimpleUnaryExpression[?yield]
* 2) IncrementExpression[?yield] ** UnaryExpression[?yield]
*/
function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression {
if (isAwaitExpression()) {
return parseAwaitExpression();
}
if (isIncrementExpression()) {
/**
* ES7 UpdateExpression:
* 1) LeftHandSideExpression[?Yield]
* 2) LeftHandSideExpression[?Yield][no LineTerminator here]++
* 3) LeftHandSideExpression[?Yield][no LineTerminator here]--
* 4) ++UnaryExpression[?Yield]
* 5) --UnaryExpression[?Yield]
*/
if (isUpdateExpression()) {
const incrementExpression = parseIncrementExpression();
return token() === SyntaxKind.AsteriskAsteriskToken ?
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) :
incrementExpression;
}
/**
* ES7 UnaryExpression:
* 1) UpdateExpression[?yield]
* 2) delete UpdateExpression[?yield]
* 3) void UpdateExpression[?yield]
* 4) typeof UpdateExpression[?yield]
* 5) + UpdateExpression[?yield]
* 6) - UpdateExpression[?yield]
* 7) ~ UpdateExpression[?yield]
* 8) ! UpdateExpression[?yield]
*/
const unaryOperator = token();
const simpleUnaryExpression = parseSimpleUnaryExpression();
if (token() === SyntaxKind.AsteriskAsteriskToken) {
@@ -3409,8 +3425,8 @@ namespace ts {
/**
* Parse ES7 simple-unary expression or higher:
*
* ES7 SimpleUnaryExpression:
* 1) IncrementExpression[?yield]
* ES7 UnaryExpression:
* 1) UpdateExpression[?yield]
* 2) delete UnaryExpression[?yield]
* 3) void UnaryExpression[?yield]
* 4) typeof UnaryExpression[?yield]
@@ -3433,13 +3449,15 @@ namespace ts {
return parseTypeOfExpression();
case SyntaxKind.VoidKeyword:
return parseVoidExpression();
case SyntaxKind.AwaitKeyword:
return parseAwaitExpression();
case SyntaxKind.LessThanToken:
// This is modified UnaryExpression grammar in TypeScript
// UnaryExpression (modified):
// < type > UnaryExpression
return parseTypeAssertion();
case SyntaxKind.AwaitKeyword:
if (isAwaitExpression()) {
return parseAwaitExpression();
}
default:
return parseIncrementExpression();
}
@@ -3448,14 +3466,14 @@ namespace ts {
/**
* Check if the current token can possibly be an ES7 increment expression.
*
* ES7 IncrementExpression:
* ES7 UpdateExpression:
* LeftHandSideExpression[?Yield]
* LeftHandSideExpression[?Yield][no LineTerminator here]++
* LeftHandSideExpression[?Yield][no LineTerminator here]--
* ++LeftHandSideExpression[?Yield]
* --LeftHandSideExpression[?Yield]
*/
function isIncrementExpression(): boolean {
function isUpdateExpression(): boolean {
// This function is called inside parseUnaryExpression to decide
// whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly
switch (token()) {
@@ -3466,6 +3484,7 @@ namespace ts {
case SyntaxKind.DeleteKeyword:
case SyntaxKind.TypeOfKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.AwaitKeyword:
return false;
case SyntaxKind.LessThanToken:
// If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression
@@ -5894,6 +5913,9 @@ namespace ts {
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NeverKeyword:
return parseTokenNode<JSDocType>();
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
+3 -2
View File
@@ -4,7 +4,8 @@
namespace ts {
/** The version of the TypeScript compiler release */
export const version = "2.1.0";
export const version = "2.0.2";
const emptyArray: any[] = [];
@@ -465,7 +466,7 @@ namespace ts {
// - This calls resolveModuleNames, and then calls findSourceFile for each resolved module.
// As all these operations happen - and are nested - within the createProgram call, they close over the below variables.
// The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses.
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 2;
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0;
let currentNodeModulesDepth = 0;
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
+5 -7
View File
@@ -352,6 +352,9 @@ namespace ts {
JSDocPropertyTag,
JSDocTypeLiteral,
JSDocLiteralType,
JSDocNullKeyword,
JSDocUndefinedKeyword,
JSDocNeverKeyword,
// Synthesized list
SyntaxList,
@@ -384,7 +387,7 @@ namespace ts {
FirstJSDocNode = JSDocTypeExpression,
LastJSDocNode = JSDocLiteralType,
FirstJSDocTagNode = JSDocComment,
LastJSDocTagNode = JSDocLiteralType
LastJSDocTagNode = JSDocNeverKeyword
}
export const enum NodeFlags {
@@ -2265,7 +2268,7 @@ namespace ts {
Class = 1 << 15, // Class
Interface = 1 << 16, // Interface
Reference = 1 << 17, // Generic type reference
Tuple = 1 << 18, // Tuple
Tuple = 1 << 18, // Synthesized generic tuple type
Union = 1 << 19, // Union (T | U)
Intersection = 1 << 20, // Intersection (T & U)
Anonymous = 1 << 21, // Anonymous
@@ -2387,11 +2390,6 @@ namespace ts {
instantiations: Map<TypeReference>; // Generic instantiation cache
}
export interface TupleType extends ObjectType {
elementTypes: Type[]; // Element types
thisType?: Type; // This-type of tuple (only needed for tuples that are constraints of type parameters)
}
export interface UnionOrIntersectionType extends Type {
types: Type[]; // Constituent types
/* @internal */
+4
View File
@@ -301,6 +301,10 @@ namespace ts {
return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode;
}
export function isJSDocTag(node: Node) {
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
}
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
if (nodeIsMissing(node) || !node.decorators) {
return getTokenPosOfNode(node, sourceFile);
+6 -6
View File
@@ -158,13 +158,13 @@ namespace RWC {
it("has the expected emitted code", () => {
Harness.Baseline.runBaseline(baseName + ".output.js", () => {
Harness.Baseline.runBaseline(`${baseName}.output.js`, () => {
return Harness.Compiler.collateOutputs(compilerResult.files);
}, baselineOpts);
});
it("has the expected declaration file content", () => {
Harness.Baseline.runBaseline(baseName + ".d.ts", () => {
Harness.Baseline.runBaseline(`${baseName}.d.ts`, () => {
if (!compilerResult.declFilesCode.length) {
return null;
}
@@ -174,7 +174,7 @@ namespace RWC {
});
it("has the expected source maps", () => {
Harness.Baseline.runBaseline(baseName + ".map", () => {
Harness.Baseline.runBaseline(`${baseName}.map`, () => {
if (!compilerResult.sourceMaps.length) {
return null;
}
@@ -192,7 +192,7 @@ namespace RWC {
});*/
it("has the expected errors", () => {
Harness.Baseline.runBaseline(baseName + ".errors.txt", () => {
Harness.Baseline.runBaseline(`${baseName}.errors.txt`, () => {
if (compilerResult.errors.length === 0) {
return null;
}
@@ -207,7 +207,7 @@ namespace RWC {
// declaration file errors as part of the baseline.
it("has the expected errors in generated declaration files", () => {
if (compilerOptions.declaration && !compilerResult.errors.length) {
Harness.Baseline.runBaseline(baseName + ".dts.errors.txt", () => {
Harness.Baseline.runBaseline(`${baseName}.dts.errors.txt`, () => {
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(
inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory);
@@ -223,7 +223,7 @@ namespace RWC {
});
it("has the expected types", () => {
Harness.Compiler.doTypeAndSymbolBaseline(baseName, compilerResult, inputFiles
Harness.Compiler.doTypeAndSymbolBaseline(`${baseName}.types`, compilerResult, inputFiles
.concat(otherFiles)
.filter(file => !!compilerResult.program.getSourceFile(file.unitName))
.filter(e => !Harness.isDefaultLibraryFile(e.unitName)), baselineOpts);
@@ -403,6 +403,7 @@ namespace ts {
{
compilerOptions: <CompilerOptions>{
allowJs: true,
maxNodeModuleJsDepth: 2,
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
@@ -429,6 +430,7 @@ namespace ts {
{
compilerOptions: <CompilerOptions>{
allowJs: false,
maxNodeModuleJsDepth: 2,
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
@@ -450,7 +452,8 @@ namespace ts {
{
compilerOptions:
{
allowJs: true
allowJs: true,
maxNodeModuleJsDepth: 2
},
errors: [{
file: undefined,
@@ -469,7 +472,8 @@ namespace ts {
{
compilerOptions:
{
allowJs: true
allowJs: true,
maxNodeModuleJsDepth: 2
},
errors: <Diagnostic[]>[]
}
+5 -19
View File
@@ -767,16 +767,9 @@ namespace ts {
parsesCorrectly(
"{null}",
`{
"kind": "JSDocTypeReference",
"kind": "NullKeyword",
"pos": 1,
"end": 5,
"name": {
"kind": "Identifier",
"pos": 1,
"end": 5,
"originalKeywordKind": "NullKeyword",
"text": "null"
}
"end": 5
}`);
});
@@ -784,16 +777,9 @@ namespace ts {
parsesCorrectly(
"{undefined}",
`{
"kind": "JSDocTypeReference",
"kind": "UndefinedKeyword",
"pos": 1,
"end": 10,
"name": {
"kind": "Identifier",
"pos": 1,
"end": 10,
"originalKeywordKind": "UndefinedKeyword",
"text": "undefined"
}
"end": 10
}`);
});
@@ -2379,4 +2365,4 @@ namespace ts {
});
});
});
}
}
+21
View File
@@ -181,5 +181,26 @@ namespace ts {
["/d.ts", "/folder/e.ts"]
);
});
it("parse and re-emit tsconfig.json file with diagnostics", () => {
const content = `{
"compilerOptions": {
"allowJs": true
// Some comments
"outDir": "bin"
}
"files": ["file1.ts"]
}`;
const { configJsonObject, diagnostics } = sanitizeConfigFile("config.json", content);
const expectedResult = {
compilerOptions: {
allowJs: true,
outDir: "bin"
},
files: ["file1.ts"]
};
assert.isTrue(diagnostics.length === 2);
assert.equal(JSON.stringify(configJsonObject), JSON.stringify(expectedResult));
});
});
}
+34 -20
View File
@@ -832,6 +832,23 @@ namespace ts {
checkNumberOfConfiguredProjects(projectService, 1);
checkNumberOfInferredProjects(projectService, 0);
});
it("should tolerate config file errors and still try to build a project", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {
"target": "es6",
"allowAnything": true
},
"someOtherProperty": {}
}`
};
const host = createServerHost([commonFile1, commonFile2, libFile, configFile]);
const projectService = createProjectService(host);
projectService.openClientFile(commonFile1.path);
checkNumberOfConfiguredProjects(projectService, 1);
checkProjectRootFiles(projectService.configuredProjects[0], [commonFile1.path, commonFile2.path]);
});
it("should use only one inferred project if 'useOneInferredProject' is set", () => {
const file1 = {
@@ -2273,10 +2290,15 @@ namespace ts {
projectService.openClientFile(file1.path);
{
projectService.checkNumberOfProjects({ inferredProjects: 1, configuredProjects: 1 });
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f);
assert.isTrue(configuredProject !== undefined, "should find configured project");
checkProjectErrors(configuredProject, [`Failed to parse file \'/a/b/tsconfig.json\': Unexpected token : in JSON at position 7.`]);
checkProjectErrors(configuredProject, [
"')' expected.",
"Declaration or statement expected.",
"Declaration or statement expected.",
"Failed to parse file '/a/b/tsconfig.json': Unexpected token ) in JSON at position 7."
]);
}
// fix config and trigger watcher
host.reloadFS([file1, file2, correctConfig]);
@@ -2316,14 +2338,19 @@ namespace ts {
assert.isTrue(configuredProject !== undefined, "should find configured project");
checkProjectErrors(configuredProject, []);
}
// fix config and trigger watcher
// break config and trigger watcher
host.reloadFS([file1, file2, corruptedConfig]);
host.triggerFileWatcherCallback(corruptedConfig.path, /*false*/);
{
projectService.checkNumberOfProjects({ inferredProjects: 1, configuredProjects: 1 });
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const configuredProject = forEach(projectService.synchronizeProjectList([]), f => f.info.projectName === corruptedConfig.path && f);
assert.isTrue(configuredProject !== undefined, "should find configured project");
checkProjectErrors(configuredProject, [`Failed to parse file \'/a/b/tsconfig.json\': Unexpected token : in JSON at position 7.`]);
checkProjectErrors(configuredProject, [
"')' expected.",
"Declaration or statement expected.",
"Declaration or statement expected.",
"Failed to parse file '/a/b/tsconfig.json': Unexpected token ) in JSON at position 7."
]);
}
});
});
@@ -2342,23 +2369,10 @@ namespace ts {
const projectService = createProjectService(host);
projectService.openClientFile(file1.path);
projectService.checkNumberOfProjects({ inferredProjects: 1, configuredProjects: 1 });
projectService.checkNumberOfProjects({ configuredProjects: 1 });
const project = projectService.findProject(corruptedConfig.path);
let expectedMessage: string;
try {
server.Errors.ThrowProjectDoesNotContainDocument(file1.path, project);
assert(false, "should not get there");
}
catch (e) {
expectedMessage = (<Error>e).message;
}
try {
project.getScriptInfo(file1.path);
}
catch (e) {
assert.equal((<Error>e).message, expectedMessage, "Unexpected error");
}
checkProjectRootFiles(project, [file1.path]);
});
});
}
+55 -15
View File
@@ -126,6 +126,7 @@ interface KeyAlgorithm {
}
interface KeyboardEventInit extends EventModifierInit {
code?: string;
key?: string;
location?: number;
repeat?: boolean;
@@ -2288,7 +2289,7 @@ declare var DeviceRotationRate: {
new(): DeviceRotationRate;
}
interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent {
interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent, ParentNode {
/**
* Sets or gets the URL for the current document.
*/
@@ -3351,7 +3352,7 @@ declare var Document: {
new(): Document;
}
interface DocumentFragment extends Node, NodeSelector {
interface DocumentFragment extends Node, NodeSelector, ParentNode {
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
@@ -3420,7 +3421,7 @@ declare var EXT_texture_filter_anisotropic: {
readonly TEXTURE_MAX_ANISOTROPY_EXT: number;
}
interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode {
interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode, ParentNode {
readonly classList: DOMTokenList;
className: string;
readonly clientHeight: number;
@@ -3675,6 +3676,16 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec
getElementsByClassName(classNames: string): NodeListOf<Element>;
matches(selector: string): boolean;
closest(selector: string): Element | null;
scrollIntoView(arg?: boolean | ScrollIntoViewOptions): void;
scroll(options?: ScrollToOptions): void;
scroll(x: number, y: number): void;
scrollTo(options?: ScrollToOptions): void;
scrollTo(x: number, y: number): void;
scrollBy(options?: ScrollToOptions): void;
scrollBy(x: number, y: number): void;
insertAdjacentElement(position: string, insertedElement: Element): Element | null;
insertAdjacentHTML(where: string, html: string): void;
insertAdjacentText(where: string, text: string): void;
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
addEventListener(type: "MSGestureDoubleTap", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
addEventListener(type: "MSGestureEnd", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
@@ -4446,7 +4457,7 @@ interface HTMLCanvasElement extends HTMLElement {
* @param type The standard MIME type for the image format to return. If you do not specify this parameter, the default value is a PNG format image.
*/
toDataURL(type?: string, ...args: any[]): string;
toBlob(callback: (result: Blob | null) => void, ... arguments: any[]): void;
toBlob(callback: (result: Blob | null) => void, type?: string, ...arguments: any[]): void;
}
declare var HTMLCanvasElement: {
@@ -4621,11 +4632,7 @@ interface HTMLElement extends Element {
click(): void;
dragDrop(): boolean;
focus(): void;
insertAdjacentElement(position: string, insertedElement: Element): Element;
insertAdjacentHTML(where: string, html: string): void;
insertAdjacentText(where: string, text: string): void;
msGetInputContext(): MSInputMethodContext;
scrollIntoView(top?: boolean): void;
setActive(): void;
addEventListener(type: "MSContentZoom", listener: (this: this, ev: UIEvent) => any, useCapture?: boolean): void;
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
@@ -5890,6 +5897,7 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle {
*/
type: string;
import?: Document;
integrity: string;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
@@ -6178,7 +6186,7 @@ interface HTMLMediaElement extends HTMLElement {
*/
canPlayType(type: string): string;
/**
* Fires immediately after the client loads the object.
* Resets the audio or video object and loads a new media resource.
*/
load(): void;
/**
@@ -6751,6 +6759,7 @@ interface HTMLScriptElement extends HTMLElement {
* Sets or retrieves the MIME type for the associated scripting engine.
*/
type: string;
integrity: string;
}
declare var HTMLScriptElement: {
@@ -7756,6 +7765,7 @@ interface KeyboardEvent extends UIEvent {
readonly repeat: boolean;
readonly shiftKey: boolean;
readonly which: number;
readonly code: string;
getModifierState(keyArg: string): boolean;
initKeyboardEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, keyArg: string, locationArg: number, modifiersListArg: string, repeat: boolean, locale: string): void;
readonly DOM_KEY_LOCATION_JOYSTICK: number;
@@ -9128,6 +9138,7 @@ interface PerformanceTiming {
readonly responseStart: number;
readonly unloadEventEnd: number;
readonly unloadEventStart: number;
readonly secureConnectionStart: number;
toJSON(): any;
}
@@ -11405,8 +11416,8 @@ declare var StereoPannerNode: {
interface Storage {
readonly length: number;
clear(): void;
getItem(key: string): string;
key(index: number): string;
getItem(key: string): string | null;
key(index: number): string | null;
removeItem(key: string): void;
setItem(key: string, data: string): void;
[key: string]: any;
@@ -12947,7 +12958,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window
onunload: (this: this, ev: Event) => any;
onvolumechange: (this: this, ev: Event) => any;
onwaiting: (this: this, ev: Event) => any;
readonly opener: Window;
opener: any;
orientation: string | number;
readonly outerHeight: number;
readonly outerWidth: number;
@@ -13002,6 +13013,9 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window
webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
webkitRequestAnimationFrame(callback: FrameRequestCallback): number;
scroll(options?: ScrollToOptions): void;
scrollTo(options?: ScrollToOptions): void;
scrollBy(options?: ScrollToOptions): void;
addEventListener(type: "MSGestureChange", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
addEventListener(type: "MSGestureDoubleTap", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
addEventListener(type: "MSGestureEnd", listener: (this: this, ev: MSGestureEvent) => any, useCapture?: boolean): void;
@@ -14029,6 +14043,20 @@ interface ProgressEventInit extends EventInit {
total?: number;
}
interface ScrollOptions {
behavior?: ScrollBehavior;
}
interface ScrollToOptions extends ScrollOptions {
left?: number;
top?: number;
}
interface ScrollIntoViewOptions extends ScrollOptions {
block?: ScrollLogicalPosition;
inline?: ScrollLogicalPosition;
}
interface ClipboardEventInit extends EventInit {
data?: string;
dataType?: string;
@@ -14072,7 +14100,7 @@ interface EcdsaParams extends Algorithm {
}
interface EcKeyGenParams extends Algorithm {
typedCurve: string;
namedCurve: string;
}
interface EcKeyAlgorithm extends KeyAlgorithm {
@@ -14208,6 +14236,13 @@ interface JsonWebKey {
k?: string;
}
interface ParentNode {
readonly children: HTMLCollection;
readonly firstElementChild: Element;
readonly lastElementChild: Element;
readonly childElementCount: number;
}
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface ErrorEventHandler {
@@ -14278,7 +14313,7 @@ declare var location: Location;
declare var locationbar: BarProp;
declare var menubar: BarProp;
declare var msCredentials: MSCredentials;
declare var name: string;
declare const name: never;
declare var navigator: Navigator;
declare var offscreenBuffering: string | boolean;
declare var onabort: (this: Window, ev: UIEvent) => any;
@@ -14372,7 +14407,7 @@ declare var ontouchstart: (ev: TouchEvent) => any;
declare var onunload: (this: Window, ev: Event) => any;
declare var onvolumechange: (this: Window, ev: Event) => any;
declare var onwaiting: (this: Window, ev: Event) => any;
declare var opener: Window;
declare var opener: any;
declare var orientation: string | number;
declare var outerHeight: number;
declare var outerWidth: number;
@@ -14425,6 +14460,9 @@ declare function webkitCancelAnimationFrame(handle: number): void;
declare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;
declare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;
declare function webkitRequestAnimationFrame(callback: FrameRequestCallback): number;
declare function scroll(options?: ScrollToOptions): void;
declare function scrollTo(options?: ScrollToOptions): void;
declare function scrollBy(options?: ScrollToOptions): void;
declare function toString(): string;
declare function addEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void;
declare function dispatchEvent(evt: Event): boolean;
@@ -14580,6 +14618,8 @@ type MSOutboundPayload = MSVideoSendPayload | MSAudioSendPayload;
type RTCIceGatherCandidate = RTCIceCandidate | RTCIceCandidateComplete;
type RTCTransport = RTCDtlsTransport | RTCSrtpSdesTransport;
type payloadtype = number;
type ScrollBehavior = "auto" | "instant" | "smooth";
type ScrollLogicalPosition = "start" | "center" | "end" | "nearest";
type IDBValidKey = number | string | Date | IDBArrayKey;
type BufferSource = ArrayBuffer | ArrayBufferView;
type MouseWheelEvent = WheelEvent;
+1 -1
View File
@@ -1000,7 +1000,7 @@ interface EcdsaParams extends Algorithm {
}
interface EcKeyGenParams extends Algorithm {
typedCurve: string;
namedCurve: string;
}
interface EcKeyAlgorithm extends KeyAlgorithm {
+56 -31
View File
@@ -11,6 +11,13 @@
namespace ts.server {
export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
export type ProjectServiceEvent =
{ eventName: "context", data: { project: Project, fileName: NormalizedPath } } | { eventName: "configFileDiag", data: { triggerFile?: string, configFileName: string, diagnostics: Diagnostic[] } }
export interface ProjectServiceEventHandler {
(event: ProjectServiceEvent): void;
}
/**
* This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
*/
@@ -19,10 +26,6 @@ namespace ts.server {
return projects.length > 1 ? deduplicate(result, areEqual) : result;
}
export interface ProjectServiceEventHandler {
(eventName: string, project: Project, fileName: NormalizedPath): void;
}
export interface HostConfiguration {
formatCodeOptions: FormatCodeSettings;
hostInfo: string;
@@ -348,7 +351,7 @@ namespace ts.server {
}
for (const openFile of this.openFiles) {
this.eventHandler("context", openFile.getDefaultProject(), openFile.fileName);
this.eventHandler({ eventName: "context", data: { project: openFile.getDefaultProject(), fileName: openFile.fileName } });
}
}
@@ -376,7 +379,8 @@ namespace ts.server {
}
private handleChangeInSourceFileForConfiguredProject(project: ConfiguredProject) {
const { projectOptions } = this.convertConfigFileContentToProjectOptions(project.configFileName);
const { projectOptions, configFileErrors } = this.convertConfigFileContentToProjectOptions(project.configFileName);
this.reportConfigFileDiagnostics(project.getProjectName(), configFileErrors);
const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f)));
const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f)));
@@ -410,6 +414,9 @@ namespace ts.server {
return;
}
const { configFileErrors } = this.convertConfigFileContentToProjectOptions(fileName);
this.reportConfigFileDiagnostics(fileName, configFileErrors);
this.logger.info(`Detected newly added tsconfig file: ${fileName}`);
this.reloadProjects();
}
@@ -657,38 +664,46 @@ namespace ts.server {
private convertConfigFileContentToProjectOptions(configFilename: string): ConfigFileConversionResult {
configFilename = normalizePath(configFilename);
const configObj = parseConfigFileTextToJson(configFilename, this.host.readFile(configFilename));
if (configObj.error) {
return { success: false, configFileErrors: [configObj.error] };
const configFileContent = this.host.readFile(configFilename);
let errors: Diagnostic[];
const result = parseConfigFileTextToJson(configFilename, configFileContent);
let config = result.config;
if (result.error) {
// try to reparse config file
const { configJsonObject: sanitizedConfig, diagnostics } = sanitizeConfigFile(configFilename, configFileContent);
config = sanitizedConfig;
errors = diagnostics.length ? diagnostics : [result.error];
}
const parsedCommandLine = parseJsonConfigFileContent(
configObj.config,
config,
this.host,
getDirectoryPath(configFilename),
/*existingOptions*/ {},
configFilename);
Debug.assert(!!parsedCommandLine.fileNames);
if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) {
return { success: false, configFileErrors: parsedCommandLine.errors };
if (parsedCommandLine.errors.length) {
errors = concatenate(errors, parsedCommandLine.errors);
}
Debug.assert(!!parsedCommandLine.fileNames);
if (parsedCommandLine.fileNames.length === 0) {
const error = createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename);
return { success: false, configFileErrors: [error] };
errors.push(createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename));
return { success: false, configFileErrors: errors };
}
const projectOptions: ProjectOptions = {
files: parsedCommandLine.fileNames,
compilerOptions: parsedCommandLine.options,
configHasFilesProperty: configObj.config["files"] !== undefined,
configHasFilesProperty: config["files"] !== undefined,
wildcardDirectories: createMap(parsedCommandLine.wildcardDirectories),
typingOptions: parsedCommandLine.typingOptions,
compileOnSave: parsedCommandLine.compileOnSave
};
return { success: true, projectOptions };
return { success: true, projectOptions, configFileErrors: errors };
}
private exceededTotalSizeLimitForNonTsFiles<T>(options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader<T>) {
@@ -718,12 +733,21 @@ namespace ts.server {
/*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(options, files, externalFilePropertyReader),
options.compileOnSave === undefined ? true : options.compileOnSave);
this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typingOptions);
this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typingOptions, /*configFileErrors*/ undefined);
this.externalProjects.push(project);
return project;
}
private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, clientFileName?: string) {
private reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile?: string) {
if (diagnostics && diagnostics.length > 0) {
this.eventHandler({
eventName: "configFileDiag",
data: { configFileName, diagnostics, triggerFile }
});
}
}
private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, configFileErrors: Diagnostic[], clientFileName?: string) {
const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader);
const project = new ConfiguredProject(
configFileName,
@@ -735,7 +759,7 @@ namespace ts.server {
/*languageServiceEnabled*/ !sizeLimitExceeded,
projectOptions.compileOnSave === undefined ? false : projectOptions.compileOnSave);
this.addFilesToProjectAndUpdateGraph(project, projectOptions.files, fileNamePropertyReader, clientFileName, projectOptions.typingOptions);
this.addFilesToProjectAndUpdateGraph(project, projectOptions.files, fileNamePropertyReader, clientFileName, projectOptions.typingOptions, configFileErrors);
project.watchConfigFile(project => this.onConfigChangedForConfiguredProject(project));
if (!sizeLimitExceeded) {
@@ -753,7 +777,7 @@ namespace ts.server {
}
}
private addFilesToProjectAndUpdateGraph<T>(project: ConfiguredProject | ExternalProject, files: T[], propertyReader: FilePropertyReader<T>, clientFileName: string, typingOptions: TypingOptions): void {
private addFilesToProjectAndUpdateGraph<T>(project: ConfiguredProject | ExternalProject, files: T[], propertyReader: FilePropertyReader<T>, clientFileName: string, typingOptions: TypingOptions, configFileErrors: Diagnostic[]): void {
let errors: Diagnostic[];
for (const f of files) {
const rootFilename = propertyReader.getFileName(f);
@@ -767,21 +791,22 @@ namespace ts.server {
(errors || (errors = [])).push(createFileNotFoundDiagnostic(rootFilename));
}
}
project.setProjectErrors(errors);
project.setProjectErrors(concatenate(configFileErrors, errors));
project.setTypingOptions(typingOptions);
project.updateGraph();
}
private openConfigFile(configFileName: NormalizedPath, clientFileName?: string): OpenConfigFileResult {
const conversionResult = this.convertConfigFileContentToProjectOptions(configFileName);
if (!conversionResult.success) {
// open project with no files and set errors on the project
const project = this.createAndAddConfiguredProject(configFileName, { files: [], compilerOptions: {} }, clientFileName);
project.setProjectErrors(conversionResult.configFileErrors);
return { success: false, errors: conversionResult.configFileErrors };
}
const project = this.createAndAddConfiguredProject(configFileName, conversionResult.projectOptions, clientFileName);
return { success: true, project, errors: project.getProjectErrors() };
const projectOptions = conversionResult.success
? conversionResult.projectOptions
: { files: [], compilerOptions: {} };
const project = this.createAndAddConfiguredProject(configFileName, projectOptions, conversionResult.configFileErrors, clientFileName);
return {
success: conversionResult.success,
project,
errors: project.getProjectErrors()
};
}
private updateNonInferredProject<T>(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader<T>, newOptions: CompilerOptions, newTypingOptions: TypingOptions, compileOnSave: boolean, configFileErrors: Diagnostic[]) {
+12 -6
View File
@@ -164,18 +164,24 @@ namespace ts.server {
protected readonly canUseEvents: boolean) {
const eventHandler: ProjectServiceEventHandler = canUseEvents
? (eventName, project, fileName) => this.handleEvent(eventName, project, fileName)
? event => this.handleEvent(event)
: undefined;
this.projectService = new ProjectService(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler);
this.gcTimer = new GcTimer(host, /*delay*/ 15000, logger);
}
private handleEvent(eventName: string, project: Project, fileName: NormalizedPath) {
if (eventName == "context") {
this.logger.info("got context event, updating diagnostics for" + fileName);
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
(n) => n === this.changeSeq, 100);
private handleEvent(event: ProjectServiceEvent) {
switch (event.eventName) {
case "context":
const { project, fileName } = event.data;
this.projectService.logger.info(`got context event, updating diagnostics for ${fileName}`);
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
(n) => n === this.changeSeq, 100);
break;
case "configFileDiag":
const { triggerFile, configFileName, diagnostics } = event.data;
this.configFileDiagnosticEvent(triggerFile, configFileName, diagnostics);
}
}
+9 -2
View File
@@ -296,11 +296,14 @@ namespace ts {
let pos = this.pos;
const useJSDocScanner = this.kind >= SyntaxKind.FirstJSDocTagNode && this.kind <= SyntaxKind.LastJSDocTagNode;
const processNode = (node: Node) => {
if (pos < node.pos) {
const isJSDocTagNode = isJSDocTag(node);
if (!isJSDocTagNode && pos < node.pos) {
pos = this.addSyntheticNodes(children, pos, node.pos, useJSDocScanner);
}
children.push(node);
pos = node.end;
if (!isJSDocTagNode) {
pos = node.end;
}
};
const processNodes = (nodes: NodeArray<Node>) => {
if (pos < nodes.pos) {
@@ -7683,6 +7686,10 @@ namespace ts {
* False will mean that node is not classified and traverse routine should recurse into node contents.
*/
function tryClassifyNode(node: Node): boolean {
if (isJSDocTag(node)) {
return true;
}
if (nodeIsMissing(node)) {
return true;
}
+1 -1
View File
@@ -1188,6 +1188,6 @@ namespace TypeScript.Services {
// TODO: it should be moved into a namespace though.
/* @internal */
const toolsVersion = "2.1";
const toolsVersion = "2.0";
/* tslint:enable:no-unused-variable */
+24
View File
@@ -925,4 +925,28 @@ namespace ts {
}
return ensureScriptKind(fileName, scriptKind);
}
export function sanitizeConfigFile(configFileName: string, content: string) {
const options: TranspileOptions = {
fileName: "config.js",
compilerOptions: {
target: ScriptTarget.ES6,
removeComments: true
},
reportDiagnostics: true
};
const { outputText, diagnostics } = ts.transpileModule("(" + content + ")", options);
// Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1
// also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these
// as well
const trimmedOutput = outputText.trim();
for (const diagnostic of diagnostics) {
diagnostic.start = diagnostic.start - 1;
}
const {config, error} = parseConfigFileTextToJson(configFileName, trimmedOutput.substring(1, trimmedOutput.length - 2), /*stripComments*/ false);
return {
configJsonObject: config || {},
diagnostics: error ? concatenate(diagnostics, [error]) : diagnostics
};
}
}