Merge branch 'master' into useReturnedThisFromSuperCalls

This commit is contained in:
Daniel Rosenwasser
2016-09-07 15:42:45 -07:00
315 changed files with 9847 additions and 3174 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ matrix:
branches:
only:
- master
- transforms
- release.2.0
install:
- npm uninstall typescript
+1
View File
@@ -128,6 +128,7 @@ var servicesSources = [
"services.ts",
"shims.ts",
"signatureHelp.ts",
"types.ts",
"utilities.ts",
"formatting/formatting.ts",
"formatting/formattingContext.ts",
+1 -1
View File
@@ -77,7 +77,7 @@
"ts-node": "latest",
"tsd": "latest",
"tslint": "next",
"typescript": "next"
"typescript": "2.1.0-dev.20160906"
},
"scripts": {
"pretest": "jake tests",
+68 -21
View File
@@ -2,6 +2,8 @@
/* @internal */
namespace ts {
const ambientModuleSymbolRegex = /^".+"$/;
let nextSymbolId = 1;
let nextNodeId = 1;
let nextMergeId = 1;
@@ -100,6 +102,7 @@ namespace ts {
getAliasedSymbol: resolveAlias,
getEmitResolver,
getExportsOfModule: getExportsOfModuleAsArray,
getAmbientModules,
getJsxElementAttributesType,
getJsxIntrinsicTagNames,
@@ -143,6 +146,7 @@ namespace ts {
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
@@ -1024,8 +1028,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 {
@@ -1192,6 +1196,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;
@@ -1227,6 +1232,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);
@@ -3348,7 +3354,13 @@ namespace ts {
// Otherwise, fall back to 'any'.
else {
if (compilerOptions.noImplicitAny) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
if (setter) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
}
else {
Debug.assert(!!getter, "there must existed getter as we are current checking either setter or getter in this function");
error(getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
}
}
type = anyType;
}
@@ -5374,7 +5386,7 @@ namespace ts {
while (i > 0) {
i--;
if (isSubtypeOfAny(types[i], types)) {
types.splice(i, 1);
orderedRemoveItemAt(types, i);
}
}
}
@@ -8758,7 +8770,7 @@ namespace ts {
// The location isn't a reference to the given symbol, meaning we're being asked
// a hypothetical question of what type the symbol would have if there was a reference
// to it at the given location. Since we have no control flow information for the
// hypotherical reference (control flow information is created and attached by the
// hypothetical reference (control flow information is created and attached by the
// binder), we simply return the declared type of the symbol.
return getTypeOfSymbol(symbol);
}
@@ -11997,18 +12009,12 @@ namespace ts {
// Function interface, since they have none by default. This is a bit of a leap of faith
// that the user will not add any.
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
// TS 1.0 spec: 4.12
// If FuncExpr is of type Any, or of an object type that has no call or construct signatures
// but is a subtype of the Function interface, the call is an untyped function call. In an
// untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
// TS 1.0 Spec: 4.12
// In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
// types are provided for the argument expressions, and the result is always of type Any.
// We exclude union types because we may have a union of function types that happen to have
// no common signatures.
if (isTypeAny(funcType) ||
(isTypeAny(apparentType) && funcType.flags & TypeFlags.TypeParameter) ||
(!callSignatures.length && !constructSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
// The unknownType indicates that an error already occurred (and was reported). No
// need to report another error in this case.
if (funcType !== unknownType && node.typeArguments) {
@@ -12031,6 +12037,29 @@ namespace ts {
return resolveCall(node, callSignatures, candidatesOutArray);
}
/**
* TS 1.0 spec: 4.12
* If FuncExpr is of type Any, or of an object type that has no call or construct signatures
* but is a subtype of the Function interface, the call is an untyped function call.
*/
function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number) {
if (isTypeAny(funcType)) {
return true;
}
if (isTypeAny(apparentFuncType) && funcType.flags & TypeFlags.TypeParameter) {
return true;
}
if (!numCallSignatures && !numConstructSignatures) {
// We exclude union types because we may have a union of function types that happen to have
// no common signatures.
if (funcType.flags & TypeFlags.Union) {
return false;
}
return isTypeAssignableTo(funcType, globalFunctionType);
}
return false;
}
function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature {
if (node.arguments && languageVersion < ScriptTarget.ES5) {
const spreadIndex = getSpreadArgumentIndex(node.arguments);
@@ -12156,8 +12185,9 @@ namespace ts {
}
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
if (isTypeAny(tagType) || (!callSignatures.length && !(tagType.flags & TypeFlags.Union) && isTypeAssignableTo(tagType, globalFunctionType))) {
if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, constructSignatures.length)) {
return resolveUntypedCall(node);
}
@@ -12202,7 +12232,8 @@ namespace ts {
}
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
if (funcType === anyType || (!callSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
return resolveUntypedCall(node);
}
@@ -12241,10 +12272,10 @@ namespace ts {
// or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
// to correctly fill the candidatesOutArray.
const cached = links.resolvedSignature;
if (cached && cached !== anySignature && !candidatesOutArray) {
if (cached && cached !== resolvingSignature && !candidatesOutArray) {
return cached;
}
links.resolvedSignature = anySignature;
links.resolvedSignature = resolvingSignature;
const result = resolveSignature(node, candidatesOutArray);
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
@@ -12256,7 +12287,7 @@ namespace ts {
function getResolvedOrAnySignature(node: CallLikeExpression) {
// If we're already in the process of resolving the given signature, don't resolve again as
// that could cause infinite recursion. Instead, return anySignature.
return getNodeLinks(node).resolvedSignature === anySignature ? anySignature : getResolvedSignature(node);
return getNodeLinks(node).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(node);
}
function getInferredClassType(symbol: Symbol) {
@@ -18889,7 +18920,13 @@ namespace ts {
(augmentations || (augmentations = [])).push(file.moduleAugmentations);
}
if (file.symbol && file.symbol.globalExports) {
mergeSymbolTable(globals, file.symbol.globalExports);
// Merge in UMD exports with first-in-wins semantics (see #9771)
const source = file.symbol.globalExports;
for (const id in source) {
if (!(id in globals)) {
globals[id] = source[id];
}
}
}
if ((compilerOptions.isolatedModules || isExternalModule(file)) && !file.isDeclarationFile) {
const fileRequestedExternalEmitHelpers = file.flags & NodeFlags.EmitHelperFlags;
@@ -20165,5 +20202,15 @@ namespace ts {
return true;
}
}
function getAmbientModules(): Symbol[] {
const result: Symbol[] = [];
for (const sym in globals) {
if (ambientModuleSymbolRegex.test(sym)) {
result.push(globals[sym]);
}
}
return result;
}
}
}
+6 -7
View File
@@ -858,14 +858,13 @@ namespace ts {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
}
else {
// By default, exclude common package folders
// By default, exclude common package folders and the outDir
excludeSpecs = ["node_modules", "bower_components", "jspm_packages"];
}
// Always exclude the output directory unless explicitly included
const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"];
if (outDir) {
excludeSpecs.push(outDir);
const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"];
if (outDir) {
excludeSpecs.push(outDir);
}
}
if (fileNames === undefined && includeSpecs === undefined) {
@@ -891,7 +890,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;
}
+63 -10
View File
@@ -199,6 +199,10 @@ namespace ts {
return count;
}
/**
* Filters an array by a predicate function. Returns the same array instance if the predicate is
* true for all elements, otherwise returns a new array instance containing the filtered subset.
*/
export function filter<T, U extends T>(array: T[], f: (x: T) => x is U): U[];
export function filter<T>(array: T[], f: (x: T) => boolean): T[]
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
@@ -746,6 +750,36 @@ namespace ts {
return result;
}
/**
* Adds the value to an array of values associated with the key, and returns the array.
* Creates the array if it does not already exist.
*/
export function multiMapAdd<V>(map: Map<V[]>, key: string, value: V): V[] {
const values = map[key];
if (values) {
values.push(value);
return values;
}
else {
return map[key] = [value];
}
}
/**
* Removes a value from an array of values associated with the key.
* Does not preserve the order of those values.
* Does nothing if `key` is not in `map`, or `value` is not in `map[key]`.
*/
export function multiMapRemove<V>(map: Map<V[]>, key: string, value: V): void {
const values = map[key];
if (values) {
unorderedRemoveItem(values, value);
if (!values.length) {
delete map[key];
}
}
}
/**
* Tests whether a value is an array.
*/
@@ -1717,20 +1751,39 @@ namespace ts {
return "";
}
export function copyListRemovingItem<T>(item: T, list: T[]) {
const copiedList: T[] = [];
for (const e of list) {
if (e !== item) {
copiedList.push(e);
}
/** Remove an item from an array, moving everything to its right one space left. */
export function orderedRemoveItemAt<T>(array: T[], index: number): void {
// This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`.
for (let i = index; i < array.length - 1; i++) {
array[i] = array[i + 1];
}
return copiedList;
array.pop();
}
export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string {
return useCaseSensitivefileNames
export function unorderedRemoveItemAt<T>(array: T[], index: number): void {
// Fill in the "hole" left at `index`.
array[index] = array[array.length - 1];
array.pop();
}
/** Remove the *first* occurrence of `item` from the array. */
export function unorderedRemoveItem<T>(array: T[], item: T): void {
unorderedRemoveFirstItemWhere(array, element => element === item);
}
/** Remove the *first* element satisfying `predicate`. */
function unorderedRemoveFirstItemWhere<T>(array: T[], predicate: (element: T) => boolean): void {
for (let i = 0; i < array.length; i++) {
if (predicate(array[i])) {
unorderedRemoveItemAt(array, i);
break;
}
}
}
export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): (fileName: string) => string {
return useCaseSensitiveFileNames
? ((fileName) => fileName)
: ((fileName) => fileName.toLowerCase());
}
}
+4 -2
View File
@@ -1133,8 +1133,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) {
+9 -5
View File
@@ -2871,11 +2871,7 @@
"Element implicitly has an 'any' type because index expression is not of type 'number'.": {
"category": "Error",
"code": 7015
},
"Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation.": {
"category": "Error",
"code": 7016
},
},
"Index signature of object type implicitly has an 'any' type.": {
"category": "Error",
"code": 7017
@@ -2932,6 +2928,14 @@
"category": "Error",
"code": 7031
},
"Property '{0}' implicitly has type 'any', because its set accessor lacks a parameter type annotation.": {
"category": "Error",
"code": 7032
},
"Property '{0}' implicitly has type 'any', because its get accessor lacks a return type annotation.": {
"category": "Error",
"code": 7033
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000
+1
View File
@@ -2338,6 +2338,7 @@ namespace ts {
token() === SyntaxKind.LessThanToken ||
token() === SyntaxKind.QuestionToken ||
token() === SyntaxKind.ColonToken ||
token() === SyntaxKind.CommaToken ||
canParseSemicolon();
}
return false;
+34 -10
View File
@@ -8,11 +8,9 @@ namespace ts {
const emptyArray: any[] = [];
const defaultTypeRoots = ["node_modules/@types"];
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string {
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string {
while (true) {
const fileName = combinePaths(searchPath, "tsconfig.json");
const fileName = combinePaths(searchPath, configName);
if (fileExists(fileName)) {
return fileName;
}
@@ -168,7 +166,7 @@ namespace ts {
const typeReferenceExtensions = [".d.ts"];
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
export function getEffectiveTypeRoots(options: CompilerOptions, host: { directoryExists?: (directoryName: string) => boolean, getCurrentDirectory?: () => string }): string[] | undefined {
if (options.typeRoots) {
return options.typeRoots;
}
@@ -181,12 +179,38 @@ namespace ts {
currentDirectory = host.getCurrentDirectory();
}
if (!currentDirectory) {
return undefined;
}
return map(defaultTypeRoots, d => combinePaths(currentDirectory, d));
return currentDirectory && getDefaultTypeRoots(currentDirectory, host);
}
/**
* Returns the path to every node_modules/@types directory from some ancestor directory.
* Returns undefined if there are none.
*/
function getDefaultTypeRoots(currentDirectory: string, host: { directoryExists?: (directoryName: string) => boolean }): string[] | undefined {
if (!host.directoryExists) {
return [combinePaths(currentDirectory, nodeModulesAtTypes)];
// And if it doesn't exist, tough.
}
let typeRoots: string[];
while (true) {
const atTypes = combinePaths(currentDirectory, nodeModulesAtTypes);
if (host.directoryExists(atTypes)) {
(typeRoots || (typeRoots = [])).push(atTypes);
}
const parent = getDirectoryPath(currentDirectory);
if (parent === currentDirectory) {
break;
}
currentDirectory = parent;
}
return typeRoots;
}
const nodeModulesAtTypes = combinePaths("node_modules", "@types");
/**
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown.
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups
@@ -1102,7 +1126,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
+2 -11
View File
@@ -273,7 +273,7 @@ namespace ts {
}
function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void {
(fileWatcherCallbacks[filePath] || (fileWatcherCallbacks[filePath] = [])).push(callback);
multiMapAdd(fileWatcherCallbacks, filePath, callback);
}
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
@@ -289,16 +289,7 @@ namespace ts {
}
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
const callbacks = fileWatcherCallbacks[filePath];
if (callbacks) {
const newCallbacks = copyListRemovingItem(callback, callbacks);
if (newCallbacks.length === 0) {
delete fileWatcherCallbacks[filePath];
}
else {
fileWatcherCallbacks[filePath] = newCallbacks;
}
}
multiMapRemove(fileWatcherCallbacks, filePath, callback);
}
function fileEventHandler(eventName: string, relativeFileName: string, baseDirPath: string) {
+1 -4
View File
@@ -482,10 +482,7 @@ namespace ts {
sourceFile.fileWatcher.close();
sourceFile.fileWatcher = undefined;
if (removed) {
const index = rootFileNames.indexOf(sourceFile.fileName);
if (index >= 0) {
rootFileNames.splice(index, 1);
}
unorderedRemoveItem(rootFileNames, sourceFile.fileName);
}
startTimerForRecompilation();
}
+4 -1
View File
@@ -435,6 +435,8 @@ namespace ts {
TypeExcludesFlags = YieldContext | AwaitContext,
}
export type ModifiersArray = NodeArray<Modifier>;
export const enum ModifierFlags {
None = 0,
Export = 1 << 0, // Declarations
@@ -480,7 +482,7 @@ namespace ts {
/* @internal */ modifierFlagsCache?: ModifierFlags;
/* @internal */ transformFlags?: TransformFlags;
decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
modifiers?: NodeArray<Modifier>; // Array of modifiers
modifiers?: ModifiersArray; // Array of modifiers
/* @internal */ id?: number; // Unique id (used to look up NodeLinks)
parent?: Node; // Parent node (initialized by binding)
/* @internal */ original?: Node; // The original node if this is an updated node.
@@ -1965,6 +1967,7 @@ namespace ts {
getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
getJsxIntrinsicTagNames(): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
// Should not be called directly. Should only be accessed through the Program instance.
/* @internal */ getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[];
+76 -57
View File
@@ -596,60 +596,6 @@ namespace ts {
return node.kind === SyntaxKind.EnumDeclaration && isConst(node);
}
function walkUpBindingElementsAndPatterns(node: Node): Node {
while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
node = node.parent;
}
return node;
}
export function getCombinedModifierFlags(node: Node): ModifierFlags {
node = walkUpBindingElementsAndPatterns(node);
let flags = getModifierFlags(node);
if (node.kind === SyntaxKind.VariableDeclaration) {
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
flags |= getModifierFlags(node);
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableStatement) {
flags |= getModifierFlags(node);
}
return flags;
}
// Returns the node flags for this node and all relevant parent nodes. This is done so that
// nodes like variable declarations and binding elements can returned a view of their flags
// that includes the modifiers from their container. i.e. flags like export/declare aren't
// stored on the variable declaration directly, but on the containing variable statement
// (if it has one). Similarly, flags for let/const are store on the variable declaration
// list. By calling this function, all those flags are combined so that the client can treat
// the node as if it actually had those flags.
export function getCombinedNodeFlags(node: Node): NodeFlags {
node = walkUpBindingElementsAndPatterns(node);
let flags = node.flags;
if (node.kind === SyntaxKind.VariableDeclaration) {
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
flags |= node.flags;
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableStatement) {
flags |= node.flags;
}
return flags;
}
export function isConst(node: Node): boolean {
return !!(getCombinedNodeFlags(node) & NodeFlags.Const)
|| !!(getCombinedModifierFlags(node) & ModifierFlags.Const);
@@ -1120,6 +1066,18 @@ namespace ts {
return undefined;
}
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
switch (node.kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.Decorator:
return true;
default:
return false;
}
}
export function getInvokedExpression(node: CallLikeExpression): Expression {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
return (<TaggedTemplateExpression>node).tag;
@@ -3022,10 +2980,13 @@ namespace ts {
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
}
export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionWithTypeArguments &&
/** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */
export function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined {
if (node.kind === SyntaxKind.ExpressionWithTypeArguments &&
(<HeritageClause>node.parent).token === SyntaxKind.ExtendsKeyword &&
isClassLike(node.parent.parent);
isClassLike(node.parent.parent)) {
return node.parent.parent;
}
}
export function isDestructuringAssignment(node: Node): node is BinaryExpression {
@@ -3058,6 +3019,10 @@ namespace ts {
}
}
export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean {
return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined;
}
export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
return node.kind === SyntaxKind.Identifier ||
node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
@@ -4351,4 +4316,58 @@ namespace ts {
export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean {
return hasModifier(node, ModifierFlags.ParameterPropertyModifier) && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent);
}
function walkUpBindingElementsAndPatterns(node: Node): Node {
while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
node = node.parent;
}
return node;
}
export function getCombinedModifierFlags(node: Node): ModifierFlags {
node = walkUpBindingElementsAndPatterns(node);
let flags = getModifierFlags(node);
if (node.kind === SyntaxKind.VariableDeclaration) {
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
flags |= getModifierFlags(node);
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableStatement) {
flags |= getModifierFlags(node);
}
return flags;
}
// Returns the node flags for this node and all relevant parent nodes. This is done so that
// nodes like variable declarations and binding elements can returned a view of their flags
// that includes the modifiers from their container. i.e. flags like export/declare aren't
// stored on the variable declaration directly, but on the containing variable statement
// (if it has one). Similarly, flags for let/const are store on the variable declaration
// list. By calling this function, all those flags are combined so that the client can treat
// the node as if it actually had those flags.
export function getCombinedNodeFlags(node: Node): NodeFlags {
node = walkUpBindingElementsAndPatterns(node);
let flags = node.flags;
if (node.kind === SyntaxKind.VariableDeclaration) {
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
flags |= node.flags;
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableStatement) {
flags |= node.flags;
}
return flags;
}
}
+216 -112
View File
@@ -206,6 +206,24 @@ namespace FourSlash {
private inputFiles = ts.createMap<string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) {
let result = "";
ts.forEach(displayParts, part => {
if (result) {
result += ",\n ";
}
else {
result = "[\n ";
}
result += JSON.stringify(part);
});
if (result) {
result += "\n]";
}
return result;
}
// Add input file which has matched file name with the given reference-file path.
// This is necessary when resolveReference flag is specified
private addMatchedInputFile(referenceFilePath: string, extensions: string[]) {
@@ -245,22 +263,31 @@ namespace FourSlash {
constructor(private basePath: string, private testType: FourSlashTestType, public testData: FourSlashData) {
// Create a new Services Adapter
this.cancellationToken = new TestCancellationToken();
const compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions);
if (compilationOptions.typeRoots) {
compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => ts.getNormalizedAbsolutePath(p, this.basePath));
}
let compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions);
compilationOptions.skipDefaultLibCheck = true;
const languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions);
this.languageServiceAdapterHost = languageServiceAdapter.getHost();
this.languageService = languageServiceAdapter.getLanguageService();
// Initialize the language service with all the scripts
let startResolveFileRef: FourSlashFile;
ts.forEach(testData.files, file => {
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
this.inputFiles[file.fileName] = file.content;
if (ts.getBaseFileName(file.fileName).toLowerCase() === "tsconfig.json") {
const configJson = ts.parseConfigFileTextToJson(file.fileName, file.content);
assert.isTrue(configJson.config !== undefined);
// Extend our existing compiler options so that we can also support tsconfig only options
if (configJson.config.compilerOptions) {
const baseDirectory = ts.normalizePath(ts.getDirectoryPath(file.fileName));
const tsConfig = ts.convertCompilerOptionsFromJson(configJson.config.compilerOptions, baseDirectory, file.fileName);
if (!tsConfig.errors || !tsConfig.errors.length) {
compilationOptions = ts.extend(compilationOptions, tsConfig.options);
}
}
}
if (!startResolveFileRef && file.fileOptions[metadataOptionNames.resolveReference] === "true") {
startResolveFileRef = file;
}
@@ -270,6 +297,15 @@ namespace FourSlash {
}
});
if (compilationOptions.typeRoots) {
compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => ts.getNormalizedAbsolutePath(p, this.basePath));
}
const languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions);
this.languageServiceAdapterHost = languageServiceAdapter.getHost();
this.languageService = languageServiceAdapter.getLanguageService();
if (startResolveFileRef) {
// Add the entry-point file itself into the languageServiceShimHost
this.languageServiceAdapterHost.addScript(startResolveFileRef.fileName, startResolveFileRef.content, /*isRootFile*/ true);
@@ -324,6 +360,7 @@ namespace FourSlash {
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
PlaceOpenBraceOnNewLineForFunctions: false,
@@ -507,6 +544,67 @@ namespace FourSlash {
}
}
public verifyGoToDefinitionIs(endMarker: string | string[]) {
this.verifyGoToDefinitionWorker(endMarker instanceof Array ? endMarker : [endMarker]);
}
public verifyGoToDefinition(arg0: any, endMarkerNames?: string | string[]) {
if (endMarkerNames) {
this.verifyGoToDefinitionPlain(arg0, endMarkerNames);
}
else if (arg0 instanceof Array) {
const pairs: [string | string[], string | string[]][] = arg0;
for (const [start, end] of pairs) {
this.verifyGoToDefinitionPlain(start, end);
}
}
else {
const obj: { [startMarkerName: string]: string | string[] } = arg0;
for (const startMarkerName in obj) {
if (ts.hasProperty(obj, startMarkerName)) {
this.verifyGoToDefinitionPlain(startMarkerName, obj[startMarkerName]);
}
}
}
}
private verifyGoToDefinitionPlain(startMarkerNames: string | string[], endMarkerNames: string | string[]) {
if (startMarkerNames instanceof Array) {
for (const start of startMarkerNames) {
this.verifyGoToDefinitionSingle(start, endMarkerNames);
}
}
else {
this.verifyGoToDefinitionSingle(startMarkerNames, endMarkerNames);
}
}
public verifyGoToDefinitionForMarkers(markerNames: string[]) {
for (const markerName of markerNames) {
this.verifyGoToDefinitionSingle(`${markerName}Reference`, `${markerName}Definition`);
}
}
private verifyGoToDefinitionSingle(startMarkerName: string, endMarkerNames: string | string[]) {
this.goToMarker(startMarkerName);
this.verifyGoToDefinitionWorker(endMarkerNames instanceof Array ? endMarkerNames : [endMarkerNames]);
}
private verifyGoToDefinitionWorker(endMarkers: string[]) {
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition) || [];
if (endMarkers.length !== definitions.length) {
this.raiseError(`goToDefinitions failed - expected to find ${endMarkers.length} definitions but got ${definitions.length}`);
}
for (let i = 0; i < endMarkers.length; i++) {
const marker = this.getMarkerByName(endMarkers[i]), definition = definitions[i];
if (marker.fileName !== definition.fileName || marker.position !== definition.textSpan.start) {
this.raiseError(`goToDefinition failed for definition ${i}: expected ${marker.fileName} at ${marker.position}, got ${definition.fileName} at ${definition.textSpan.start}`);
}
}
}
public verifyGetEmitOutputForCurrentFile(expected: string): void {
const emit = this.languageService.getEmitOutput(this.activeFile.fileName);
if (emit.outputFiles.length !== 1) {
@@ -651,10 +749,10 @@ namespace FourSlash {
}
}
public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number) {
const completions = this.getCompletionListAtCaret();
if (completions) {
this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind);
this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind, spanIndex);
}
else {
this.raiseError(`No completions at position '${this.currentCaretPosition}' when looking for '${symbol}'.`);
@@ -670,25 +768,32 @@ namespace FourSlash {
* @param expectedText the text associated with the symbol
* @param expectedDocumentation the documentation text associated with the symbol
* @param expectedKind the kind of symbol (see ScriptElementKind)
* @param spanIndex the index of the range that the completion item's replacement text span should match
*/
public verifyCompletionListDoesNotContain(symbol: string, expectedText?: string, expectedDocumentation?: string, expectedKind?: string) {
public verifyCompletionListDoesNotContain(symbol: string, expectedText?: string, expectedDocumentation?: string, expectedKind?: string, spanIndex?: number) {
const that = this;
let replacementSpan: ts.TextSpan;
if (spanIndex !== undefined) {
replacementSpan = this.getTextSpanForRangeAtIndex(spanIndex);
}
function filterByTextOrDocumentation(entry: ts.CompletionEntry) {
const details = that.getCompletionEntryDetails(entry.name);
const documentation = ts.displayPartsToString(details.documentation);
const text = ts.displayPartsToString(details.displayParts);
if (expectedText && expectedDocumentation) {
return (documentation === expectedDocumentation && text === expectedText) ? true : false;
// If any of the expected values are undefined, assume that users don't
// care about them.
if (replacementSpan && !TestState.textSpansEqual(replacementSpan, entry.replacementSpan)) {
return false;
}
else if (expectedText && !expectedDocumentation) {
return text === expectedText ? true : false;
else if (expectedText && text !== expectedText) {
return false;
}
else if (expectedDocumentation && !expectedText) {
return documentation === expectedDocumentation ? true : false;
else if (expectedDocumentation && documentation !== expectedDocumentation) {
return false;
}
// Because expectedText and expectedDocumentation are undefined, we assume that
// users don"t care to compare them so we will treat that entry as if the entry has matching text and documentation
// and keep it in the list of filtered entry.
return true;
}
@@ -712,6 +817,10 @@ namespace FourSlash {
if (expectedKind) {
error += "Expected kind: " + expectedKind + " to equal: " + filterCompletions[0].kind + ".";
}
if (replacementSpan) {
const spanText = filterCompletions[0].replacementSpan ? stringify(filterCompletions[0].replacementSpan) : undefined;
error += "Expected replacement span: " + stringify(replacementSpan) + " to equal: " + spanText + ".";
}
this.raiseError(error);
}
}
@@ -777,6 +886,20 @@ namespace FourSlash {
ts.forEachProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
}
public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) {
const referencedSymbols = this.findReferencesAtCaret();
if (referencedSymbols.length === 0) {
this.raiseError("No referenced symbols found at current caret position");
}
else if (referencedSymbols.length > 1) {
this.raiseError("More than one referenced symbol found");
}
assert.equal(TestState.getDisplayPartsJson(referencedSymbols[0].definition.displayParts),
TestState.getDisplayPartsJson(expected), this.messageAtLastKnownMarker("referenced symbol definition display parts"));
}
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
for (let i = 0; i < references.length; i++) {
const reference = references[i];
@@ -811,6 +934,10 @@ namespace FourSlash {
return this.languageService.getReferencesAtPosition(this.activeFile.fileName, this.currentCaretPosition);
}
private findReferencesAtCaret() {
return this.languageService.findReferences(this.activeFile.fileName, this.currentCaretPosition);
}
public getSyntacticDiagnostics(expected: string) {
const diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
this.testDiagnostics(expected, diagnostics);
@@ -856,30 +983,12 @@ namespace FourSlash {
displayParts: ts.SymbolDisplayPart[],
documentation: ts.SymbolDisplayPart[]) {
function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) {
let result = "";
ts.forEach(displayParts, part => {
if (result) {
result += ",\n ";
}
else {
result = "[\n ";
}
result += JSON.stringify(part);
});
if (result) {
result += "\n]";
}
return result;
}
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind"));
assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers"));
assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan"));
assert.equal(getDisplayPartsJson(actualQuickInfo.displayParts), getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts"));
assert.equal(getDisplayPartsJson(actualQuickInfo.documentation), getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation"));
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts"));
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation"));
}
public verifyRenameLocations(findInStrings: boolean, findInComments: boolean, ranges?: Range[]) {
@@ -1543,25 +1652,10 @@ namespace FourSlash {
this.goToPosition(len);
}
public goToDefinition(definitionIndex: number) {
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
if (!definitions || !definitions.length) {
this.raiseError("goToDefinition failed - expected to at least one definition location but got 0");
}
if (definitionIndex >= definitions.length) {
this.raiseError(`goToDefinition failed - definitionIndex value (${definitionIndex}) exceeds definition list size (${definitions.length})`);
}
const definition = definitions[definitionIndex];
this.openFile(definition.fileName);
this.currentCaretPosition = definition.textSpan.start;
}
public goToTypeDefinition(definitionIndex: number) {
const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
if (!definitions || !definitions.length) {
this.raiseError("goToTypeDefinition failed - expected to at least one definition location but got 0");
this.raiseError("goToTypeDefinition failed - expected to find at least one definition location but got 0");
}
if (definitionIndex >= definitions.length) {
@@ -1573,28 +1667,6 @@ namespace FourSlash {
this.currentCaretPosition = definition.textSpan.start;
}
public verifyDefinitionLocationExists(negative: boolean) {
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const foundDefinitions = definitions && definitions.length;
if (foundDefinitions && negative) {
this.raiseError(`goToDefinition - expected to 0 definition locations but got ${definitions.length}`);
}
else if (!foundDefinitions && !negative) {
this.raiseError("goToDefinition - expected to at least one definition location but got 0");
}
}
public verifyDefinitionsCount(negative: boolean, expectedCount: number) {
const assertFn = negative ? assert.notEqual : assert.equal;
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const actualCount = definitions && definitions.length || 0;
assertFn(actualCount, expectedCount, this.messageAtLastKnownMarker("Definitions Count"));
}
public verifyTypeDefinitionsCount(negative: boolean, expectedCount: number) {
const assertFn = negative ? assert.notEqual : assert.equal;
@@ -1604,18 +1676,12 @@ namespace FourSlash {
assertFn(actualCount, expectedCount, this.messageAtLastKnownMarker("Type definitions Count"));
}
public verifyDefinitionsName(negative: boolean, expectedName: string, expectedContainerName: string) {
public verifyGoToDefinitionName(expectedName: string, expectedContainerName: string) {
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const actualDefinitionName = definitions && definitions.length ? definitions[0].name : "";
const actualDefinitionContainerName = definitions && definitions.length ? definitions[0].containerName : "";
if (negative) {
assert.notEqual(actualDefinitionName, expectedName, this.messageAtLastKnownMarker("Definition Info Name"));
assert.notEqual(actualDefinitionContainerName, expectedContainerName, this.messageAtLastKnownMarker("Definition Info Container Name"));
}
else {
assert.equal(actualDefinitionName, expectedName, this.messageAtLastKnownMarker("Definition Info Name"));
assert.equal(actualDefinitionContainerName, expectedContainerName, this.messageAtLastKnownMarker("Definition Info Container Name"));
}
assert.equal(actualDefinitionName, expectedName, this.messageAtLastKnownMarker("Definition Info Name"));
assert.equal(actualDefinitionContainerName, expectedContainerName, this.messageAtLastKnownMarker("Definition Info Container Name"));
}
public getMarkers(): Marker[] {
@@ -1623,6 +1689,10 @@ namespace FourSlash {
return this.testData.markers.slice(0);
}
public getMarkerNames(): string[] {
return Object.keys(this.testData.markerPositions);
}
public getRanges(): Range[] {
return this.testData.ranges;
}
@@ -1631,8 +1701,7 @@ namespace FourSlash {
const result = ts.createMap<Range[]>();
for (const range of this.getRanges()) {
const text = this.rangeText(range);
const ranges = result[text] || (result[text] = []);
ranges.push(range);
ts.multiMapAdd(result, text, range);
}
return result;
}
@@ -2149,7 +2218,7 @@ namespace FourSlash {
return text.substring(startPos, endPos);
}
private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string) {
private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string, spanIndex?: number) {
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.name === name) {
@@ -2168,6 +2237,11 @@ namespace FourSlash {
assert.equal(item.kind, kind, this.assertionMessageAtLastKnownMarker("completion item kind for " + name));
}
if (spanIndex !== undefined) {
const span = this.getTextSpanForRangeAtIndex(spanIndex);
assert.isTrue(TestState.textSpansEqual(span, item.replacementSpan), this.assertionMessageAtLastKnownMarker(stringify(span) + " does not equal " + stringify(item.replacementSpan) + " replacement span for " + name));
}
return;
}
}
@@ -2224,6 +2298,17 @@ namespace FourSlash {
return `line ${(pos.line + 1)}, col ${pos.character}`;
}
private getTextSpanForRangeAtIndex(index: number): ts.TextSpan {
const ranges = this.getRanges();
if (ranges && ranges.length > index) {
const range = ranges[index];
return { start: range.start, length: range.end - range.start };
}
else {
this.raiseError("Supplied span index: " + index + " does not exist in range list of size: " + (ranges ? 0 : ranges.length));
}
}
public getMarkerByName(markerName: string) {
const markerPos = this.testData.markerPositions[markerName];
if (markerPos === undefined) {
@@ -2247,6 +2332,10 @@ namespace FourSlash {
public resetCancelled(): void {
this.cancellationToken.resetCancelled();
}
private static textSpansEqual(a: ts.TextSpan, b: ts.TextSpan) {
return a && b && a.start === b.start && a.length === b.length;
}
}
export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) {
@@ -2255,12 +2344,16 @@ namespace FourSlash {
}
export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void {
// Give file paths an absolute path for the virtual file system
const absoluteBasePath = ts.combinePaths(Harness.virtualFileSystemRoot, basePath);
const absoluteFileName = ts.combinePaths(Harness.virtualFileSystemRoot, fileName);
// Parse out the files and their metadata
const testData = parseTestData(basePath, content, fileName);
const state = new TestState(basePath, testType, testData);
const testData = parseTestData(absoluteBasePath, content, absoluteFileName);
const state = new TestState(absoluteBasePath, testType, testData);
const output = ts.transpileModule(content, { reportDiagnostics: true });
if (output.diagnostics.length > 0) {
throw new Error(`Syntax error in ${basePath}: ${output.diagnostics[0].messageText}`);
throw new Error(`Syntax error in ${absoluteBasePath}: ${output.diagnostics[0].messageText}`);
}
runCode(output.outputText, state);
}
@@ -2725,6 +2818,10 @@ namespace FourSlashInterface {
return this.state.getMarkers();
}
public markerNames(): string[] {
return this.state.getMarkerNames();
}
public marker(name?: string): FourSlash.Marker {
return this.state.getMarkerByName(name);
}
@@ -2760,10 +2857,6 @@ namespace FourSlashInterface {
this.state.goToEOF();
}
public definition(definitionIndex = 0) {
this.state.goToDefinition(definitionIndex);
}
public type(definitionIndex = 0) {
this.state.goToTypeDefinition(definitionIndex);
}
@@ -2813,12 +2906,12 @@ namespace FourSlashInterface {
// Verifies the completion list contains the specified symbol. The
// completion list is brought up if necessary
public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number) {
if (this.negative) {
this.state.verifyCompletionListDoesNotContain(symbol, text, documentation, kind);
this.state.verifyCompletionListDoesNotContain(symbol, text, documentation, kind, spanIndex);
}
else {
this.state.verifyCompletionListContains(symbol, text, documentation, kind);
this.state.verifyCompletionListContains(symbol, text, documentation, kind, spanIndex);
}
}
@@ -2868,22 +2961,10 @@ namespace FourSlashInterface {
this.state.verifyQuickInfoExists(this.negative);
}
public definitionCountIs(expectedCount: number) {
this.state.verifyDefinitionsCount(this.negative, expectedCount);
}
public typeDefinitionCountIs(expectedCount: number) {
this.state.verifyTypeDefinitionsCount(this.negative, expectedCount);
}
public definitionLocationExists() {
this.state.verifyDefinitionLocationExists(this.negative);
}
public verifyDefinitionsName(name: string, containerName: string) {
this.state.verifyDefinitionsName(this.negative, name, containerName);
}
public isValidBraceCompletionAtPosition(openingBrace: string) {
this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace);
}
@@ -2927,6 +3008,25 @@ namespace FourSlashInterface {
this.state.verifyCurrentFileContent(text);
}
public goToDefinitionIs(endMarkers: string | string[]) {
this.state.verifyGoToDefinitionIs(endMarkers);
}
public goToDefinition(startMarkerName: string | string[], endMarkerName: string | string[]): void;
public goToDefinition(startsAndEnds: [string | string[], string | string[]][]): void;
public goToDefinition(startsAndEnds: { [startMarkerName: string]: string | string[] }): void;
public goToDefinition(arg0: any, endMarkerName?: string | string[]) {
this.state.verifyGoToDefinition(arg0, endMarkerName);
}
public goToDefinitionForMarkers(...markerNames: string[]) {
this.state.verifyGoToDefinitionForMarkers(markerNames);
}
public goToDefinitionName(name: string, containerName: string) {
this.state.verifyGoToDefinitionName(name, containerName);
}
public verifyGetEmitOutputForCurrentFile(expected: string): void {
this.state.verifyGetEmitOutputForCurrentFile(expected);
}
@@ -2947,6 +3047,10 @@ namespace FourSlashInterface {
this.state.verifyRangesReferenceEachOther(ranges);
}
public findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]) {
this.state.verifyDisplayPartsOfReferencedSymbol(expected);
}
public rangesWithSameTextReferenceEachOther() {
this.state.verifyRangesWithSameTextReferenceEachOther();
}
+23 -8
View File
@@ -514,6 +514,9 @@ namespace Harness {
// harness always uses one kind of new line
const harnessNewLine = "\r\n";
// Root for file paths that are stored in a virtual file system
export const virtualFileSystemRoot = "/";
namespace IOImpl {
declare class Enumerator {
public atEnd(): boolean;
@@ -1444,23 +1447,31 @@ namespace Harness {
// Produce baselines. The first gives the types for all expressions.
// The second gives symbols for all identifiers.
let e1: Error, e2: Error;
let typesError: Error, symbolsError: Error;
try {
checkBaseLines(/*isSymbolBaseLine*/ false);
}
catch (e) {
e1 = e;
typesError = e;
}
try {
checkBaseLines(/*isSymbolBaseLine*/ true);
}
catch (e) {
e2 = e;
symbolsError = e;
}
if (e1 || e2) {
throw e1 || e2;
if (typesError && symbolsError) {
throw new Error(typesError.message + ts.sys.newLine + symbolsError.message);
}
if (typesError) {
throw typesError;
}
if (symbolsError) {
throw symbolsError;
}
return;
@@ -1470,7 +1481,12 @@ namespace Harness {
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, fullExtension), () => fullBaseLine, opts);
// When calling this function from rwc-runner, the baselinePath will have no extension.
// As rwc test- file is stored in json which ".json" will get stripped off.
// When calling this function from compiler-runner, the baselinePath will then has either ".ts" or ".tsx" extension
const outputFileName = ts.endsWith(baselinePath, ".ts") || ts.endsWith(baselinePath, ".tsx") ?
baselinePath.replace(/\.tsx?/, fullExtension) : baselinePath.concat(fullExtension);
Harness.Baseline.runBaseline(outputFileName, () => fullBaseLine, opts);
}
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
@@ -1846,7 +1862,7 @@ namespace Harness {
tsConfig.options.configFilePath = data.name;
// delete entry from the list
testUnitData.splice(i, 1);
ts.orderedRemoveItemAt(testUnitData, i);
break;
}
@@ -1967,7 +1983,6 @@ namespace Harness {
export function runBaseline(relativeFileName: string, generateContent: () => string, opts?: BaselineOptions): void {
const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
const actual = generateActual(generateContent);
const comparison = compareToBaseline(actual, relativeFileName, opts);
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName);
+32 -8
View File
@@ -123,7 +123,7 @@ namespace Harness.LanguageService {
}
export class LanguageServiceAdapterHost {
protected fileNameToScript = ts.createMap<ScriptInfo>();
protected virtualFileSystem: Utils.VirtualFileSystem = new Utils.VirtualFileSystem(virtualFileSystemRoot, /*useCaseSensitiveFilenames*/false);
constructor(protected cancellationToken = DefaultHostCancellationToken.Instance,
protected settings = ts.getDefaultCompilerOptions()) {
@@ -135,22 +135,24 @@ namespace Harness.LanguageService {
public getFilenames(): string[] {
const fileNames: string[] = [];
ts.forEachProperty(this.fileNameToScript, (scriptInfo) => {
for (const virtualEntry of this.virtualFileSystem.getAllFileEntries()){
const scriptInfo = virtualEntry.content;
if (scriptInfo.isRootFile) {
// only include root files here
// usually it means that we won't include lib.d.ts in the list of root files so it won't mess the computation of compilation root dir.
fileNames.push(scriptInfo.fileName);
}
});
}
return fileNames;
}
public getScriptInfo(fileName: string): ScriptInfo {
return this.fileNameToScript[fileName];
const fileEntry = this.virtualFileSystem.traversePath(fileName);
return fileEntry && fileEntry.isFile() ? (<Utils.VirtualFile>fileEntry).content : undefined;
}
public addScript(fileName: string, content: string, isRootFile: boolean): void {
this.fileNameToScript[fileName] = new ScriptInfo(fileName, content, isRootFile);
this.virtualFileSystem.addFile(fileName, new ScriptInfo(fileName, content, isRootFile));
}
public editScript(fileName: string, start: number, end: number, newText: string) {
@@ -171,7 +173,7 @@ namespace Harness.LanguageService {
* @param col 0 based index
*/
public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter {
const script: ScriptInfo = this.fileNameToScript[fileName];
const script: ScriptInfo = this.getScriptInfo(fileName);
assert.isOk(script);
return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position);
@@ -182,8 +184,14 @@ namespace Harness.LanguageService {
class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost {
getCompilationSettings() { return this.settings; }
getCancellationToken() { return this.cancellationToken; }
getDirectories(path: string): string[] { return []; }
getCurrentDirectory(): string { return ""; }
getDirectories(path: string): string[] {
const dir = this.virtualFileSystem.traversePath(path);
if (dir && dir.isDirectory()) {
return ts.map((<Utils.VirtualDirectory>dir).getDirectories(), (d) => ts.combinePaths(path, d.name));
}
return [];
}
getCurrentDirectory(): string { return virtualFileSystemRoot; }
getDefaultLibFileName(): string { return Harness.Compiler.defaultLibFileName; }
getScriptFileNames(): string[] { return this.getFilenames(); }
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
@@ -196,6 +204,22 @@ namespace Harness.LanguageService {
return script ? script.version.toString() : undefined;
}
fileExists(fileName: string): boolean {
const script = this.getScriptSnapshot(fileName);
return script !== undefined;
}
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[] {
return ts.matchFiles(path, extensions, exclude, include,
/*useCaseSensitiveFileNames*/false,
this.getCurrentDirectory(),
(p) => this.virtualFileSystem.getAccessibleFileSystemEntries(p));
}
readFile(path: string, encoding?: string): string {
const snapshot = this.getScriptSnapshot(path);
return snapshot.getText(0, snapshot.getLength());
}
log(s: string): void { }
trace(s: string): void { }
error(s: string): void { }
-1
View File
@@ -509,7 +509,6 @@ class ProjectRunner extends RunnerBase {
// });
// Verify that all the generated .d.ts files compile
it("Errors in generated Dts files for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
if (!compilerResult.errors.length && testCase.declaration) {
const dTsCompileResult = compileCompileDTsFiles(compilerResult);
+2 -1
View File
@@ -223,7 +223,8 @@ namespace RWC {
});
it("has the expected types", () => {
Harness.Compiler.doTypeAndSymbolBaseline(`${baseName}.types`, compilerResult, inputFiles
// We don't need to pass the extension here because "doTypeAndSymbolBaseline" will append appropriate extension of ".types" or ".symbols"
Harness.Compiler.doTypeAndSymbolBaseline(baseName, 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[]>[]
}
+1 -1
View File
@@ -289,4 +289,4 @@ namespace ts {
});
});
});
}
}
@@ -1,79 +0,0 @@
class a {
constructor ( n : number ) ;
constructor ( s : string ) ;
constructor ( ns : any ) {
}
public pgF ( ) { } ;
public pv ;
public get d ( ) {
return 30 ;
}
public set d ( ) {
}
public static get p2 ( ) {
return { x : 30 , y : 40 } ;
}
private static d2 ( ) {
}
private static get p3 ( ) {
return "string" ;
}
private pv3 ;
private foo ( n : number ) : string ;
private foo ( s : string ) : string ;
private foo ( ns : any ) {
return ns.toString ( ) ;
}
}
class b extends a {
}
class m1b {
}
interface m1ib {
}
class c extends m1b {
}
class ib2 implements m1ib {
}
declare class aAmbient {
constructor ( n : number ) ;
constructor ( s : string ) ;
public pgF ( ) : void ;
public pv ;
public d : number ;
static p2 : { x : number ; y : number ; } ;
static d2 ( ) ;
static p3 ;
private pv3 ;
private foo ( s ) ;
}
class d {
private foo ( n : number ) : string ;
private foo ( ns : any ) {
return ns.toString ( ) ;
}
private foo ( s : string ) : string ;
}
class e {
private foo ( ns : any ) {
return ns.toString ( ) ;
}
private foo ( s : string ) : string ;
private foo ( n : number ) : string ;
}
@@ -1,79 +0,0 @@
class a {
constructor(n: number);
constructor(s: string);
constructor(ns: any) {
}
public pgF() { };
public pv;
public get d() {
return 30;
}
public set d() {
}
public static get p2() {
return { x: 30, y: 40 };
}
private static d2() {
}
private static get p3() {
return "string";
}
private pv3;
private foo(n: number): string;
private foo(s: string): string;
private foo(ns: any) {
return ns.toString();
}
}
class b extends a {
}
class m1b {
}
interface m1ib {
}
class c extends m1b {
}
class ib2 implements m1ib {
}
declare class aAmbient {
constructor(n: number);
constructor(s: string);
public pgF(): void;
public pv;
public d: number;
static p2: { x: number; y: number; };
static d2();
static p3;
private pv3;
private foo(s);
}
class d {
private foo(n: number): string;
private foo(ns: any) {
return ns.toString();
}
private foo(s: string): string;
}
class e {
private foo(ns: any) {
return ns.toString();
}
private foo(s: string): string;
private foo(n: number): string;
}
@@ -1,4 +0,0 @@
class foo {
constructor (n?: number, m? = 5, o?: string = "") { }
x:number = 1?2:3;
}
@@ -1,4 +0,0 @@
class foo {
constructor(n?: number, m? = 5, o?: string = "") { }
x: number = 1 ? 2 : 3;
}
@@ -1,3 +0,0 @@
$ ( document ) . ready ( function ( ) {
alert ( 'i am ready' ) ;
} );
@@ -1,3 +0,0 @@
$(document).ready(function() {
alert('i am ready');
});
@@ -1,10 +0,0 @@
function foo ( x : { } ) { }
foo ( { } ) ;
interface bar {
x : { } ;
y : ( ) => { } ;
}
@@ -1,10 +0,0 @@
function foo(x: {}) { }
foo({});
interface bar {
x: {};
y: () => {};
}
@@ -1,112 +0,0 @@
// valid
( ) => 1 ;
( arg ) => 2 ;
arg => 2 ;
( arg = 1 ) => 3 ;
( arg ? ) => 4 ;
( arg : number ) => 5 ;
( arg : number = 0 ) => 6 ;
( arg ? : number ) => 7 ;
( ... arg : number [ ] ) => 8 ;
( arg1 , arg2 ) => 12 ;
( arg1 = 1 , arg2 =3 ) => 13 ;
( arg1 ? , arg2 ? ) => 14 ;
( arg1 : number , arg2 : number ) => 15 ;
( arg1 : number = 0 , arg2 : number = 1 ) => 16 ;
( arg1 ? : number , arg2 ? : number ) => 17 ;
( arg1 , ... arg2 : number [ ] ) => 18 ;
( arg1 , arg2 ? : number ) => 19 ;
// in paren
( ( ) => 21 ) ;
( ( arg ) => 22 ) ;
( ( arg = 1 ) => 23 ) ;
( ( arg ? ) => 24 ) ;
( ( arg : number ) => 25 ) ;
( ( arg : number = 0 ) => 26 ) ;
( ( arg ? : number ) => 27 ) ;
( ( ... arg : number [ ] ) => 28 ) ;
// in multiple paren
( ( ( ( ( arg ) => { return 32 ; } ) ) ) ) ;
// in ternary exression
false ? ( ) => 41 : null ;
false ? ( arg ) => 42 : null ;
false ? ( arg = 1 ) => 43 : null ;
false ? ( arg ? ) => 44 : null ;
false ? ( arg : number ) => 45 : null ;
false ? ( arg ? : number ) => 46 : null ;
false ? ( arg ? : number = 0 ) => 47 : null ;
false ? ( ... arg : number [ ] ) => 48 : null ;
// in ternary exression within paren
false ? ( ( ) => 51 ) : null ;
false ? ( ( arg ) => 52 ) : null ;
false ? ( ( arg = 1 ) => 53 ) : null ;
false ? ( ( arg ? ) => 54 ) : null ;
false ? ( ( arg : number ) => 55 ) : null ;
false ? ( ( arg ? : number ) => 56 ) : null ;
false ? ( ( arg ? : number = 0 ) => 57 ) : null ;
false ? ( ( ... arg : number [ ] ) => 58 ) : null ;
// ternary exression's else clause
false ? null : ( ) => 61 ;
false ? null : ( arg ) => 62 ;
false ? null : ( arg = 1 ) => 63 ;
false ? null : ( arg ? ) => 64 ;
false ? null : ( arg : number ) => 65 ;
false ? null : ( arg ? : number ) => 66 ;
false ? null : ( arg ? : number = 0 ) => 67 ;
false ? null : ( ... arg : number [ ] ) => 68 ;
// nested ternary expressions
( a ? ) => { return a ; } ? ( b ? ) => { return b ; } : ( c ? ) => { return c ; } ;
//multiple levels
( a ? ) => { return a ; } ? ( b ) => ( c ) => 81 : ( c ) => ( d ) => 82 ;
// In Expressions
( ( arg ) => 90 ) instanceof Function ;
( ( arg = 1 ) => 91 ) instanceof Function ;
( ( arg ? ) => 92 ) instanceof Function ;
( ( arg : number ) => 93 ) instanceof Function ;
( ( arg : number = 1 ) => 94 ) instanceof Function ;
( ( arg ? : number ) => 95 ) instanceof Function ;
( ( ... arg : number [ ] ) => 96 ) instanceof Function ;
'' + ( arg ) => 100 ;
( ( arg ) => 0 ) + '' + ( arg ) => 101 ;
( ( arg = 1 ) => 0 ) + '' + ( arg = 2 ) => 102 ;
( ( arg ? ) => 0 ) + '' + ( arg ? ) => 103 ;
( ( arg : number ) => 0 ) + '' + ( arg : number ) => 104 ;
( ( arg : number = 1 ) => 0 ) + '' + ( arg : number = 2 ) => 105 ;
( ( arg ? : number = 1 ) => 0 ) + '' + ( arg ? : number = 2 ) => 106 ;
( ( ... arg : number [ ] ) => 0 ) + '' + ( ... arg : number [ ] ) => 107 ;
( ( arg1 , arg2 ? ) => 0 ) + '' + ( arg1 , arg2 ? ) => 108 ;
( ( arg1 , ... arg2 : number [ ] ) => 0 ) + '' + ( arg1 , ... arg2 : number [ ] ) => 108 ;
// Function Parameters
function foo ( ... arg : any [ ] ) { }
foo (
( a ) => 110 ,
( ( a ) => 111 ) ,
( a ) => {
return 112 ;
} ,
( a ? ) => 113 ,
( a , b ? ) => 114 ,
( a : number ) => 115 ,
( a : number = 0 ) => 116 ,
( a = 0 ) => 117 ,
( a ? : number = 0 ) => 118 ,
( a ? , b ? : number = 0 ) => 118 ,
( ... a : number [ ] ) => 119 ,
( a , b ? = 0 , ... c : number [ ] ) => 120 ,
( a ) => ( b ) => ( c ) => 121 ,
false ? ( a ) => 0 : ( b ) => 122
) ;
@@ -1,112 +0,0 @@
// valid
() => 1;
(arg) => 2;
arg => 2;
(arg = 1) => 3;
(arg?) => 4;
(arg: number) => 5;
(arg: number = 0) => 6;
(arg?: number) => 7;
(...arg: number[]) => 8;
(arg1, arg2) => 12;
(arg1 = 1, arg2 = 3) => 13;
(arg1?, arg2?) => 14;
(arg1: number, arg2: number) => 15;
(arg1: number = 0, arg2: number = 1) => 16;
(arg1?: number, arg2?: number) => 17;
(arg1, ...arg2: number[]) => 18;
(arg1, arg2?: number) => 19;
// in paren
(() => 21);
((arg) => 22);
((arg = 1) => 23);
((arg?) => 24);
((arg: number) => 25);
((arg: number = 0) => 26);
((arg?: number) => 27);
((...arg: number[]) => 28);
// in multiple paren
(((((arg) => { return 32; }))));
// in ternary exression
false ? () => 41 : null;
false ? (arg) => 42 : null;
false ? (arg = 1) => 43 : null;
false ? (arg?) => 44 : null;
false ? (arg: number) => 45 : null;
false ? (arg?: number) => 46 : null;
false ? (arg?: number = 0) => 47 : null;
false ? (...arg: number[]) => 48 : null;
// in ternary exression within paren
false ? (() => 51) : null;
false ? ((arg) => 52) : null;
false ? ((arg = 1) => 53) : null;
false ? ((arg?) => 54) : null;
false ? ((arg: number) => 55) : null;
false ? ((arg?: number) => 56) : null;
false ? ((arg?: number = 0) => 57) : null;
false ? ((...arg: number[]) => 58) : null;
// ternary exression's else clause
false ? null : () => 61;
false ? null : (arg) => 62;
false ? null : (arg = 1) => 63;
false ? null : (arg?) => 64;
false ? null : (arg: number) => 65;
false ? null : (arg?: number) => 66;
false ? null : (arg?: number = 0) => 67;
false ? null : (...arg: number[]) => 68;
// nested ternary expressions
(a?) => { return a; } ? (b?) => { return b; } : (c?) => { return c; };
//multiple levels
(a?) => { return a; } ? (b) => (c) => 81 : (c) => (d) => 82;
// In Expressions
((arg) => 90) instanceof Function;
((arg = 1) => 91) instanceof Function;
((arg?) => 92) instanceof Function;
((arg: number) => 93) instanceof Function;
((arg: number = 1) => 94) instanceof Function;
((arg?: number) => 95) instanceof Function;
((...arg: number[]) => 96) instanceof Function;
'' + (arg) => 100;
((arg) => 0) + '' + (arg) => 101;
((arg = 1) => 0) + '' + (arg = 2) => 102;
((arg?) => 0) + '' + (arg?) => 103;
((arg: number) => 0) + '' + (arg: number) => 104;
((arg: number = 1) => 0) + '' + (arg: number = 2) => 105;
((arg?: number = 1) => 0) + '' + (arg?: number = 2) => 106;
((...arg: number[]) => 0) + '' + (...arg: number[]) => 107;
((arg1, arg2?) => 0) + '' + (arg1, arg2?) => 108;
((arg1, ...arg2: number[]) => 0) + '' + (arg1, ...arg2: number[]) => 108;
// Function Parameters
function foo(...arg: any[]) { }
foo(
(a) => 110,
((a) => 111),
(a) => {
return 112;
},
(a?) => 113,
(a, b?) => 114,
(a: number) => 115,
(a: number = 0) => 116,
(a = 0) => 117,
(a?: number = 0) => 118,
(a?, b?: number = 0) => 118,
(...a: number[]) => 119,
(a, b? = 0, ...c: number[]) => 120,
(a) => (b) => (c) => 121,
false ? (a) => 0 : (b) => 122
);
@@ -1,2 +0,0 @@
if(false){debugger;}
if ( false ) { debugger ; }
@@ -1,2 +0,0 @@
if (false) { debugger; }
if (false) { debugger; }
@@ -1,13 +0,0 @@
var fun1 = function ( ) {
var x = 'foo' ,
z = 'bar' ;
return x ;
},
fun2 = ( function ( f ) {
var fun = function ( ) {
console . log ( f ( ) ) ;
},
x = 'Foo' ;
return fun ;
} ( fun1 ) ) ;
@@ -1,13 +0,0 @@
var fun1 = function() {
var x = 'foo',
z = 'bar';
return x;
},
fun2 = (function(f) {
var fun = function() {
console.log(f());
},
x = 'Foo';
return fun;
} (fun1));
@@ -1,3 +0,0 @@
export class A {
}
@@ -1,6 +0,0 @@
module Foo {
}
import bar = Foo;
import bar2=Foo;
@@ -1,6 +0,0 @@
module Foo {
}
import bar = Foo;
import bar2 = Foo;
@@ -1,95 +0,0 @@
var a;var c , b;var $d
var $e
var f
a++;b++;
function f ( ) {
for (i = 0; i < 10; i++) {
k = abc + 123 ^ d;
a = XYZ[m (a[b[c][d]])];
break;
switch ( variable){
case 1: abc += 425;
break;
case 404 : a [x--/2]%=3 ;
break ;
case vari : v[--x ] *=++y*( m + n / k[z]);
for (a in b){
for (a = 0; a < 10; ++a) {
a++;--a;
if (a == b) {
a++;b--;
}
else
if (a == c){
++a;
(--c)+=d;
$c = $a + --$b;
}
if (a == b)
if (a != b) {
if (a !== b)
if (a === b)
--a;
else
--a;
else {
a--;++b;
a++
}
}
}
for (x in y) {
m-=m;
k=1+2+3+4;
}
}
break;
}
}
var a ={b:function(){}};
return {a:1,b:2}
}
var z = 1;
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
for (k = 0; k < 10; ++k) {
z++;
}
for (k = 0; k < 10; k += 2) {
z++;
}
$(document).ready ();
function pageLoad() {
$('#TextBox1' ) . unbind ( ) ;
$('#TextBox1' ) . datepicker ( ) ;
}
function pageLoad ( ) {
var webclass=[
{ 'student' :
{ 'id': '1', 'name': 'Linda Jones', 'legacySkill': 'Access, VB 5.0' }
} ,
{ 'student':
{'id':'2','name':'Adam Davidson','legacySkill':'Cobol,MainFrame'}
} ,
{ 'student':
{ 'id':'3','name':'Charles Boyer' ,'legacySkill':'HTML, XML'}
}
];
$create(Sys.UI.DataView,{data:webclass},null,null,$get('SList'));
}
$( document ).ready(function(){
alert('hello');
} ) ;
@@ -1,98 +0,0 @@
var a; var c, b; var $d
var $e
var f
a++; b++;
function f() {
for (i = 0; i < 10; i++) {
k = abc + 123 ^ d;
a = XYZ[m(a[b[c][d]])];
break;
switch (variable) {
case 1: abc += 425;
break;
case 404: a[x-- / 2] %= 3;
break;
case vari: v[--x] *= ++y * (m + n / k[z]);
for (a in b) {
for (a = 0; a < 10; ++a) {
a++; --a;
if (a == b) {
a++; b--;
}
else
if (a == c) {
++a;
(--c) += d;
$c = $a + --$b;
}
if (a == b)
if (a != b) {
if (a !== b)
if (a === b)
--a;
else
--a;
else {
a--; ++b;
a++
}
}
}
for (x in y) {
m -= m;
k = 1 + 2 + 3 + 4;
}
}
break;
}
}
var a = { b: function() { } };
return { a: 1, b: 2 }
}
var z = 1;
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
for (k = 0; k < 10; ++k) {
z++;
}
for (k = 0; k < 10; k += 2) {
z++;
}
$(document).ready();
function pageLoad() {
$('#TextBox1').unbind();
$('#TextBox1').datepicker();
}
function pageLoad() {
var webclass = [
{
'student':
{ 'id': '1', 'name': 'Linda Jones', 'legacySkill': 'Access, VB 5.0' }
},
{
'student':
{ 'id': '2', 'name': 'Adam Davidson', 'legacySkill': 'Cobol,MainFrame' }
},
{
'student':
{ 'id': '3', 'name': 'Charles Boyer', 'legacySkill': 'HTML, XML' }
}
];
$create(Sys.UI.DataView, { data: webclass }, null, null, $get('SList'));
}
$(document).ready(function() {
alert('hello');
});
@@ -1,3 +0,0 @@
module Foo {
export module A . B . C { }
}
@@ -1,3 +0,0 @@
module Foo {
export module A.B.C { }
}
@@ -1,76 +0,0 @@
module mod1 {
export class b {
}
class d {
}
export interface ib {
}
}
module m2 {
export module m3 {
export class c extends mod1.b {
}
export class ib2 implements mod1.ib {
}
}
}
class c extends mod1.b {
}
class ib2 implements mod1.ib {
}
declare export module "m4" {
export class d {
} ;
var x : d ;
export function foo ( ) : d ;
}
import m4 = module ( "m4" ) ;
export var x4 = m4.x ;
export var d4 = m4.d ;
export var f4 = m4.foo ( ) ;
export module m1 {
declare export module "m2" {
export class d {
} ;
var x: d ;
export function foo ( ) : d ;
}
import m2 = module ( "m2" ) ;
import m3 = module ( "m4" ) ;
export var x2 = m2.x ;
export var d2 = m2.d ;
export var f2 = m2.foo ( ) ;
export var x3 = m3.x ;
export var d3 = m3.d ;
export var f3 = m3.foo ( ) ;
}
export var x2 = m1.m2.x ;
export var d2 = m1.m2.d ;
export var f2 = m1.m2.foo ( ) ;
export var x3 = m1.m3.x ;
export var d3 = m1.m3.d ;
export var f3 = m1.m3.foo ( ) ;
export module m5 {
export var x2 = m1.m2.x ;
export var d2 = m1.m2.d ;
export var f2 = m1.m2.foo ( ) ;
export var x3 = m1.m3.x ;
export var d3 = m1.m3.d ;
export var f3 = m1.m3.foo ( ) ;
}
@@ -1,76 +0,0 @@
module mod1 {
export class b {
}
class d {
}
export interface ib {
}
}
module m2 {
export module m3 {
export class c extends mod1.b {
}
export class ib2 implements mod1.ib {
}
}
}
class c extends mod1.b {
}
class ib2 implements mod1.ib {
}
declare export module "m4" {
export class d {
};
var x: d;
export function foo(): d;
}
import m4 = module("m4");
export var x4 = m4.x;
export var d4 = m4.d;
export var f4 = m4.foo();
export module m1 {
declare export module "m2" {
export class d {
};
var x: d;
export function foo(): d;
}
import m2 = module("m2");
import m3 = module("m4");
export var x2 = m2.x;
export var d2 = m2.d;
export var f2 = m2.foo();
export var x3 = m3.x;
export var d3 = m3.d;
export var f3 = m3.foo();
}
export var x2 = m1.m2.x;
export var d2 = m1.m2.d;
export var f2 = m1.m2.foo();
export var x3 = m1.m3.x;
export var d3 = m1.m3.d;
export var f3 = m1.m3.foo();
export module m5 {
export var x2 = m1.m2.x;
export var d2 = m1.m2.d;
export var f2 = m1.m2.foo();
export var x3 = m1.m3.x;
export var d3 = m1.m3.d;
export var f3 = m1.m3.foo();
}
@@ -1,27 +0,0 @@
var x = {foo: 1,
bar: "tt",
boo: 1 + 5};
var x2 = {foo: 1,
bar: "tt",boo:1+5};
function Foo() {
var typeICalc = {
clear: {
"()": [1, 2, 3]
}
}
}
// Rule for object literal members for the "value" of the memebr to follow the indent
// of the member, i.e. the relative position of the value is maintained when the member
// is indented.
var x2 = {
foo:
3,
'bar':
{ a: 1, b : 2}
};
var x={ };
var y = {};
@@ -1,31 +0,0 @@
var x = {
foo: 1,
bar: "tt",
boo: 1 + 5
};
var x2 = {
foo: 1,
bar: "tt", boo: 1 + 5
};
function Foo() {
var typeICalc = {
clear: {
"()": [1, 2, 3]
}
}
}
// Rule for object literal members for the "value" of the memebr to follow the indent
// of the member, i.e. the relative position of the value is maintained when the member
// is indented.
var x2 = {
foo:
3,
'bar':
{ a: 1, b: 2 }
};
var x = {};
var y = {};
@@ -1,32 +0,0 @@
function f( ) {
var x = 3;
var z = 2 ;
a = z ++ - 2 * x ;
for ( ; ; ) {
a+=(g +g)*a%t;
b -- ;
}
switch ( a )
{
case 1 : {
a ++ ;
b--;
if(a===a)
return;
else
{
for(a in b)
if(a!=a)
{
for(a in b)
{
a++;
}
}
}
}
default:
break;
}
}
@@ -1,28 +0,0 @@
function f() {
var x = 3;
var z = 2;
a = z++ - 2 * x;
for (; ;) {
a += (g + g) * a % t;
b--;
}
switch (a) {
case 1: {
a++;
b--;
if (a === a)
return;
else {
for (a in b)
if (a != a) {
for (a in b) {
a++;
}
}
}
}
default:
break;
}
}
@@ -1 +0,0 @@
var a=b+c^d-e*++f;
@@ -1 +0,0 @@
var a = b + c ^ d - e * ++f;
@@ -1 +0,0 @@
class test { constructor () { } }
@@ -1 +0,0 @@
class test { constructor() { } }
@@ -1,10 +0,0 @@
module Tools {
export enum NodeType {
Error,
Comment,
}
export enum foob
{
Blah=1, Bleah=2
}
}
@@ -1,9 +0,0 @@
module Tools {
export enum NodeType {
Error,
Comment,
}
export enum foob {
Blah = 1, Bleah = 2
}
}
@@ -1,65 +0,0 @@
module MyModule
{
module A.B.C {
module F {
}
}
interface Blah
{
boo: string;
}
class Foo
{
}
class Foo2 {
public foo():number {
return 5 * 6;
}
public foo2() {
if (1 === 2)
{
var y : number= 76;
return y;
}
while (2 == 3) {
if ( y == null ) {
}
}
}
public foo3() {
if (1 === 2)
//comment preventing line merging
{
var y = 76;
return y;
}
}
}
}
function foo(a:number, b:number):number
{
return 0;
}
function bar(a:number, b:number) :number[] {
return [];
}
module BugFix3 {
declare var f: {
(): any;
(x: number): string;
foo: number;
};
}
@@ -1,58 +0,0 @@
module MyModule {
module A.B.C {
module F {
}
}
interface Blah {
boo: string;
}
class Foo {
}
class Foo2 {
public foo(): number {
return 5 * 6;
}
public foo2() {
if (1 === 2) {
var y: number = 76;
return y;
}
while (2 == 3) {
if (y == null) {
}
}
}
public foo3() {
if (1 === 2)
//comment preventing line merging
{
var y = 76;
return y;
}
}
}
}
function foo(a: number, b: number): number {
return 0;
}
function bar(a: number, b: number): number[] {
return [];
}
module BugFix3 {
declare var f: {
(): any;
(x: number): string;
foo: number;
};
}
@@ -1,17 +0,0 @@
function f(a,b,c,d){
for(var i=0;i<10;i++){
var a=0;
var b=a+a+a*a%a/2-1;
b+=a;
++b;
f(a,b,c,d);
if(1===1){
var m=function(e,f){
return e^f;
}
}
}
}
for (var i = 0 ; i < this.foo(); i++) {
}
@@ -1,17 +0,0 @@
function f(a, b, c, d) {
for (var i = 0; i < 10; i++) {
var a = 0;
var b = a + a + a * a % a / 2 - 1;
b += a;
++b;
f(a, b, c, d);
if (1 === 1) {
var m = function(e, f) {
return e ^ f;
}
}
}
}
for (var i = 0 ; i < this.foo(); i++) {
}
@@ -1,9 +0,0 @@
with (foo.bar)
{
}
with (bar.blah)
{
}
@@ -1,6 +0,0 @@
with (foo.bar) {
}
with (bar.blah) {
}
+3 -2
View File
@@ -151,7 +151,7 @@ namespace ts {
);
});
it("always exclude outDir", () => {
it("exclude outDir unless overridden", () => {
const tsconfigWithoutExclude =
`{
"compilerOptions": {
@@ -169,7 +169,7 @@ namespace ts {
const allFiles = ["/bin/a.ts", "/b.ts"];
const expectedFiles = ["/b.ts"];
assertParseFileList(tsconfigWithoutExclude, "tsconfig.json", rootDir, allFiles, expectedFiles);
assertParseFileList(tsconfigWithExclude, "tsconfig.json", rootDir, allFiles, expectedFiles);
assertParseFileList(tsconfigWithExclude, "tsconfig.json", rootDir, allFiles, allFiles);
});
it("implicitly exclude common package folders", () => {
@@ -186,6 +186,7 @@ namespace ts {
const content = `{
"compilerOptions": {
"allowJs": true
// Some comments
"outDir": "bin"
}
"files": ["file1.ts"]
+6 -25
View File
@@ -198,22 +198,12 @@ namespace ts {
watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher {
const path = this.toPath(directoryName);
const callbacks = this.watchedDirectories[path] || (this.watchedDirectories[path] = []);
callbacks.push({ cb: callback, recursive });
const cbWithRecursive = { cb: callback, recursive };
multiMapAdd(this.watchedDirectories, path, cbWithRecursive);
return {
referenceCount: 0,
directoryName,
close: () => {
for (let i = 0; i < callbacks.length; i++) {
if (callbacks[i].cb === callback) {
callbacks.splice(i, 1);
break;
}
}
if (!callbacks.length) {
delete this.watchedDirectories[path];
}
}
close: () => multiMapRemove(this.watchedDirectories, path, cbWithRecursive)
};
}
@@ -239,17 +229,8 @@ namespace ts {
watchFile(fileName: string, callback: FileWatcherCallback) {
const path = this.toPath(fileName);
const callbacks = this.watchedFiles[path] || (this.watchedFiles[path] = []);
callbacks.push(callback);
return {
close: () => {
const i = callbacks.indexOf(callback);
callbacks.splice(i, 1);
if (!callbacks.length) {
delete this.watchedFiles[path];
}
}
};
multiMapAdd(this.watchedFiles, path, callback);
return { close: () => multiMapRemove(this.watchedFiles, path, callback) };
}
// TOOD: record and invoke callbacks to simulate timer events
@@ -259,7 +240,7 @@ namespace ts {
};
readonly clearTimeout = (timeoutId: any): void => {
if (typeof timeoutId === "number") {
this.callbackQueue.splice(timeoutId, 1);
orderedRemoveItemAt(this.callbackQueue, timeoutId);
}
};
+40 -16
View File
@@ -16,7 +16,7 @@ namespace Utils {
}
export class VirtualFile extends VirtualFileSystemEntry {
content: string;
content?: Harness.LanguageService.ScriptInfo;
isFile() { return true; }
}
@@ -73,7 +73,7 @@ namespace Utils {
}
}
addFile(name: string, content?: string): VirtualFile {
addFile(name: string, content?: Harness.LanguageService.ScriptInfo): VirtualFile {
const entry = this.getFileSystemEntry(name);
if (entry === undefined) {
const file = new VirtualFile(this.fileSystem, name);
@@ -111,6 +111,7 @@ namespace Utils {
getFileSystemEntries() { return this.root.getFileSystemEntries(); }
addDirectory(path: string) {
path = ts.normalizePath(path);
const components = ts.getNormalizedPathComponents(path, this.currentDirectory);
let directory: VirtualDirectory = this.root;
for (const component of components) {
@@ -123,8 +124,8 @@ namespace Utils {
return directory;
}
addFile(path: string, content?: string) {
const absolutePath = ts.getNormalizedAbsolutePath(path, this.currentDirectory);
addFile(path: string, content?: Harness.LanguageService.ScriptInfo) {
const absolutePath = ts.normalizePath(ts.getNormalizedAbsolutePath(path, this.currentDirectory));
const fileName = ts.getBaseFileName(path);
const directoryPath = ts.getDirectoryPath(absolutePath);
const directory = this.addDirectory(directoryPath);
@@ -141,6 +142,7 @@ namespace Utils {
}
traversePath(path: string) {
path = ts.normalizePath(path);
let directory: VirtualDirectory = this.root;
for (const component of ts.getNormalizedPathComponents(path, this.currentDirectory)) {
const entry = directory.getFileSystemEntry(component);
@@ -157,6 +159,40 @@ namespace Utils {
return directory;
}
/**
* Reads the directory at the given path and retrieves a list of file names and a list
* of directory names within it. Suitable for use with ts.matchFiles()
* @param path The path to the directory to be read
*/
getAccessibleFileSystemEntries(path: string) {
const entry = this.traversePath(path);
if (entry && entry.isDirectory()) {
const directory = <VirtualDirectory>entry;
return {
files: ts.map(directory.getFiles(), f => f.name),
directories: ts.map(directory.getDirectories(), d => d.name)
};
}
return { files: [], directories: [] };
}
getAllFileEntries() {
const fileEntries: VirtualFile[] = [];
getFilesRecursive(this.root, fileEntries);
return fileEntries;
function getFilesRecursive(dir: VirtualDirectory, result: VirtualFile[]) {
const files = dir.getFiles();
const dirs = dir.getDirectories();
for (const file of files) {
result.push(file);
}
for (const subDir of dirs) {
getFilesRecursive(subDir, result);
}
}
}
}
export class MockParseConfigHost extends VirtualFileSystem implements ts.ParseConfigHost {
@@ -170,17 +206,5 @@ namespace Utils {
readDirectory(path: string, extensions: string[], excludes: string[], includes: string[]) {
return ts.matchFiles(path, extensions, excludes, includes, this.useCaseSensitiveFileNames, this.currentDirectory, (path: string) => this.getAccessibleFileSystemEntries(path));
}
getAccessibleFileSystemEntries(path: string) {
const entry = this.traversePath(path);
if (entry && entry.isDirectory()) {
const directory = <VirtualDirectory>entry;
return {
files: ts.map(directory.getFiles(), f => f.name),
directories: ts.map(directory.getDirectories(), d => d.name)
};
}
return { files: [], directories: [] };
}
}
}
-2
View File
@@ -16,7 +16,6 @@ interface MapConstructor {
declare var Map: MapConstructor;
interface WeakMap<K, V> {
clear(): void;
delete(key: K): boolean;
get(key: K): V | undefined;
has(key: K): boolean;
@@ -48,7 +47,6 @@ declare var Set: SetConstructor;
interface WeakSet<T> {
add(value: T): this;
clear(): void;
delete(value: T): boolean;
has(value: T): boolean;
}
+6
View File
@@ -1060,6 +1060,12 @@ interface ReadonlyArray<T> {
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => U, thisArg?: any): U[];
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
filter<S extends T>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg?: any): S[];
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
+12 -1
View File
@@ -216,7 +216,18 @@ namespace ts.server {
return {
isMemberCompletion: false,
isNewIdentifierLocation: false,
entries: response.body
entries: response.body.map(entry => {
if (entry.replacementSpan !== undefined) {
const { name, kind, kindModifiers, sortText, replacementSpan} = entry;
const convertedSpan = createTextSpanFromBounds(this.lineOffsetToPosition(fileName, replacementSpan.start),
this.lineOffsetToPosition(fileName, replacementSpan.end));
return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan };
}
return entry as { name: string, kind: string, kindModifiers: string, sortText: string };
})
};
}
+15 -21
View File
@@ -275,7 +275,7 @@ namespace ts.server {
removeRoot(info: ScriptInfo) {
if (this.filenameToScript.contains(info.path)) {
this.filenameToScript.remove(info.path);
this.roots = copyListRemovingItem(info, this.roots);
unorderedRemoveItem(this.roots, info);
this.resolvedModuleNames.remove(info.path);
this.resolvedTypeReferenceDirectives.remove(info.path);
}
@@ -306,11 +306,6 @@ namespace ts.server {
throw new Error("No script with name '" + filename + "'");
}
resolvePath(path: string): string {
const result = this.host.resolvePath(path);
return result;
}
fileExists(path: string): boolean {
const result = this.host.fileExists(path);
return result;
@@ -324,6 +319,14 @@ namespace ts.server {
return this.host.getDirectories(path);
}
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[] {
return this.host.readDirectory(path, extensions, exclude, include);
}
readFile(path: string, encoding?: string): string {
return this.host.readFile(path, encoding);
}
/**
* @param line 1 based index
*/
@@ -585,16 +588,6 @@ namespace ts.server {
project?: Project;
}
function copyListRemovingItem<T>(item: T, list: T[]) {
const copiedList: T[] = [];
for (let i = 0, len = list.length; i < len; i++) {
if (list[i] != item) {
copiedList.push(list[i]);
}
}
return copiedList;
}
/**
* This helper funciton processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
*/
@@ -880,7 +873,7 @@ namespace ts.server {
project.directoryWatcher.close();
forEachProperty(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
delete project.directoriesWatchedForWildcards;
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
unorderedRemoveItem(this.configuredProjects, project);
}
else {
for (const directory of project.directoriesWatchedForTsconfig) {
@@ -892,7 +885,7 @@ namespace ts.server {
delete project.projectService.directoryWatchersForTsconfig[directory];
}
}
this.inferredProjects = copyListRemovingItem(project, this.inferredProjects);
unorderedRemoveItem(this.inferredProjects, project);
}
const fileNames = project.getFileNames();
@@ -1017,7 +1010,7 @@ namespace ts.server {
}
}
else {
this.openFilesReferenced = copyListRemovingItem(info, this.openFilesReferenced);
unorderedRemoveItem(this.openFilesReferenced, info);
}
info.close();
}
@@ -1524,13 +1517,13 @@ namespace ts.server {
// openFileRoots or openFileReferenced.
if (info.isOpen) {
if (this.openFileRoots.indexOf(info) >= 0) {
this.openFileRoots = copyListRemovingItem(info, this.openFileRoots);
unorderedRemoveItem(this.openFileRoots, info);
if (info.defaultProject && !info.defaultProject.isConfiguredProject()) {
this.removeProject(info.defaultProject);
}
}
if (this.openFilesReferenced.indexOf(info) >= 0) {
this.openFilesReferenced = copyListRemovingItem(info, this.openFilesReferenced);
unorderedRemoveItem(this.openFilesReferenced, info);
}
this.openFileRootsConfigured.push(info);
info.defaultProject = project;
@@ -1601,6 +1594,7 @@ namespace ts.server {
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
PlaceOpenBraceOnNewLineForFunctions: false,
+5
View File
@@ -773,6 +773,11 @@ declare namespace ts.server.protocol {
* is often the same as the name but may be different in certain circumstances.
*/
sortText: string;
/**
* An optional span that indicates the text to be replaced by this completion item. If present,
* this span should be used instead of the default one.
*/
replacementSpan?: TextSpan;
}
/**
+2 -2
View File
@@ -204,7 +204,7 @@ namespace ts.server {
// average async stat takes about 30 microseconds
// set chunk size to do 30 files in < 1 millisecond
function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) {
let watchedFiles: WatchedFile[] = [];
const watchedFiles: WatchedFile[] = [];
let nextFileToCheck = 0;
let watchTimer: any;
@@ -267,7 +267,7 @@ namespace ts.server {
}
function removeFile(file: WatchedFile) {
watchedFiles = copyListRemovingItem(file, watchedFiles);
unorderedRemoveItem(watchedFiles, file);
}
return {
+11 -1
View File
@@ -778,7 +778,17 @@ namespace ts.server {
return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => {
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) {
result.push(entry);
const { name, kind, kindModifiers, sortText, replacementSpan } = entry;
let convertedSpan: protocol.TextSpan = undefined;
if (replacementSpan) {
convertedSpan = {
start: compilerService.host.positionToLineOffset(fileName, replacementSpan.start),
end: compilerService.host.positionToLineOffset(fileName, replacementSpan.start + replacementSpan.length)
};
}
result.push({ name, kind, kindModifiers, sortText, replacementSpan: convertedSpan });
}
return result;
}, []).sort((a, b) => a.name.localeCompare(b.name));
+5 -1
View File
@@ -50,6 +50,8 @@ namespace ts.formatting {
// Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
public SpaceAfterOpenBrace: Rule;
public SpaceBeforeCloseBrace: Rule;
public NoSpaceAfterOpenBrace: Rule;
public NoSpaceBeforeCloseBrace: Rule;
public NoSpaceBetweenEmptyBraceBrackets: Rule;
// Insert new line after { and before } in multi-line contexts.
@@ -287,6 +289,8 @@ namespace ts.formatting {
// Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
this.SpaceAfterOpenBrace = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSingleLineBlockContext), RuleAction.Space));
this.SpaceBeforeCloseBrace = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSingleLineBlockContext), RuleAction.Space));
this.NoSpaceAfterOpenBrace = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSingleLineBlockContext), RuleAction.Delete));
this.NoSpaceBeforeCloseBrace = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSingleLineBlockContext), RuleAction.Delete));
this.NoSpaceBetweenEmptyBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectContext), RuleAction.Delete));
// Insert new line after { and before } in multi-line contexts.
@@ -414,7 +418,7 @@ namespace ts.formatting {
this.SpaceAfterPostdecrementWhenFollowedBySubtract,
this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement,
this.NoSpaceAfterCloseBrace,
this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NewLineBeforeCloseBraceInBlockContext,
this.NewLineBeforeCloseBraceInBlockContext,
this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets,
this.NoSpaceBetweenFunctionKeywordAndStar, this.SpaceAfterStarInGeneratorDeclaration,
this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember,
+13
View File
@@ -81,6 +81,19 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceBetweenBrackets);
}
// The default value of InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces is true
// so if the option is undefined, we should treat it as true as well
if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces !== false) {
rules.push(this.globalRules.SpaceAfterOpenBrace);
rules.push(this.globalRules.SpaceBeforeCloseBrace);
rules.push(this.globalRules.NoSpaceBetweenEmptyBraceBrackets);
}
else {
rules.push(this.globalRules.NoSpaceAfterOpenBrace);
rules.push(this.globalRules.NoSpaceBeforeCloseBrace);
rules.push(this.globalRules.NoSpaceBetweenEmptyBraceBrackets);
}
if (options.InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) {
rules.push(this.globalRules.SpaceAfterTemplateHeadAndMiddle);
rules.push(this.globalRules.SpaceBeforeTemplateMiddleAndTail);
+1
View File
@@ -466,6 +466,7 @@ namespace ts.NavigationBar {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.VariableDeclaration:
return hasSomeImportantChild(item);
case SyntaxKind.ArrowFunction:
+652 -842
View File
File diff suppressed because it is too large Load Diff
+26
View File
@@ -67,6 +67,10 @@ namespace ts {
getProjectVersion?(): string;
useCaseSensitiveFileNames?(): boolean;
readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string;
readFile(path: string, encoding?: string): string;
fileExists(path: string): boolean;
getModuleResolutionsForFile?(fileName: string): string;
getTypeReferenceDirectiveResolutionsForFile?(fileName: string): string;
directoryExists(directoryName: string): boolean;
@@ -421,6 +425,28 @@ namespace ts {
public getDefaultLibFileName(options: CompilerOptions): string {
return this.shimHost.getDefaultLibFileName(JSON.stringify(options));
}
public readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[], depth?: number): string[] {
const pattern = getFileMatcherPatterns(path, extensions, exclude, include,
this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
return JSON.parse(this.shimHost.readDirectory(
path,
JSON.stringify(extensions),
JSON.stringify(pattern.basePaths),
pattern.excludePattern,
pattern.includeFilePattern,
pattern.includeDirectoryPattern,
depth
));
}
public readFile(path: string, encoding?: string): string {
return this.shimHost.readFile(path, encoding);
}
public fileExists(path: string): boolean {
return this.shimHost.fileExists(path);
}
}
/** A cancellation that throttles calls to the host */
+1
View File
@@ -48,6 +48,7 @@
"services.ts",
"shims.ts",
"signatureHelp.ts",
"types.ts",
"utilities.ts",
"jsTyping.ts",
"formatting/formatting.ts",
+830
View File
@@ -0,0 +1,830 @@
namespace ts {
export interface Node {
getSourceFile(): SourceFile;
getChildCount(sourceFile?: SourceFile): number;
getChildAt(index: number, sourceFile?: SourceFile): Node;
getChildren(sourceFile?: SourceFile): Node[];
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
getFullStart(): number;
getEnd(): number;
getWidth(sourceFile?: SourceFile): number;
getFullWidth(): number;
getLeadingTriviaWidth(sourceFile?: SourceFile): number;
getFullText(sourceFile?: SourceFile): string;
getText(sourceFile?: SourceFile): string;
getFirstToken(sourceFile?: SourceFile): Node;
getLastToken(sourceFile?: SourceFile): Node;
}
export interface Symbol {
getFlags(): SymbolFlags;
getName(): string;
getDeclarations(): Declaration[];
getDocumentationComment(): SymbolDisplayPart[];
}
export interface Type {
getFlags(): TypeFlags;
getSymbol(): Symbol;
getProperties(): Symbol[];
getProperty(propertyName: string): Symbol;
getApparentProperties(): Symbol[];
getCallSignatures(): Signature[];
getConstructSignatures(): Signature[];
getStringIndexType(): Type;
getNumberIndexType(): Type;
getBaseTypes(): ObjectType[];
getNonNullableType(): Type;
}
export interface Signature {
getDeclaration(): SignatureDeclaration;
getTypeParameters(): Type[];
getParameters(): Symbol[];
getReturnType(): Type;
getDocumentationComment(): SymbolDisplayPart[];
}
export interface SourceFile {
/* @internal */ version: string;
/* @internal */ scriptSnapshot: IScriptSnapshot;
/* @internal */ nameTable: Map<number>;
/* @internal */ getNamedDeclarations(): Map<Declaration[]>;
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
getLineStarts(): number[];
getPositionOfLineAndCharacter(line: number, character: number): number;
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
}
/**
* Represents an immutable snapshot of a script at a specified time.Once acquired, the
* snapshot is observably immutable. i.e. the same calls with the same parameters will return
* the same values.
*/
export interface IScriptSnapshot {
/** Gets a portion of the script snapshot specified by [start, end). */
getText(start: number, end: number): string;
/** Gets the length of this script snapshot. */
getLength(): number;
/**
* Gets the TextChangeRange that describe how the text changed between this text and
* an older version. This information is used by the incremental parser to determine
* what sections of the script need to be re-parsed. 'undefined' can be returned if the
* change range cannot be determined. However, in that case, incremental parsing will
* not happen and the entire document will be re - parsed.
*/
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined;
/** Releases all resources held by this script snapshot */
dispose?(): void;
}
export namespace ScriptSnapshot {
class StringScriptSnapshot implements IScriptSnapshot {
constructor(private text: string) {
}
public getText(start: number, end: number): string {
return this.text.substring(start, end);
}
public getLength(): number {
return this.text.length;
}
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
// Text-based snapshots do not support incremental parsing. Return undefined
// to signal that to the caller.
return undefined;
}
}
export function fromString(text: string): IScriptSnapshot {
return new StringScriptSnapshot(text);
}
}
export interface PreProcessedFileInfo {
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
importedFiles: FileReference[];
ambientExternalModules: string[];
isLibFile: boolean;
}
export interface HostCancellationToken {
isCancellationRequested(): boolean;
}
//
// Public interface of the host of a language service instance.
//
export interface LanguageServiceHost {
getCompilationSettings(): CompilerOptions;
getNewLine?(): string;
getProjectVersion?(): string;
getScriptFileNames(): string[];
getScriptKind?(fileName: string): ScriptKind;
getScriptVersion(fileName: string): string;
getScriptSnapshot(fileName: string): IScriptSnapshot | undefined;
getLocalizedDiagnosticMessages?(): any;
getCancellationToken?(): HostCancellationToken;
getCurrentDirectory(): string;
getDefaultLibFileName(options: CompilerOptions): string;
log?(s: string): void;
trace?(s: string): void;
error?(s: string): void;
useCaseSensitiveFileNames?(): boolean;
/*
* LS host can optionally implement these methods to support completions for module specifiers.
* Without these methods, only completions for ambient modules will be provided.
*/
readDirectory?(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[];
readFile?(path: string, encoding?: string): string;
fileExists?(path: string): boolean;
/*
* LS host can optionally implement this method if it wants to be completely in charge of module name resolution.
* if implementation is omitted then language service will use built-in module resolution logic and get answers to
* host specific questions using 'getScriptSnapshot'.
*/
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
directoryExists?(directoryName: string): boolean;
/*
* getDirectories is also required for full import and type reference completions. Without it defined, certain
* completions will not be provided
*/
getDirectories?(directoryName: string): string[];
}
//
// Public services of a language service instance associated
// with a language service host instance
//
export interface LanguageService {
cleanupSemanticCache(): void;
getSyntacticDiagnostics(fileName: string): Diagnostic[];
getSemanticDiagnostics(fileName: string): Diagnostic[];
// TODO: Rename this to getProgramDiagnostics to better indicate that these are any
// diagnostics present for the program level, and not just 'options' diagnostics.
getCompilerOptionsDiagnostics(): Diagnostic[];
/**
* @deprecated Use getEncodedSyntacticClassifications instead.
*/
getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
/**
* @deprecated Use getEncodedSemanticClassifications instead.
*/
getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
// Encoded as triples of [start, length, ClassificationType].
getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications;
getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications;
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo;
getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails;
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo;
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan;
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan;
getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems;
getRenameInfo(fileName: string, position: number): RenameInfo;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[];
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
findReferences(fileName: string, position: number): ReferencedSymbol[];
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[];
/** @deprecated */
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[];
getNavigationBarItems(fileName: string): NavigationBarItem[];
getOutliningSpans(fileName: string): OutliningSpan[];
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[];
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[];
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[];
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
getEmitOutput(fileName: string): EmitOutput;
getProgram(): Program;
/* @internal */ getNonBoundSourceFile(fileName: string): SourceFile;
dispose(): void;
}
export interface Classifications {
spans: number[];
endOfLineState: EndOfLineState;
}
export interface ClassifiedSpan {
textSpan: TextSpan;
classificationType: string; // ClassificationTypeNames
}
export interface NavigationBarItem {
text: string;
kind: string;
kindModifiers: string;
spans: TextSpan[];
childItems: NavigationBarItem[];
indent: number;
bolded: boolean;
grayed: boolean;
}
export interface TodoCommentDescriptor {
text: string;
priority: number;
}
export interface TodoComment {
descriptor: TodoCommentDescriptor;
message: string;
position: number;
}
export class TextChange {
span: TextSpan;
newText: string;
}
export interface TextInsertion {
newText: string;
/** The position in newText the caret should point to after the insertion. */
caretOffset: number;
}
export interface RenameLocation {
textSpan: TextSpan;
fileName: string;
}
export interface ReferenceEntry {
textSpan: TextSpan;
fileName: string;
isWriteAccess: boolean;
isDefinition: boolean;
}
export interface DocumentHighlights {
fileName: string;
highlightSpans: HighlightSpan[];
}
export namespace HighlightSpanKind {
export const none = "none";
export const definition = "definition";
export const reference = "reference";
export const writtenReference = "writtenReference";
}
export interface HighlightSpan {
fileName?: string;
textSpan: TextSpan;
kind: string;
}
export interface NavigateToItem {
name: string;
kind: string;
kindModifiers: string;
matchKind: string;
isCaseSensitive: boolean;
fileName: string;
textSpan: TextSpan;
containerName: string;
containerKind: string;
}
export interface EditorOptions {
BaseIndentSize?: number;
IndentSize: number;
TabSize: number;
NewLineCharacter: string;
ConvertTabsToSpaces: boolean;
IndentStyle: IndentStyle;
}
export enum IndentStyle {
None = 0,
Block = 1,
Smart = 2,
}
export interface FormatCodeOptions extends EditorOptions {
InsertSpaceAfterCommaDelimiter: boolean;
InsertSpaceAfterSemicolonInForStatements: boolean;
InsertSpaceBeforeAndAfterBinaryOperators: boolean;
InsertSpaceAfterKeywordsInControlFlowStatements: boolean;
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean;
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean;
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean;
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean;
InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
PlaceOpenBraceOnNewLineForFunctions: boolean;
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
[s: string]: boolean | number | string | undefined;
}
export interface DefinitionInfo {
fileName: string;
textSpan: TextSpan;
kind: string;
name: string;
containerKind: string;
containerName: string;
}
export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo {
displayParts: SymbolDisplayPart[];
}
export interface ReferencedSymbol {
definition: ReferencedSymbolDefinitionInfo;
references: ReferenceEntry[];
}
export enum SymbolDisplayPartKind {
aliasName,
className,
enumName,
fieldName,
interfaceName,
keyword,
lineBreak,
numericLiteral,
stringLiteral,
localName,
methodName,
moduleName,
operator,
parameterName,
propertyName,
punctuation,
space,
text,
typeParameterName,
enumMemberName,
functionName,
regularExpressionLiteral,
}
export interface SymbolDisplayPart {
text: string;
kind: string;
}
export interface QuickInfo {
kind: string;
kindModifiers: string;
textSpan: TextSpan;
displayParts: SymbolDisplayPart[];
documentation: SymbolDisplayPart[];
}
export interface RenameInfo {
canRename: boolean;
localizedErrorMessage: string;
displayName: string;
fullDisplayName: string;
kind: string;
kindModifiers: string;
triggerSpan: TextSpan;
}
export interface SignatureHelpParameter {
name: string;
documentation: SymbolDisplayPart[];
displayParts: SymbolDisplayPart[];
isOptional: boolean;
}
/**
* Represents a single signature to show in signature help.
* The id is used for subsequent calls into the language service to ask questions about the
* signature help item in the context of any documents that have been updated. i.e. after
* an edit has happened, while signature help is still active, the host can ask important
* questions like 'what parameter is the user currently contained within?'.
*/
export interface SignatureHelpItem {
isVariadic: boolean;
prefixDisplayParts: SymbolDisplayPart[];
suffixDisplayParts: SymbolDisplayPart[];
separatorDisplayParts: SymbolDisplayPart[];
parameters: SignatureHelpParameter[];
documentation: SymbolDisplayPart[];
}
/**
* Represents a set of signature help items, and the preferred item that should be selected.
*/
export interface SignatureHelpItems {
items: SignatureHelpItem[];
applicableSpan: TextSpan;
selectedItemIndex: number;
argumentIndex: number;
argumentCount: number;
}
export interface CompletionInfo {
isMemberCompletion: boolean;
isNewIdentifierLocation: boolean; // true when the current location also allows for a new identifier
entries: CompletionEntry[];
}
export interface CompletionEntry {
name: string;
kind: string; // see ScriptElementKind
kindModifiers: string; // see ScriptElementKindModifier, comma separated
sortText: string;
/**
* An optional span that indicates the text to be replaced by this completion item. It will be
* set if the required span differs from the one generated by the default replacement behavior and should
* be used in that case
*/
replacementSpan?: TextSpan;
}
export interface CompletionEntryDetails {
name: string;
kind: string; // see ScriptElementKind
kindModifiers: string; // see ScriptElementKindModifier, comma separated
displayParts: SymbolDisplayPart[];
documentation: SymbolDisplayPart[];
}
export interface OutliningSpan {
/** The span of the document to actually collapse. */
textSpan: TextSpan;
/** The span of the document to display when the user hovers over the collapsed span. */
hintSpan: TextSpan;
/** The text to display in the editor for the collapsed region. */
bannerText: string;
/**
* Whether or not this region should be automatically collapsed when
* the 'Collapse to Definitions' command is invoked.
*/
autoCollapse: boolean;
}
export interface EmitOutput {
outputFiles: OutputFile[];
emitSkipped: boolean;
}
export const enum OutputFileType {
JavaScript,
SourceMap,
Declaration
}
export interface OutputFile {
name: string;
writeByteOrderMark: boolean;
text: string;
}
export const enum EndOfLineState {
None,
InMultiLineCommentTrivia,
InSingleQuoteStringLiteral,
InDoubleQuoteStringLiteral,
InTemplateHeadOrNoSubstitutionTemplate,
InTemplateMiddleOrTail,
InTemplateSubstitutionPosition,
}
export enum TokenClass {
Punctuation,
Keyword,
Operator,
Comment,
Whitespace,
Identifier,
NumberLiteral,
StringLiteral,
RegExpLiteral,
}
export interface ClassificationResult {
finalLexState: EndOfLineState;
entries: ClassificationInfo[];
}
export interface ClassificationInfo {
length: number;
classification: TokenClass;
}
export interface Classifier {
/**
* Gives lexical classifications of tokens on a line without any syntactic context.
* For instance, a token consisting of the text 'string' can be either an identifier
* named 'string' or the keyword 'string', however, because this classifier is not aware,
* it relies on certain heuristics to give acceptable results. For classifications where
* speed trumps accuracy, this function is preferable; however, for true accuracy, the
* syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
* lexical, syntactic, and semantic classifiers may issue the best user experience.
*
* @param text The text of a line to classify.
* @param lexState The state of the lexical classifier at the end of the previous line.
* @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
* If there is no syntactic classifier (syntacticClassifierAbsent=true),
* certain heuristics may be used in its place; however, if there is a
* syntactic classifier (syntacticClassifierAbsent=false), certain
* classifications which may be incorrectly categorized will be given
* back as Identifiers in order to allow the syntactic classifier to
* subsume the classification.
* @deprecated Use getLexicalClassifications instead.
*/
getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications;
}
/**
* The document registry represents a store of SourceFile objects that can be shared between
* multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
* of files in the context.
* SourceFile objects account for most of the memory usage by the language service. Sharing
* the same DocumentRegistry instance between different instances of LanguageService allow
* for more efficient memory utilization since all projects will share at least the library
* file (lib.d.ts).
*
* A more advanced use of the document registry is to serialize sourceFile objects to disk
* and re-hydrate them when needed.
*
* To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it
* to all subsequent createLanguageService calls.
*/
export interface DocumentRegistry {
/**
* Request a stored SourceFile with a given fileName and compilationSettings.
* The first call to acquire will call createLanguageServiceSourceFile to generate
* the SourceFile if was not found in the registry.
*
* @param fileName The name of the file requested
* @param compilationSettings Some compilation settings like target affects the
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
* multiple copies of the same file for different compilation settings.
* @parm scriptSnapshot Text of the file. Only used if the file was not found
* in the registry and a new one was created.
* @parm version Current version of the file. Only used if the file was not found
* in the registry and a new one was created.
*/
acquireDocument(
fileName: string,
compilationSettings: CompilerOptions,
scriptSnapshot: IScriptSnapshot,
version: string,
scriptKind?: ScriptKind): SourceFile;
acquireDocumentWithKey(
fileName: string,
path: Path,
compilationSettings: CompilerOptions,
key: DocumentRegistryBucketKey,
scriptSnapshot: IScriptSnapshot,
version: string,
scriptKind?: ScriptKind): SourceFile;
/**
* Request an updated version of an already existing SourceFile with a given fileName
* and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile
* to get an updated SourceFile.
*
* @param fileName The name of the file requested
* @param compilationSettings Some compilation settings like target affects the
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
* multiple copies of the same file for different compilation settings.
* @param scriptSnapshot Text of the file.
* @param version Current version of the file.
*/
updateDocument(
fileName: string,
compilationSettings: CompilerOptions,
scriptSnapshot: IScriptSnapshot,
version: string,
scriptKind?: ScriptKind): SourceFile;
updateDocumentWithKey(
fileName: string,
path: Path,
compilationSettings: CompilerOptions,
key: DocumentRegistryBucketKey,
scriptSnapshot: IScriptSnapshot,
version: string,
scriptKind?: ScriptKind): SourceFile;
getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey;
/**
* Informs the DocumentRegistry that a file is not needed any longer.
*
* Note: It is not allowed to call release on a SourceFile that was not acquired from
* this registry originally.
*
* @param fileName The name of the file to be released
* @param compilationSettings The compilation settings used to acquire the file
*/
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void;
reportStats(): string;
}
export type DocumentRegistryBucketKey = string & { __bucketKey: any };
// TODO: move these to enums
export namespace ScriptElementKind {
export const unknown = "";
export const warning = "warning";
/** predefined type (void) or keyword (class) */
export const keyword = "keyword";
/** top level script node */
export const scriptElement = "script";
/** module foo {} */
export const moduleElement = "module";
/** class X {} */
export const classElement = "class";
/** var x = class X {} */
export const localClassElement = "local class";
/** interface Y {} */
export const interfaceElement = "interface";
/** type T = ... */
export const typeElement = "type";
/** enum E */
export const enumElement = "enum";
// TODO: GH#9983
export const enumMemberElement = "const";
/**
* Inside module and script only
* const v = ..
*/
export const variableElement = "var";
/** Inside function */
export const localVariableElement = "local var";
/**
* Inside module and script only
* function f() { }
*/
export const functionElement = "function";
/** Inside function */
export const localFunctionElement = "local function";
/** class X { [public|private]* foo() {} } */
export const memberFunctionElement = "method";
/** class X { [public|private]* [get|set] foo:number; } */
export const memberGetAccessorElement = "getter";
export const memberSetAccessorElement = "setter";
/**
* class X { [public|private]* foo:number; }
* interface Y { foo:number; }
*/
export const memberVariableElement = "property";
/** class X { constructor() { } } */
export const constructorImplementationElement = "constructor";
/** interface Y { ():number; } */
export const callSignatureElement = "call";
/** interface Y { []:number; } */
export const indexSignatureElement = "index";
/** interface Y { new():Y; } */
export const constructSignatureElement = "construct";
/** function foo(*Y*: string) */
export const parameterElement = "parameter";
export const typeParameterElement = "type parameter";
export const primitiveType = "primitive type";
export const label = "label";
export const alias = "alias";
export const constElement = "const";
export const letElement = "let";
export const directory = "directory";
export const externalModuleName = "external module name";
}
export namespace ScriptElementKindModifier {
export const none = "";
export const publicMemberModifier = "public";
export const privateMemberModifier = "private";
export const protectedMemberModifier = "protected";
export const exportedModifier = "export";
export const ambientModifier = "declare";
export const staticModifier = "static";
export const abstractModifier = "abstract";
}
export class ClassificationTypeNames {
public static comment = "comment";
public static identifier = "identifier";
public static keyword = "keyword";
public static numericLiteral = "number";
public static operator = "operator";
public static stringLiteral = "string";
public static whiteSpace = "whitespace";
public static text = "text";
public static punctuation = "punctuation";
public static className = "class name";
public static enumName = "enum name";
public static interfaceName = "interface name";
public static moduleName = "module name";
public static typeParameterName = "type parameter name";
public static typeAliasName = "type alias name";
public static parameterName = "parameter name";
public static docCommentTagName = "doc comment tag name";
public static jsxOpenTagName = "jsx open tag name";
public static jsxCloseTagName = "jsx close tag name";
public static jsxSelfClosingTagName = "jsx self closing tag name";
public static jsxAttribute = "jsx attribute";
public static jsxText = "jsx text";
public static jsxAttributeStringLiteralValue = "jsx attribute string literal value";
}
export const enum ClassificationType {
comment = 1,
identifier = 2,
keyword = 3,
numericLiteral = 4,
operator = 5,
stringLiteral = 6,
regularExpressionLiteral = 7,
whiteSpace = 8,
text = 9,
punctuation = 10,
className = 11,
enumName = 12,
interfaceName = 13,
moduleName = 14,
typeParameterName = 15,
typeAliasName = 16,
parameterName = 17,
docCommentTagName = 18,
jsxOpenTagName = 19,
jsxCloseTagName = 20,
jsxSelfClosingTagName = 21,
jsxAttribute = 22,
jsxText = 23,
jsxAttributeStringLiteralValue = 24,
}
}
+28 -1
View File
@@ -1,6 +1,9 @@
// These utilities are common to multiple language service features.
/* @internal */
namespace ts {
// Matches the beginning of a triple slash directive
const tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</;
export interface ListItemInfo {
listItemIndex: number;
list: Node;
@@ -704,6 +707,29 @@ namespace ts {
return false;
}
export function hasTrailingDirectorySeparator(path: string) {
const lastCharacter = path.charAt(path.length - 1);
return lastCharacter === "/" || lastCharacter === "\\";
}
export function isInReferenceComment(sourceFile: SourceFile, position: number): boolean {
return isInCommentHelper(sourceFile, position, isReferenceComment);
function isReferenceComment(c: CommentRange): boolean {
const commentText = sourceFile.text.substring(c.pos, c.end);
return tripleSlashDirectivePrefixRegex.test(commentText);
}
}
export function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean {
return isInCommentHelper(sourceFile, position, isNonReferenceComment);
function isNonReferenceComment(c: CommentRange): boolean {
const commentText = sourceFile.text.substring(c.pos, c.end);
return !tripleSlashDirectivePrefixRegex.test(commentText);
}
}
}
// Display-part writer helpers
@@ -930,7 +956,8 @@ namespace ts {
const options: TranspileOptions = {
fileName: "config.js",
compilerOptions: {
target: ScriptTarget.ES6
target: ScriptTarget.ES6,
removeComments: true
},
reportDiagnostics: true
};
@@ -1,8 +1,8 @@
EmitSkipped: true
Diagnostics:
Cannot write file 'tests/cases/fourslash/b.js' because it would overwrite input file.
Cannot write file '/tests/cases/fourslash/b.js' because it would overwrite input file.
EmitSkipped: false
FileName : tests/cases/fourslash/a.js
FileName : /tests/cases/fourslash/a.js
function foo2() { return 30; } // no error - should emit a.js
@@ -0,0 +1,16 @@
tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts(4,1): error TS1238: Unable to resolve signature of class decorator when called as an expression.
Cannot invoke an expression whose type lacks a call signature.
==== tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts (1 errors) ====
class CtorDtor {}
@CtorDtor
~~~~~~~~~
!!! error TS1238: Unable to resolve signature of class decorator when called as an expression.
!!! error TS1238: Cannot invoke an expression whose type lacks a call signature.
class C {
}
@@ -0,0 +1,30 @@
//// [constructableDecoratorOnClass01.ts]
class CtorDtor {}
@CtorDtor
class C {
}
//// [constructableDecoratorOnClass01.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var CtorDtor = (function () {
function CtorDtor() {
}
return CtorDtor;
}());
var C = (function () {
function C() {
}
return C;
}());
C = __decorate([
CtorDtor
], C);
@@ -0,0 +1,13 @@
=== tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts ===
class CtorDtor {}
>CtorDtor : Symbol(CtorDtor, Decl(constructableDecoratorOnClass01.ts, 0, 0))
@CtorDtor
>CtorDtor : Symbol(CtorDtor, Decl(constructableDecoratorOnClass01.ts, 0, 0))
class C {
>C : Symbol(C, Decl(constructableDecoratorOnClass01.ts, 1, 17))
}
@@ -0,0 +1,13 @@
=== tests/cases/conformance/decorators/class/constructableDecoratorOnClass01.ts ===
class CtorDtor {}
>CtorDtor : CtorDtor
@CtorDtor
>CtorDtor : typeof CtorDtor
class C {
>C : C
}
@@ -247,7 +247,7 @@ export declare class ConstructorWithPrivateParameterProperty {
constructor(x: string);
}
export declare class ConstructorWithOptionalParameterProperty {
x?: string;
x: string;
constructor(x?: string);
}
export declare class ConstructorWithParameterInitializer {
@@ -281,7 +281,7 @@ declare class GlobalConstructorWithPrivateParameterProperty {
constructor(x: string);
}
declare class GlobalConstructorWithOptionalParameterProperty {
x?: string;
x: string;
constructor(x?: string);
}
declare class GlobalConstructorWithParameterInitializer {
@@ -0,0 +1,9 @@
tests/cases/compiler/errorForConflictingExportEqualsValue.ts(2,1): error TS2309: An export assignment cannot be used in a module with other exported elements.
==== tests/cases/compiler/errorForConflictingExportEqualsValue.ts (1 errors) ====
export var x;
export = {};
~~~~~~~~~~~~
!!! error TS2309: An export assignment cannot be used in a module with other exported elements.
@@ -0,0 +1,8 @@
//// [errorForConflictingExportEqualsValue.ts]
export var x;
export = {};
//// [errorForConflictingExportEqualsValue.js]
"use strict";
module.exports = {};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,12 +1,12 @@
EmitSkipped: false
FileName : tests/cases/fourslash/shims-pp/inputFile1.js
FileName : /tests/cases/fourslash/shims-pp/inputFile1.js
var x = 5;
var Bar = (function () {
function Bar() {
}
return Bar;
}());
FileName : tests/cases/fourslash/shims-pp/inputFile1.d.ts
FileName : /tests/cases/fourslash/shims-pp/inputFile1.d.ts
declare var x: number;
declare class Bar {
x: string;
@@ -14,14 +14,14 @@ declare class Bar {
}
EmitSkipped: false
FileName : tests/cases/fourslash/shims-pp/inputFile2.js
FileName : /tests/cases/fourslash/shims-pp/inputFile2.js
var x1 = "hello world";
var Foo = (function () {
function Foo() {
}
return Foo;
}());
FileName : tests/cases/fourslash/shims-pp/inputFile2.d.ts
FileName : /tests/cases/fourslash/shims-pp/inputFile2.d.ts
declare var x1: string;
declare class Foo {
x: string;
@@ -1,12 +1,12 @@
EmitSkipped: false
FileName : tests/cases/fourslash/shims/inputFile1.js
FileName : /tests/cases/fourslash/shims/inputFile1.js
var x = 5;
var Bar = (function () {
function Bar() {
}
return Bar;
}());
FileName : tests/cases/fourslash/shims/inputFile1.d.ts
FileName : /tests/cases/fourslash/shims/inputFile1.d.ts
declare var x: number;
declare class Bar {
x: string;
@@ -14,14 +14,14 @@ declare class Bar {
}
EmitSkipped: false
FileName : tests/cases/fourslash/shims/inputFile2.js
FileName : /tests/cases/fourslash/shims/inputFile2.js
var x1 = "hello world";
var Foo = (function () {
function Foo() {
}
return Foo;
}());
FileName : tests/cases/fourslash/shims/inputFile2.d.ts
FileName : /tests/cases/fourslash/shims/inputFile2.d.ts
declare var x1: string;
declare class Foo {
x: string;
@@ -1,12 +1,12 @@
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile1.js
FileName : /tests/cases/fourslash/inputFile1.js
var x = 5;
var Bar = (function () {
function Bar() {
}
return Bar;
}());
FileName : tests/cases/fourslash/inputFile1.d.ts
FileName : /tests/cases/fourslash/inputFile1.d.ts
declare var x: number;
declare class Bar {
x: string;
@@ -14,14 +14,14 @@ declare class Bar {
}
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile2.js
FileName : /tests/cases/fourslash/inputFile2.js
var x1 = "hello world";
var Foo = (function () {
function Foo() {
}
return Foo;
}());
FileName : tests/cases/fourslash/inputFile2.d.ts
FileName : /tests/cases/fourslash/inputFile2.d.ts
declare var x1: string;
declare class Foo {
x: string;
@@ -1,5 +1,5 @@
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile.js
FileName : /tests/cases/fourslash/inputFile.js
var x;
var M = (function () {
function M() {
@@ -1,5 +1,5 @@
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile2.js
FileName : /tests/cases/fourslash/inputFile2.js
var x;
var Foo = (function () {
function Foo() {
@@ -1,6 +1,6 @@
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile.js.map
{"version":3,"file":"inputFile.js","sourceRoot":"","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : tests/cases/fourslash/inputFile.js
FileName : /tests/cases/fourslash/inputFile.js.map
{"version":3,"file":"inputFile.js","sourceRoot":"","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile.js
var x = 109;
var foo = "hello world";
var M = (function () {
@@ -1,6 +1,6 @@
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile.js.map
{"version":3,"file":"inputFile.js","sourceRoot":"sourceRootDir/","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : tests/cases/fourslash/inputFile.js
FileName : /tests/cases/fourslash/inputFile.js.map
{"version":3,"file":"inputFile.js","sourceRoot":"sourceRootDir/","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile.js
var x = 109;
var foo = "hello world";
var M = (function () {
@@ -1,6 +1,6 @@
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile1.js.map
{"version":3,"file":"inputFile1.js","sourceRoot":"sourceRootDir/","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : tests/cases/fourslash/inputFile1.js
FileName : /tests/cases/fourslash/inputFile1.js.map
{"version":3,"file":"inputFile1.js","sourceRoot":"sourceRootDir/","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile1.js
var x = 109;
var foo = "hello world";
var M = (function () {
@@ -10,8 +10,8 @@ var M = (function () {
}());
//# sourceMappingURL=inputFile1.js.map
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile2.js.map
{"version":3,"file":"inputFile2.js","sourceRoot":"sourceRootDir/","sources":["inputFile2.ts"],"names":[],"mappings":"AAAA,IAAI,GAAG,GAAG,wBAAwB,CAAC;AACnC;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : tests/cases/fourslash/inputFile2.js
FileName : /tests/cases/fourslash/inputFile2.js.map
{"version":3,"file":"inputFile2.js","sourceRoot":"sourceRootDir/","sources":["inputFile2.ts"],"names":[],"mappings":"AAAA,IAAI,GAAG,GAAG,wBAAwB,CAAC;AACnC;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile2.js
var bar = "hello world Typescript";
var C = (function () {
function C() {
@@ -1,6 +1,6 @@
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile1.js.map
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,kBAAkB;AACjB,IAAI,CAAC,GAAW,CAAC,CAAC;AAClB;IAAA;IAGA,CAAC;IAAD,UAAC;AAAD,CAAC,AAHD,IAGC"}FileName : tests/cases/fourslash/inputFile1.js
FileName : /tests/cases/fourslash/inputFile1.js.map
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,kBAAkB;AACjB,IAAI,CAAC,GAAW,CAAC,CAAC;AAClB;IAAA;IAGA,CAAC;IAAD,UAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile1.js
// regular ts file
var t = 5;
var Bar = (function () {
@@ -8,7 +8,7 @@ var Bar = (function () {
}
return Bar;
}());
//# sourceMappingURL=inputFile1.js.mapFileName : tests/cases/fourslash/inputFile1.d.ts
//# sourceMappingURL=inputFile1.js.mapFileName : /tests/cases/fourslash/inputFile1.d.ts
declare var t: number;
declare class Bar {
x: string;
@@ -16,11 +16,11 @@ declare class Bar {
}
EmitSkipped: false
FileName : tests/cases/fourslash/inputFile2.jsx.map
{"version":3,"file":"inputFile2.jsx","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,CAAC,CAAC,EAAG,CAAA"}FileName : tests/cases/fourslash/inputFile2.jsx
FileName : /tests/cases/fourslash/inputFile2.jsx.map
{"version":3,"file":"inputFile2.jsx","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,CAAC,CAAC,EAAG,CAAA"}FileName : /tests/cases/fourslash/inputFile2.jsx
var y = "my div";
var x = <div name={y}/>;
//# sourceMappingURL=inputFile2.jsx.mapFileName : tests/cases/fourslash/inputFile2.d.ts
//# sourceMappingURL=inputFile2.jsx.mapFileName : /tests/cases/fourslash/inputFile2.d.ts
declare var y: string;
declare var x: any;

Some files were not shown because too many files have changed in this diff Show More