Merge branch 'master' into esau-squash

This commit is contained in:
Ryan Cavanaugh
2018-06-14 13:23:15 -07:00
20 changed files with 283 additions and 62 deletions
+12 -4
View File
@@ -22601,6 +22601,10 @@ namespace ts {
checkSourceElement(node.typeExpression);
}
function checkJSDocTypeTag(node: JSDocTypeTag) {
checkSourceElement(node.typeExpression);
}
function checkJSDocParameterTag(node: JSDocParameterTag) {
checkSourceElement(node.typeExpression);
if (!getParameterSymbolFromJSDoc(node)) {
@@ -22895,7 +22899,11 @@ namespace ts {
}
for (const declaration of local.declarations) {
if (isAmbientModule(declaration)) continue;
if (isAmbientModule(declaration) ||
(isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderScore(declaration.name!)) {
continue;
}
if (isImportedDeclaration(declaration)) {
addToGroup(unusedImports, importClauseFromImported(declaration), declaration, getNodeId);
}
@@ -22907,9 +22915,7 @@ namespace ts {
}
}
else if (isVariableDeclaration(declaration)) {
if (!isIdentifierThatStartsWithUnderScore(declaration.name) || !isForInOrOfStatement(declaration.parent.parent)) {
addToGroup(unusedVariables, declaration.parent, declaration, getNodeId);
}
addToGroup(unusedVariables, declaration.parent, declaration, getNodeId);
}
else {
const parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration);
@@ -25560,6 +25566,8 @@ namespace ts {
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
return checkJSDocTypeAliasTag(node as JSDocTypedefTag);
case SyntaxKind.JSDocTypeTag:
return checkJSDocTypeTag(node as JSDocTypeTag);
case SyntaxKind.JSDocParameterTag:
return checkJSDocParameterTag(node as JSDocParameterTag);
case SyntaxKind.JSDocFunctionType:
+16 -9
View File
@@ -60,11 +60,14 @@ namespace ts {
watcher: FileWatcher;
/** ref count keeping this directory watch alive */
refCount: number;
/** is the directory watched being non recursive */
nonRecursive?: boolean;
}
interface DirectoryOfFailedLookupWatch {
dir: string;
dirPath: Path;
nonRecursive?: boolean;
ignore?: true;
}
@@ -251,7 +254,6 @@ namespace ts {
perDirectoryResolution = createMap();
perDirectoryCache.set(dirPath, perDirectoryResolution);
}
const resolvedModules: R[] = [];
const compilerOptions = resolutionHost.getCompilationSettings();
const hasInvalidatedNonRelativeUnresolvedImport = logChanges && isFileWithInvalidatedNonRelativeUnresolvedImports(path);
@@ -393,6 +395,7 @@ namespace ts {
function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch {
if (isInDirectoryPath(rootPath, failedLookupLocationPath)) {
// Always watch root directory recursively
return { dir: rootDir!, dirPath: rootPath }; // TODO: GH#18217
}
@@ -409,11 +412,12 @@ namespace ts {
dirPath = getDirectoryPath(dirPath);
}
// If the directory is node_modules use it to watch
// If the directory is node_modules use it to watch, always watch it recursively
if (isNodeModulesDirectory(dirPath)) {
return filterFSRootDirectoriesToWatch({ dir, dirPath }, getDirectoryPath(dirPath));
}
let nonRecursive = true;
// Use some ancestor of the root directory
let subDirectoryPath: Path | undefined, subDirectory: string | undefined;
if (rootPath !== undefined) {
@@ -422,6 +426,7 @@ namespace ts {
if (parentPath === dirPath) {
break;
}
nonRecursive = false;
subDirectoryPath = dirPath;
subDirectory = dir;
dirPath = parentPath;
@@ -429,7 +434,7 @@ namespace ts {
}
}
return filterFSRootDirectoriesToWatch({ dir: subDirectory || dir, dirPath: subDirectoryPath || dirPath }, dirPath);
return filterFSRootDirectoriesToWatch({ dir: subDirectory || dir, dirPath: subDirectoryPath || dirPath, nonRecursive }, dirPath);
}
function isPathWithDefaultFailedLookupExtension(path: Path) {
@@ -452,7 +457,7 @@ namespace ts {
let setAtRoot = false;
for (const failedLookupLocation of failedLookupLocations) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
const { dir, dirPath, nonRecursive, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (!ignore) {
// If the failed lookup location path is not one of the supported extensions,
// store it in the custom path
@@ -464,23 +469,25 @@ namespace ts {
setAtRoot = true;
}
else {
setDirectoryWatcher(dir, dirPath);
setDirectoryWatcher(dir, dirPath, nonRecursive);
}
}
}
if (setAtRoot) {
// This is always recursive
setDirectoryWatcher(rootDir!, rootPath); // TODO: GH#18217
}
}
function setDirectoryWatcher(dir: string, dirPath: Path) {
function setDirectoryWatcher(dir: string, dirPath: Path, nonRecursive?: boolean) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
if (dirWatcher) {
Debug.assert(!!nonRecursive === !!dirWatcher.nonRecursive);
dirWatcher.refCount++;
}
else {
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath, nonRecursive), refCount: 1, nonRecursive });
}
}
@@ -530,7 +537,7 @@ namespace ts {
dirWatcher.refCount--;
}
function createDirectoryWatcher(directory: string, dirPath: Path) {
function createDirectoryWatcher(directory: string, dirPath: Path, nonRecursive: boolean | undefined) {
return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, fileOrDirectory => {
const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory);
if (cachedDirectoryStructureHost) {
@@ -541,7 +548,7 @@ namespace ts {
if (!allFilesHaveInvalidatedResolution && invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath)) {
resolutionHost.onInvalidatedResolution();
}
}, WatchDirectoryFlags.Recursive);
}, nonRecursive ? WatchDirectoryFlags.None : WatchDirectoryFlags.Recursive);
}
function removeResolutionsOfFileFromCache(cache: Map<Map<ResolutionWithFailedLookupLocations>>, filePath: Path) {
+1 -1
View File
@@ -8010,7 +8010,7 @@ namespace ts {
}
export function tryGetExtensionFromPath(path: string): Extension | undefined {
return find<Extension>(supportedTypescriptExtensionsForExtractExtension, e => fileExtensionIs(path, e)) || find(supportedJavascriptExtensions, e => fileExtensionIs(path, e));
return find<Extension>(extensionsToRemove, e => fileExtensionIs(path, e));
}
function getAnyExtensionFromPathWorker(path: string, extensions: string | ReadonlyArray<string>, stringEqualityComparer: (a: string, b: string) => boolean) {
+11 -2
View File
@@ -507,8 +507,17 @@ namespace FourSlash {
}
private getAllDiagnostics(): ts.Diagnostic[] {
return ts.flatMap(this.languageServiceAdapterHost.getFilenames(), fileName =>
ts.isAnySupportedFileExtension(fileName) ? this.getDiagnostics(fileName) : []);
return ts.flatMap(this.languageServiceAdapterHost.getFilenames(), fileName => {
if (!ts.isAnySupportedFileExtension(fileName)) {
return [];
}
const baseName = ts.getBaseFileName(fileName);
if (baseName === "package.json" || baseName === "tsconfig.json" || baseName === "jsconfig.json") {
return [];
}
return this.getDiagnostics(fileName);
});
}
public verifyErrorExistsAfterMarker(markerName: string, shouldExist: boolean, after: boolean) {
+39
View File
@@ -2532,4 +2532,43 @@ declare module "fs" {
checkWatchedDirectoriesDetailed(host, [mainPackageRoot, linkedPackageRoot, `${mainPackageRoot}/node_modules/@types`, `${projectRoot}/node_modules/@types`], 1, /*recursive*/ true);
});
});
describe("tsc-watch with custom module resolution", () => {
const projectRoot = "/user/username/projects/project";
const configFileJson: any = {
compilerOptions: { module: "commonjs", resolveJsonModule: true },
files: ["index.ts"]
};
const mainFile: File = {
path: `${projectRoot}/index.ts`,
content: "import settings from './settings.json';"
};
const config: File = {
path: `${projectRoot}/tsconfig.json`,
content: JSON.stringify(configFileJson)
};
const settingsJson: File = {
path: `${projectRoot}/settings.json`,
content: JSON.stringify({ content: "Print this" })
};
it("verify that module resolution with json extension works when returned without extension", () => {
const files = [libFile, mainFile, config, settingsJson];
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
const compilerHost = createWatchCompilerHostOfConfigFile(config.path, {}, host);
const parsedCommandResult = parseJsonConfigFileContent(configFileJson, host, config.path);
compilerHost.resolveModuleNames = (moduleNames, containingFile) => moduleNames.map(m => {
const result = resolveModuleName(m, containingFile, parsedCommandResult.options, compilerHost);
const resolvedModule = result.resolvedModule!;
return {
resolvedFileName: resolvedModule.resolvedFileName,
isExternalLibraryImport: resolvedModule.isExternalLibraryImport,
originalFileName: resolvedModule.originalPath,
};
});
const watch = createWatchProgram(compilerHost);
const program = watch.getCurrentProgram().getProgram();
checkProgramActualFiles(program, [mainFile.path, libFile.path, settingsJson.path]);
});
});
}
@@ -8011,10 +8011,10 @@ new C();`
checkCompleteEvent(session, 2, expectedSequenceId);
}
function verifyWatchedFilesAndDirectories(host: TestServerHost, files: string[], directories: string[]) {
function verifyWatchedFilesAndDirectories(host: TestServerHost, files: string[], recursiveDirectories: string[], nonRecursiveDirectories: string[]) {
checkWatchedFilesDetailed(host, files.filter(f => f !== recognizersDateTimeSrcFile.path), 1);
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
checkWatchedDirectoriesDetailed(host, directories, 1, /*recursive*/ true);
checkWatchedDirectoriesDetailed(host, nonRecursiveDirectories, 1, /*recursive*/ false);
checkWatchedDirectoriesDetailed(host, recursiveDirectories, 1, /*recursive*/ true);
}
function createSessionAndOpenFile(host: TestServerHost) {
@@ -8035,14 +8035,15 @@ new C();`
const filesWithNodeModulesSetup = [...filesWithSources, nodeModulesRecorgnizersText];
const filesAfterCompilation = [...filesWithNodeModulesSetup, recongnizerTextDistTypingFile];
const watchedDirectoriesWithResolvedModule = [`${recognizersDateTime}/src`, withPathMapping ? packages : recognizersDateTime, ...getTypeRootsFromLocation(recognizersDateTime)];
const watchedDirectoriesWithResolvedModule = [`${recognizersDateTime}/src`, ...(withPathMapping ? emptyArray : [recognizersDateTime]), ...getTypeRootsFromLocation(recognizersDateTime)];
const watchedDirectoriesWithUnresolvedModule = [recognizersDateTime, ...(withPathMapping ? [recognizersText] : emptyArray), ...watchedDirectoriesWithResolvedModule, ...getNodeModuleDirectories(packages)];
const nonRecursiveWatchedDirectories = withPathMapping ? [packages] : emptyArray;
function verifyProjectWithResolvedModule(session: TestSession) {
const projectService = session.getProjectService();
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!;
checkProjectActualFiles(project, filesInProjectWithResolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithResolvedModule, watchedDirectoriesWithResolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithResolvedModule, watchedDirectoriesWithResolvedModule, nonRecursiveWatchedDirectories);
verifyErrors(session, []);
}
@@ -8050,7 +8051,7 @@ new C();`
const projectService = session.getProjectService();
const project = projectService.configuredProjects.get(recognizerDateTimeTsconfigPath)!;
checkProjectActualFiles(project, filesInProjectWithUnresolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithUnresolvedModule, watchedDirectoriesWithUnresolvedModule);
verifyWatchedFilesAndDirectories(session.host, filesInProjectWithUnresolvedModule, watchedDirectoriesWithUnresolvedModule, nonRecursiveWatchedDirectories);
const startOffset = recognizersDateTimeSrcFile.content.indexOf('"') + 1;
verifyErrors(session, [
createDiagnostic({ line: 1, offset: startOffset }, { line: 1, offset: startOffset + moduleNameInFile.length }, Diagnostics.Cannot_find_module_0, [moduleName])
@@ -8506,6 +8507,65 @@ new C();`
}
});
});
it("when watching directories for failed lookup locations in amd resolution", () => {
const projectRoot = "/user/username/projects/project";
const nodeFile: File = {
path: `${projectRoot}/src/typings/node.d.ts`,
content: `
declare module "fs" {
export interface something {
}
}`
};
const electronFile: File = {
path: `${projectRoot}/src/typings/electron.d.ts`,
content: `
declare module 'original-fs' {
import * as fs from 'fs';
export = fs;
}`
};
const srcFile: File = {
path: `${projectRoot}/src/somefolder/srcfile.ts`,
content: `
import { x } from "somefolder/module1";
import { x } from "somefolder/module2";
const y = x;`
};
const moduleFile: File = {
path: `${projectRoot}/src/somefolder/module1.ts`,
content: `
export const x = 10;`
};
const configFile: File = {
path: `${projectRoot}/src/tsconfig.json`,
content: JSON.stringify({
compilerOptions: {
module: "amd",
moduleResolution: "classic",
target: "es5",
outDir: "../out",
baseUrl: "./",
typeRoots: ["typings"]
}
})
};
const files = [nodeFile, electronFile, srcFile, moduleFile, configFile, libFile];
const host = createServerHost(files);
const service = createProjectService(host);
service.openClientFile(srcFile.path, srcFile.content, ScriptKind.TS, projectRoot);
checkProjectActualFiles(service.configuredProjects.get(configFile.path)!, files.map(f => f.path));
checkWatchedFilesDetailed(host, mapDefined(files, f => f === srcFile ? undefined : f.path), 1);
checkWatchedDirectoriesDetailed(host, [`${projectRoot}`], 1, /*recursive*/ false); // failed lookup for fs
const expectedWatchedDirectories = createMap<number>();
expectedWatchedDirectories.set(`${projectRoot}/src`, 2); // Wild card and failed lookup
expectedWatchedDirectories.set(`${projectRoot}/somefolder`, 1); // failed lookup for somefolder/module2
expectedWatchedDirectories.set(`${projectRoot}/node_modules`, 1); // failed lookup for with node_modules/@types/fs
expectedWatchedDirectories.set(`${projectRoot}/src/typings`, 1); // typeroot directory
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, /*recursive*/ true);
});
});
describe("tsserverProjectSystem watchDirectories implementation", () => {
@@ -0,0 +1,21 @@
tests/cases/conformance/jsdoc/test.js(5,14): error TS2344: Type 'number' does not satisfy the constraint 'string'.
tests/cases/conformance/jsdoc/test.js(7,14): error TS2344: Type 'number' does not satisfy the constraint 'string'.
==== tests/cases/conformance/jsdoc/t.d.ts (0 errors) ====
type A<T extends string> = { a: T }
==== tests/cases/conformance/jsdoc/test.js (2 errors) ====
/** Also should error for jsdoc typedefs
* @template {string} U
* @typedef {{ b: U }} B
*/
/** @type {A<number>} */
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'string'.
var a;
/** @type {B<number>} */
~~~~~~
!!! error TS2344: Type 'number' does not satisfy the constraint 'string'.
var b;
@@ -0,0 +1,20 @@
=== tests/cases/conformance/jsdoc/t.d.ts ===
type A<T extends string> = { a: T }
>A : Symbol(A, Decl(t.d.ts, 0, 0))
>T : Symbol(T, Decl(t.d.ts, 0, 7))
>a : Symbol(a, Decl(t.d.ts, 0, 28))
>T : Symbol(T, Decl(t.d.ts, 0, 7))
=== tests/cases/conformance/jsdoc/test.js ===
/** Also should error for jsdoc typedefs
* @template {string} U
* @typedef {{ b: U }} B
*/
/** @type {A<number>} */
var a;
>a : Symbol(a, Decl(test.js, 5, 3))
/** @type {B<number>} */
var b;
>b : Symbol(b, Decl(test.js, 7, 3))
@@ -0,0 +1,20 @@
=== tests/cases/conformance/jsdoc/t.d.ts ===
type A<T extends string> = { a: T }
>A : A<T>
>T : T
>a : T
>T : T
=== tests/cases/conformance/jsdoc/test.js ===
/** Also should error for jsdoc typedefs
* @template {string} U
* @typedef {{ b: U }} B
*/
/** @type {A<number>} */
var a;
>a : A<number>
/** @type {B<number>} */
var b;
>b : { b: number; }
@@ -1,11 +1,14 @@
tests/cases/compiler/example.js(3,20): error TS1110: Type expected.
tests/cases/compiler/example.js(3,21): error TS2304: Cannot find name 'foo'.
==== tests/cases/compiler/example.js (1 errors) ====
==== tests/cases/compiler/example.js (2 errors) ====
// @ts-check
/**
* @type {function(@foo)}
~
!!! error TS1110: Type expected.
~~~
!!! error TS2304: Cannot find name 'foo'.
*/
let x;
@@ -1,9 +1,11 @@
tests/cases/conformance/jsdoc/a.js(16,12): error TS2314: Generic type 'Everything' requires 5 type argument(s).
tests/cases/conformance/jsdoc/a.js(12,23): error TS2344: Type '{ a: number; }' does not satisfy the constraint '{ a: number; b: string; }'.
Property 'b' is missing in type '{ a: number; }'.
tests/cases/conformance/jsdoc/a.js(15,12): error TS2314: Generic type 'Everything' requires 5 type argument(s).
tests/cases/conformance/jsdoc/test.ts(1,34): error TS2344: Type '{ a: number; }' does not satisfy the constraint '{ a: number; b: string; }'.
Property 'b' is missing in type '{ a: number; }'.
==== tests/cases/conformance/jsdoc/a.js (1 errors) ====
==== tests/cases/conformance/jsdoc/a.js (2 errors) ====
/**
* @template {{ a: number, b: string }} T,U A Comment
* @template {{ c: boolean }} V uh ... are comments even supported??
@@ -15,8 +17,10 @@ tests/cases/conformance/jsdoc/test.ts(1,34): error TS2344: Type '{ a: number; }'
/** @type {Everything<{ a: number, b: 'hi', c: never }, undefined, { c: true, d: 1 }, number, string>} */
var tuvwx;
// TODO: will error when #24592 is fixed
/** @type {Everything<{ a: number }, undefined, { c: 1, d: 1 }, number, string>} */
~~~~~~~~~~~~~~
!!! error TS2344: Type '{ a: number; }' does not satisfy the constraint '{ a: number; b: string; }'.
!!! error TS2344: Property 'b' is missing in type '{ a: number; }'.
var wrong;
/** @type {Everything<{ a: number }>} */
@@ -11,14 +11,13 @@
var tuvwx;
>tuvwx : Symbol(tuvwx, Decl(a.js, 9, 3))
// TODO: will error when #24592 is fixed
/** @type {Everything<{ a: number }, undefined, { c: 1, d: 1 }, number, string>} */
var wrong;
>wrong : Symbol(wrong, Decl(a.js, 13, 3))
>wrong : Symbol(wrong, Decl(a.js, 12, 3))
/** @type {Everything<{ a: number }>} */
var insufficient;
>insufficient : Symbol(insufficient, Decl(a.js, 16, 3))
>insufficient : Symbol(insufficient, Decl(a.js, 15, 3))
=== tests/cases/conformance/jsdoc/test.ts ===
declare var actually: Everything<{ a: number }, undefined, { c: 1, d: 1 }, number, string>;
@@ -11,7 +11,6 @@
var tuvwx;
>tuvwx : { t: { a: number; b: "hi"; c: never; }; u: undefined; v: { c: true; d: 1; }; w: number; x: string; }
// TODO: will error when #24592 is fixed
/** @type {Everything<{ a: number }, undefined, { c: 1, d: 1 }, number, string>} */
var wrong;
>wrong : { t: { a: number; }; u: undefined; v: { c: 1; d: 1; }; w: number; x: string; }
@@ -1,12 +1,17 @@
tests/cases/compiler/unusedLocalsStartingWithUnderscore.ts(6,9): error TS6133: '_' is declared but its value is never read.
/a.ts(7,11): error TS6133: '_ns' is declared but its value is never read.
/a.ts(8,9): error TS6133: '_' is declared but its value is never read.
==== tests/cases/compiler/unusedLocalsStartingWithUnderscore.ts (1 errors) ====
==== /a.ts (2 errors) ====
import * as _ from "./a";
for (const _ of []) { }
for (const _ in []) { }
namespace M {
namespace _ns {
~~~
!!! error TS6133: '_ns' is declared but its value is never read.
let _;
~
!!! error TS6133: '_' is declared but its value is never read.
@@ -14,4 +19,4 @@ tests/cases/compiler/unusedLocalsStartingWithUnderscore.ts(6,9): error TS6133: '
for (const _ in []) { }
}
@@ -1,26 +1,30 @@
//// [unusedLocalsStartingWithUnderscore.ts]
//// [a.ts]
import * as _ from "./a";
for (const _ of []) { }
for (const _ in []) { }
namespace M {
namespace _ns {
let _;
for (const _ of []) { }
for (const _ in []) { }
}
//// [unusedLocalsStartingWithUnderscore.js]
//// [a.js]
"use strict";
exports.__esModule = true;
for (var _i = 0, _a = []; _i < _a.length; _i++) {
var _ = _a[_i];
var _1 = _a[_i];
}
for (var _ in []) { }
var M;
(function (M) {
for (var _2 in []) { }
var _ns;
(function (_ns) {
var _;
for (var _i = 0, _a = []; _i < _a.length; _i++) {
var _1 = _a[_i];
var _3 = _a[_i];
}
for (var _2 in []) { }
})(M || (M = {}));
for (var _4 in []) { }
})(_ns || (_ns = {}));
@@ -1,20 +1,23 @@
=== tests/cases/compiler/unusedLocalsStartingWithUnderscore.ts ===
=== /a.ts ===
import * as _ from "./a";
>_ : Symbol(_, Decl(a.ts, 0, 6))
for (const _ of []) { }
>_ : Symbol(_, Decl(unusedLocalsStartingWithUnderscore.ts, 0, 10))
>_ : Symbol(_, Decl(a.ts, 2, 10))
for (const _ in []) { }
>_ : Symbol(_, Decl(unusedLocalsStartingWithUnderscore.ts, 2, 10))
>_ : Symbol(_, Decl(a.ts, 4, 10))
namespace M {
>M : Symbol(M, Decl(unusedLocalsStartingWithUnderscore.ts, 2, 23))
namespace _ns {
>_ns : Symbol(_ns, Decl(a.ts, 4, 23))
let _;
>_ : Symbol(_, Decl(unusedLocalsStartingWithUnderscore.ts, 5, 7))
>_ : Symbol(_, Decl(a.ts, 7, 7))
for (const _ of []) { }
>_ : Symbol(_, Decl(unusedLocalsStartingWithUnderscore.ts, 6, 14))
>_ : Symbol(_, Decl(a.ts, 8, 14))
for (const _ in []) { }
>_ : Symbol(_, Decl(unusedLocalsStartingWithUnderscore.ts, 8, 14))
>_ : Symbol(_, Decl(a.ts, 10, 14))
}
@@ -1,4 +1,7 @@
=== tests/cases/compiler/unusedLocalsStartingWithUnderscore.ts ===
=== /a.ts ===
import * as _ from "./a";
>_ : typeof _
for (const _ of []) { }
>_ : any
>[] : undefined[]
@@ -7,8 +10,8 @@ for (const _ in []) { }
>_ : string
>[] : undefined[]
namespace M {
>M : typeof M
namespace _ns {
>_ns : typeof _ns
let _;
>_ : any
@@ -21,4 +24,4 @@ namespace M {
>_ : string
>[] : undefined[]
}
@@ -1,13 +1,15 @@
//@noUnusedLocals:true
// @noUnusedLocals:true
// @Filename: /a.ts
import * as _ from "./a";
for (const _ of []) { }
for (const _ in []) { }
namespace M {
namespace _ns {
let _;
for (const _ of []) { }
for (const _ in []) { }
}
@@ -0,0 +1,16 @@
// @checkJs: true
// @allowJs: true
// @noEmit: true
// @Filename: t.d.ts
type A<T extends string> = { a: T }
// @Filename: test.js
/** Also should error for jsdoc typedefs
* @template {string} U
* @typedef {{ b: U }} B
*/
/** @type {A<number>} */
var a;
/** @type {B<number>} */
var b;
@@ -13,7 +13,6 @@
/** @type {Everything<{ a: number, b: 'hi', c: never }, undefined, { c: true, d: 1 }, number, string>} */
var tuvwx;
// TODO: will error when #24592 is fixed
/** @type {Everything<{ a: number }, undefined, { c: 1, d: 1 }, number, string>} */
var wrong;