diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 24ca7da87c4..70cbda14f6d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8277,8 +8277,8 @@ namespace ts { maybeStack[depth].set(id, RelationComparisonResult.Succeeded); depth++; const saveExpandingFlags = expandingFlags; - if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack, depth)) expandingFlags |= 1; - if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack, depth)) expandingFlags |= 2; + if (!(expandingFlags & 1) && isDeeplyNestedType(source, sourceStack, depth)) expandingFlags |= 1; + if (!(expandingFlags & 2) && isDeeplyNestedType(target, targetStack, depth)) expandingFlags |= 2; let result: Ternary; if (expandingFlags === 3) { result = Ternary.Maybe; @@ -8698,21 +8698,23 @@ namespace ts { return false; } - // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case - // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible, - // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding. - // Effectively, we will generate a false positive when two types are structurally equal to at least 10 levels, but unequal at - // some level beyond that. - function isDeeplyNestedGeneric(type: Type, stack: Type[], depth: number): boolean { - // We track type references (created by createTypeReference) and instantiated types (created by instantiateType) - if (getObjectFlags(type) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && depth >= 5) { + // Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons + // for 5 or more occurrences or instantiations of the type have been recorded on the given stack. It is possible, + // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely + // expanding. Effectively, we will generate a false positive when two types are structurally equal to at least 5 + // levels, but unequal at some level beyond that. + function isDeeplyNestedType(type: Type, stack: Type[], depth: number): boolean { + // We track all object types that have an associated symbol (representing the origin of the type) + if (depth >= 5 && type.flags & TypeFlags.Object) { const symbol = type.symbol; - let count = 0; - for (let i = 0; i < depth; i++) { - const t = stack[i]; - if (getObjectFlags(t) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && t.symbol === symbol) { - count++; - if (count >= 5) return true; + if (symbol) { + let count = 0; + for (let i = 0; i < depth; i++) { + const t = stack[i]; + if (t.flags & TypeFlags.Object && t.symbol === symbol) { + count++; + if (count >= 5) return true; + } } } } @@ -9455,7 +9457,7 @@ namespace ts { if (isInProcess(source, target)) { return; } - if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { + if (isDeeplyNestedType(source, sourceStack, depth) && isDeeplyNestedType(target, targetStack, depth)) { return; } const key = source.id + "," + target.id; @@ -18788,7 +18790,7 @@ namespace ts { // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeVariable)) { + if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeVariable | TypeFlags.NonPrimitive)) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 821402f1f06..da6125f3106 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3019,7 +3019,6 @@ namespace ts { ObjectLiteral = 1 << 7, // Originates in an object literal EvolvingArray = 1 << 8, // Evolving array type ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties - NonPrimitive = 1 << 10, // NonPrimitive object type ClassOrInterface = Class | Interface } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 5ea0df91caa..356a7a8962d 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1007,6 +1007,41 @@ namespace ts.projectSystem { checkProjectRootFiles(projectService.configuredProjects[0], [commonFile1.path, commonFile2.path]); }); + it("should disable features when the files are too large", () => { + const file1 = { + path: "/a/b/f1.js", + content: "let x =1;", + fileSize: 10 * 1024 * 1024 + }; + const file2 = { + path: "/a/b/f2.js", + content: "let y =1;", + fileSize: 6 * 1024 * 1024 + }; + const file3 = { + path: "/a/b/f3.js", + content: "let y =1;", + fileSize: 6 * 1024 * 1024 + }; + + const proj1name = "proj1", proj2name = "proj2", proj3name = "proj3"; + + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); + + projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name }); + const proj1 = projectService.findProject(proj1name); + assert.isTrue(proj1.languageServiceEnabled); + + projectService.openExternalProject({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name }); + const proj2 = projectService.findProject(proj2name); + assert.isTrue(proj2.languageServiceEnabled); + + projectService.openExternalProject({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name }); + const proj3 = projectService.findProject(proj3name); + assert.isFalse(proj3.languageServiceEnabled); + }); + it("should use only one inferred project if 'useOneInferredProject' is set", () => { const file1 = { path: "/a/b/main.ts", diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 5d4bb9ce6e4..348e52246a7 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -1396,6 +1396,7 @@ interface AudioNode extends EventTarget { readonly numberOfInputs: number; readonly numberOfOutputs: number; connect(destination: AudioNode, output?: number, input?: number): AudioNode; + connect(destination: AudioParam, output?: number): void; disconnect(output?: number): void; disconnect(destination: AudioNode, output?: number, input?: number): void; disconnect(destination: AudioParam, output?: number): void; @@ -2152,7 +2153,9 @@ interface CanvasRenderingContext2D extends Object, CanvasPathMethods { createPattern(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, repetition: string): CanvasPattern; createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient; drawFocusIfNeeded(element: Element): void; - drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, offsetX: number, offsetY: number, width?: number, height?: number, canvasOffsetX?: number, canvasOffsetY?: number, canvasImageWidth?: number, canvasImageHeight?: number): void; + drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number): void; + drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number, dstW: number, dstH: number): void; + drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, srcX: number, srcY: number, srcW: number, srcH: number, dstX: number, dstY: number, dstW: number, dstH: number): void; fill(fillRule?: string): void; fillRect(x: number, y: number, w: number, h: number): void; fillText(text: string, x: number, y: number, maxWidth?: number): void; @@ -2449,10 +2452,10 @@ declare var DOMException: { } interface DOMImplementation { - createDocument(namespaceURI: string | null, qualifiedName: string | null, doctype: DocumentType): Document; + createDocument(namespaceURI: string | null, qualifiedName: string | null, doctype: DocumentType | null): Document; createDocumentType(qualifiedName: string, publicId: string, systemId: string): DocumentType; createHTMLDocument(title: string): Document; - hasFeature(): boolean; + hasFeature(feature: string | null, version: string | null): boolean; } declare var DOMImplementation: { @@ -3449,6 +3452,7 @@ declare var Document: { } interface DocumentFragment extends Node, NodeSelector, ParentNode { + getElementById(elementId: string): HTMLElement | null; } declare var DocumentFragment: { @@ -11837,7 +11841,7 @@ interface URL { protocol: string; search: string; username: string; - readonly searchparams: URLSearchParams; + readonly searchParams: URLSearchParams; toString(): string; } @@ -12161,12 +12165,12 @@ interface WebGLRenderingContext { stencilMaskSeparate(face: number, mask: number): void; stencilOp(fail: number, zfail: number, zpass: number): void; stencilOpSeparate(face: number, fail: number, zfail: number, zpass: number): void; - texImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, format: number, type: number, pixels?: ArrayBufferView): void; - texImage2D(target: number, level: number, internalformat: number, format: number, type: number, pixels?: ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void; + texImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, format: number, type: number, pixels: ArrayBufferView | null): void; + texImage2D(target: number, level: number, internalformat: number, format: number, type: number, pixels: ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void; texParameterf(target: number, pname: number, param: number): void; texParameteri(target: number, pname: number, param: number): void; - texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, pixels?: ArrayBufferView): void; - texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, pixels?: ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void; + texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView | null): void; + texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, pixels: ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void; uniform1f(location: WebGLUniformLocation | null, x: number): void; uniform1fv(location: WebGLUniformLocation, v: Float32Array | number[]): void; uniform1i(location: WebGLUniformLocation | null, x: number): void; @@ -13260,6 +13264,8 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint; webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint; webkitRequestAnimationFrame(callback: FrameRequestCallback): number; + createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise; + createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise; scroll(options?: ScrollToOptions): void; scrollTo(options?: ScrollToOptions): void; scrollBy(options?: ScrollToOptions): void; @@ -13473,6 +13479,7 @@ interface Body { blob(): Promise; json(): Promise; text(): Promise; + formData(): Promise; } interface CanvasPathMethods { @@ -13835,6 +13842,21 @@ interface Canvas2DContextAttributes { [attribute: string]: boolean | string | undefined; } +interface ImageBitmapOptions { + imageOrientation?: "none" | "flipY"; + premultiplyAlpha?: "none" | "premultiply" | "default"; + colorSpaceConversion?: "none" | "default"; + resizeWidth?: number; + resizeHeight?: number; + resizeQuality?: "pixelated" | "low" | "medium" | "high"; +} + +interface ImageBitmap { + readonly width: number; + readonly height: number; + close(): void; +} + interface URLSearchParams { /** * Appends a specified key/value pair as a new search parameter. @@ -13879,6 +13901,7 @@ interface NodeListOf extends NodeList { interface HTMLCollectionOf extends HTMLCollection { item(index: number): T; namedItem(name: string): T; + [index: number]: T; } interface BlobPropertyBag { @@ -14840,6 +14863,8 @@ declare function webkitCancelAnimationFrame(handle: number): void; declare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint; declare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint; declare function webkitRequestAnimationFrame(callback: FrameRequestCallback): number; +declare function createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise; +declare function createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise; declare function scroll(options?: ScrollToOptions): void; declare function scrollTo(options?: ScrollToOptions): void; declare function scrollBy(options?: ScrollToOptions): void; diff --git a/src/lib/es2015.generator.d.ts b/src/lib/es2015.generator.d.ts index 2f522ad8770..5637ef816de 100644 --- a/src/lib/es2015.generator.d.ts +++ b/src/lib/es2015.generator.d.ts @@ -1,4 +1,29 @@ -interface GeneratorFunction extends Function { } +interface Generator extends Iterator { } + +interface GeneratorFunction { + /** + * Creates a new Generator object. + * @param args A list of arguments the function accepts. + */ + new (...args: any[]): Generator; + /** + * Creates a new Generator object. + * @param args A list of arguments the function accepts. + */ + (...args: any[]): Generator; + /** + * The length of the arguments. + */ + readonly length: number; + /** + * Returns the name of the function. + */ + readonly name: string; + /** + * A reference to the prototype. + */ + readonly prototype: Generator; +} interface GeneratorFunctionConstructor { /** @@ -6,7 +31,22 @@ interface GeneratorFunctionConstructor { * @param args A list of arguments the function accepts. */ new (...args: string[]): GeneratorFunction; + /** + * Creates a new Generator function. + * @param args A list of arguments the function accepts. + */ (...args: string[]): GeneratorFunction; + /** + * The length of the arguments. + */ + readonly length: number; + /** + * Returns the name of the function. + */ + readonly name: string; + /** + * A reference to the prototype. + */ readonly prototype: GeneratorFunction; } declare var GeneratorFunction: GeneratorFunctionConstructor; diff --git a/src/lib/es2015.symbol.wellknown.d.ts b/src/lib/es2015.symbol.wellknown.d.ts index 71e4cb7c893..5334dae9e01 100644 --- a/src/lib/es2015.symbol.wellknown.d.ts +++ b/src/lib/es2015.symbol.wellknown.d.ts @@ -137,7 +137,7 @@ interface Function { [Symbol.hasInstance](value: any): boolean; } -interface GeneratorFunction extends Function { +interface GeneratorFunction { readonly [Symbol.toStringTag]: "GeneratorFunction"; } diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index e9563db1bcd..326a3a9546e 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -1407,6 +1407,8 @@ interface WorkerGlobalScope extends EventTarget, WorkerUtils, WindowConsole, Glo readonly performance: Performance; readonly self: WorkerGlobalScope; msWriteProfilerMark(profilerMarkName: string): void; + createImageBitmap(image: ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise; + createImageBitmap(image: ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise; addEventListener(type: K, listener: (this: WorkerGlobalScope, ev: WorkerGlobalScopeEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -1467,6 +1469,21 @@ interface ErrorEventInit { error?: any; } +interface ImageBitmapOptions { + imageOrientation?: "none" | "flipY"; + premultiplyAlpha?: "none" | "premultiply" | "default"; + colorSpaceConversion?: "none" | "default"; + resizeWidth?: number; + resizeHeight?: number; + resizeQuality?: "pixelated" | "low" | "medium" | "high"; +} + +interface ImageBitmap { + readonly width: number; + readonly height: number; + close(): void; +} + interface BlobPropertyBag { type?: string; endings?: string; @@ -1697,6 +1714,8 @@ declare var onerror: (this: DedicatedWorkerGlobalScope, ev: ErrorEvent) => any; declare var performance: Performance; declare var self: WorkerGlobalScope; declare function msWriteProfilerMark(profilerMarkName: string): void; +declare function createImageBitmap(image: ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise; +declare function createImageBitmap(image: ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise; declare function dispatchEvent(evt: Event): boolean; declare function removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; declare var indexedDB: IDBFactory; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 397de9ead30..8af6fe5d347 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -254,6 +254,7 @@ namespace ts.server { private compilerOptionsForInferredProjects: CompilerOptions; private compileOnSaveForInferredProjects: boolean; + private readonly projectToSizeMap: Map = createMap(); private readonly directoryWatchers: DirectoryWatchers; private readonly throttledOperations: ThrottledOperations; @@ -563,9 +564,11 @@ namespace ts.server { switch (project.projectKind) { case ProjectKind.External: removeItemFromSet(this.externalProjects, project); + this.projectToSizeMap.delete((project as ExternalProject).externalProjectName); break; case ProjectKind.Configured: removeItemFromSet(this.configuredProjects, project); + this.projectToSizeMap.delete((project as ConfiguredProject).canonicalConfigFilePath); break; case ProjectKind.Inferred: removeItemFromSet(this.inferredProjects, project); @@ -852,10 +855,15 @@ namespace ts.server { return { success: true, projectOptions, configFileErrors: errors }; } - private exceededTotalSizeLimitForNonTsFiles(options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader) { + private exceededTotalSizeLimitForNonTsFiles(name: string, options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader) { if (options && options.disableSizeLimit || !this.host.getFileSize) { return false; } + + let availableSpace = maxProgramSizeForNonTsFiles; + this.projectToSizeMap.set(name, 0); + this.projectToSizeMap.forEach(val => (availableSpace -= (val || 0))); + let totalNonTsFileSize = 0; for (const f of fileNames) { const fileName = propertyReader.getFileName(f); @@ -864,9 +872,16 @@ namespace ts.server { } totalNonTsFileSize += this.host.getFileSize(fileName); if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) { + // Keep the size as zero since it's disabled return true; } } + + if (totalNonTsFileSize > availableSpace) { + return true; + } + + this.projectToSizeMap.set(name, totalNonTsFileSize); return false; } @@ -877,7 +892,7 @@ namespace ts.server { this, this.documentRegistry, compilerOptions, - /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, files, externalFilePropertyReader), + /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader), options.compileOnSave === undefined ? true : options.compileOnSave); this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typeAcquisition, /*configFileErrors*/ undefined); @@ -897,7 +912,7 @@ namespace ts.server { } private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, configFileErrors: Diagnostic[], clientFileName?: string) { - const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); + const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); const project = new ConfiguredProject( configFileName, this, @@ -1050,7 +1065,7 @@ namespace ts.server { return configFileErrors; } - if (this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader)) { + if (this.exceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader)) { project.setCompilerOptions(projectOptions.compilerOptions); if (!project.languageServiceEnabled) { // language service is already disabled @@ -1414,7 +1429,7 @@ namespace ts.server { if (externalProject) { if (!tsConfigFiles) { const compilerOptions = convertCompilerOptions(proj.options); - if (this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, proj.rootFiles, externalFilePropertyReader)) { + if (this.exceededTotalSizeLimitForNonTsFiles(proj.projectFileName, compilerOptions, proj.rootFiles, externalFilePropertyReader)) { externalProject.disableLanguageService(); } else { diff --git a/src/server/project.ts b/src/server/project.ts index 385816b1029..e57e605d65b 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1031,7 +1031,7 @@ namespace ts.server { export class ExternalProject extends Project { private typeAcquisition: TypeAcquisition; - constructor(externalProjectName: string, + constructor(public externalProjectName: string, projectService: ProjectService, documentRegistry: ts.DocumentRegistry, compilerOptions: CompilerOptions, diff --git a/src/server/session.ts b/src/server/session.ts index 8dd0411d077..11c99dfe46c 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -25,8 +25,14 @@ namespace ts.server { return ((1e9 * seconds) + nanoseconds) / 1000000.0; } - function shouldSkipSematicCheck(project: Project) { - return (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) && project.isJsOnlyProject(); + function shouldSkipSemanticCheck(project: Project) { + if (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) { + return project.isJsOnlyProject(); + } + else { + // For configured projects, require that skipLibCheck be set also + return project.getCompilerOptions().skipLibCheck && project.isJsOnlyProject(); + } } interface FileStart { @@ -447,7 +453,7 @@ namespace ts.server { private semanticCheck(file: NormalizedPath, project: Project) { try { let diags: Diagnostic[] = []; - if (!shouldSkipSematicCheck(project)) { + if (!shouldSkipSemanticCheck(project)) { diags = project.getLanguageService().getSemanticDiagnostics(file); } @@ -555,7 +561,7 @@ namespace ts.server { private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) { const { project, file } = this.getFileAndProject(args); - if (isSemantic && shouldSkipSematicCheck(project)) { + if (isSemantic && shouldSkipSemanticCheck(project)) { return []; } const scriptInfo = project.getScriptInfoForNormalizedPath(file); diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index b457165b67f..3fcc467f6ab 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -419,7 +419,7 @@ namespace ts.SymbolDisplay { if (!documentation) { documentation = symbol.getDocumentationComment(); if (documentation.length === 0 && symbol.flags & SymbolFlags.Property) { - // For some special property access expressions like `experts.foo = foo` or `module.exports.foo = foo` + // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo` // there documentation comments might be attached to the right hand side symbol of their declarations. // The pattern of such special property access is that the parent symbol is the symbol of the file. if (symbol.parent && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile)) { diff --git a/tests/baselines/reference/deeplyNestedCheck.js b/tests/baselines/reference/deeplyNestedCheck.js new file mode 100644 index 00000000000..466ae94f12d --- /dev/null +++ b/tests/baselines/reference/deeplyNestedCheck.js @@ -0,0 +1,14 @@ +//// [deeplyNestedCheck.ts] +// Repro from #14794 + +interface DataSnapshot { + child(path: string): DataSnapshot; +} + +interface Snapshot extends DataSnapshot { + child(path: U): Snapshot; +} + + +//// [deeplyNestedCheck.js] +// Repro from #14794 diff --git a/tests/baselines/reference/deeplyNestedCheck.symbols b/tests/baselines/reference/deeplyNestedCheck.symbols new file mode 100644 index 00000000000..a8b5af60880 --- /dev/null +++ b/tests/baselines/reference/deeplyNestedCheck.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/deeplyNestedCheck.ts === +// Repro from #14794 + +interface DataSnapshot { +>DataSnapshot : Symbol(DataSnapshot, Decl(deeplyNestedCheck.ts, 0, 0)) +>X : Symbol(X, Decl(deeplyNestedCheck.ts, 2, 23)) + + child(path: string): DataSnapshot; +>child : Symbol(DataSnapshot.child, Decl(deeplyNestedCheck.ts, 2, 32)) +>path : Symbol(path, Decl(deeplyNestedCheck.ts, 3, 8)) +>DataSnapshot : Symbol(DataSnapshot, Decl(deeplyNestedCheck.ts, 0, 0)) +} + +interface Snapshot extends DataSnapshot { +>Snapshot : Symbol(Snapshot, Decl(deeplyNestedCheck.ts, 4, 1)) +>T : Symbol(T, Decl(deeplyNestedCheck.ts, 6, 19)) +>DataSnapshot : Symbol(DataSnapshot, Decl(deeplyNestedCheck.ts, 0, 0)) + + child(path: U): Snapshot; +>child : Symbol(Snapshot.child, Decl(deeplyNestedCheck.ts, 6, 44)) +>U : Symbol(U, Decl(deeplyNestedCheck.ts, 7, 8)) +>T : Symbol(T, Decl(deeplyNestedCheck.ts, 6, 19)) +>path : Symbol(path, Decl(deeplyNestedCheck.ts, 7, 27)) +>U : Symbol(U, Decl(deeplyNestedCheck.ts, 7, 8)) +>Snapshot : Symbol(Snapshot, Decl(deeplyNestedCheck.ts, 4, 1)) +>T : Symbol(T, Decl(deeplyNestedCheck.ts, 6, 19)) +>U : Symbol(U, Decl(deeplyNestedCheck.ts, 7, 8)) +} + diff --git a/tests/baselines/reference/deeplyNestedCheck.types b/tests/baselines/reference/deeplyNestedCheck.types new file mode 100644 index 00000000000..e500fc75ed1 --- /dev/null +++ b/tests/baselines/reference/deeplyNestedCheck.types @@ -0,0 +1,29 @@ +=== tests/cases/compiler/deeplyNestedCheck.ts === +// Repro from #14794 + +interface DataSnapshot { +>DataSnapshot : DataSnapshot +>X : X + + child(path: string): DataSnapshot; +>child : (path: string) => DataSnapshot<{}> +>path : string +>DataSnapshot : DataSnapshot +} + +interface Snapshot extends DataSnapshot { +>Snapshot : Snapshot +>T : T +>DataSnapshot : DataSnapshot + + child(path: U): Snapshot; +>child : (path: U) => Snapshot +>U : U +>T : T +>path : U +>U : U +>Snapshot : Snapshot +>T : T +>U : U +} + diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForIn.js b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.js new file mode 100644 index 00000000000..c5f4319c748 --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.js @@ -0,0 +1,13 @@ +//// [nonPrimitiveIndexingWithForIn.ts] +var a: object; + +for (var key in a) { + var value = a[key]; +} + + +//// [nonPrimitiveIndexingWithForIn.js] +var a; +for (var key in a) { + var value = a[key]; +} diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForIn.symbols b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.symbols new file mode 100644 index 00000000000..3cb41269541 --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForIn.ts === +var a: object; +>a : Symbol(a, Decl(nonPrimitiveIndexingWithForIn.ts, 0, 3)) + +for (var key in a) { +>key : Symbol(key, Decl(nonPrimitiveIndexingWithForIn.ts, 2, 8)) +>a : Symbol(a, Decl(nonPrimitiveIndexingWithForIn.ts, 0, 3)) + + var value = a[key]; +>value : Symbol(value, Decl(nonPrimitiveIndexingWithForIn.ts, 3, 7)) +>a : Symbol(a, Decl(nonPrimitiveIndexingWithForIn.ts, 0, 3)) +>key : Symbol(key, Decl(nonPrimitiveIndexingWithForIn.ts, 2, 8)) +} + diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForIn.types b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.types new file mode 100644 index 00000000000..44e2b3f4d50 --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForIn.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForIn.ts === +var a: object; +>a : object + +for (var key in a) { +>key : string +>a : object + + var value = a[key]; +>value : any +>a[key] : any +>a : object +>key : string +} + diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForInNoImplicitAny.errors.txt b/tests/baselines/reference/nonPrimitiveIndexingWithForInNoImplicitAny.errors.txt new file mode 100644 index 00000000000..f7f2ee3db16 --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForInNoImplicitAny.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInNoImplicitAny.ts(4,17): error TS7017: Element implicitly has an 'any' type because type '{}' has no index signature. + + +==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInNoImplicitAny.ts (1 errors) ==== + var a: object; + + for (var key in a) { + var value = a[key]; // error + ~~~~~~ +!!! error TS7017: Element implicitly has an 'any' type because type '{}' has no index signature. + } + \ No newline at end of file diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForInNoImplicitAny.js b/tests/baselines/reference/nonPrimitiveIndexingWithForInNoImplicitAny.js new file mode 100644 index 00000000000..e105e5ba9bb --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForInNoImplicitAny.js @@ -0,0 +1,13 @@ +//// [nonPrimitiveIndexingWithForInNoImplicitAny.ts] +var a: object; + +for (var key in a) { + var value = a[key]; // error +} + + +//// [nonPrimitiveIndexingWithForInNoImplicitAny.js] +var a; +for (var key in a) { + var value = a[key]; // error +} diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.js b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.js new file mode 100644 index 00000000000..ce575b2a4d6 --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.js @@ -0,0 +1,13 @@ +//// [nonPrimitiveIndexingWithForInSupressError.ts] +var a: object; + +for (var key in a) { + var value = a[key]; +} + + +//// [nonPrimitiveIndexingWithForInSupressError.js] +var a; +for (var key in a) { + var value = a[key]; +} diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.symbols b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.symbols new file mode 100644 index 00000000000..4e52e66b1c0 --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInSupressError.ts === +var a: object; +>a : Symbol(a, Decl(nonPrimitiveIndexingWithForInSupressError.ts, 0, 3)) + +for (var key in a) { +>key : Symbol(key, Decl(nonPrimitiveIndexingWithForInSupressError.ts, 2, 8)) +>a : Symbol(a, Decl(nonPrimitiveIndexingWithForInSupressError.ts, 0, 3)) + + var value = a[key]; +>value : Symbol(value, Decl(nonPrimitiveIndexingWithForInSupressError.ts, 3, 7)) +>a : Symbol(a, Decl(nonPrimitiveIndexingWithForInSupressError.ts, 0, 3)) +>key : Symbol(key, Decl(nonPrimitiveIndexingWithForInSupressError.ts, 2, 8)) +} + diff --git a/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.types b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.types new file mode 100644 index 00000000000..3fafa40b596 --- /dev/null +++ b/tests/baselines/reference/nonPrimitiveIndexingWithForInSupressError.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInSupressError.ts === +var a: object; +>a : object + +for (var key in a) { +>key : string +>a : object + + var value = a[key]; +>value : any +>a[key] : any +>a : object +>key : string +} + diff --git a/tests/cases/compiler/deeplyNestedCheck.ts b/tests/cases/compiler/deeplyNestedCheck.ts new file mode 100644 index 00000000000..e95233af985 --- /dev/null +++ b/tests/cases/compiler/deeplyNestedCheck.ts @@ -0,0 +1,9 @@ +// Repro from #14794 + +interface DataSnapshot { + child(path: string): DataSnapshot; +} + +interface Snapshot extends DataSnapshot { + child(path: U): Snapshot; +} diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForIn.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForIn.ts new file mode 100644 index 00000000000..2ec8cf83cb7 --- /dev/null +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForIn.ts @@ -0,0 +1,5 @@ +var a: object; + +for (var key in a) { + var value = a[key]; +} diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInNoImplicitAny.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInNoImplicitAny.ts new file mode 100644 index 00000000000..1050cdea497 --- /dev/null +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInNoImplicitAny.ts @@ -0,0 +1,6 @@ +// @noImplicitAny: true +var a: object; + +for (var key in a) { + var value = a[key]; // error +} diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInSupressError.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInSupressError.ts new file mode 100644 index 00000000000..3f63faee604 --- /dev/null +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveIndexingWithForInSupressError.ts @@ -0,0 +1,7 @@ +// @noImplicitAny: true +// @suppressImplicitAnyIndexErrors: true +var a: object; + +for (var key in a) { + var value = a[key]; +}