mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-27 23:58:38 -06:00
Merge branch 'master' into map4
This commit is contained in:
commit
867093707b
@ -1071,7 +1071,7 @@ namespace ts {
|
||||
|
||||
if (moduleSymbol) {
|
||||
let exportDefaultSymbol: Symbol;
|
||||
if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
|
||||
if (isUntypedModuleSymbol(moduleSymbol)) {
|
||||
exportDefaultSymbol = moduleSymbol;
|
||||
}
|
||||
else {
|
||||
@ -1151,7 +1151,7 @@ namespace ts {
|
||||
if (targetSymbol) {
|
||||
const name = specifier.propertyName || specifier.name;
|
||||
if (name.text) {
|
||||
if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
|
||||
if (isUntypedModuleSymbol(moduleSymbol)) {
|
||||
return moduleSymbol;
|
||||
}
|
||||
|
||||
@ -1371,8 +1371,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
const isRelative = isExternalModuleNameRelative(moduleName);
|
||||
const quotedName = '"' + moduleName + '"';
|
||||
if (!isRelative) {
|
||||
const symbol = getSymbol(globals, '"' + moduleName + '"', SymbolFlags.ValueModule);
|
||||
const symbol = getSymbol(globals, quotedName, SymbolFlags.ValueModule);
|
||||
if (symbol) {
|
||||
// merged symbol is module declaration symbol combined with all augmentations
|
||||
return getMergedSymbol(symbol);
|
||||
@ -1401,6 +1402,28 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// May be an untyped module. If so, ignore resolutionDiagnostic.
|
||||
if (!isRelative && resolvedModule && !extensionIsTypeScript(resolvedModule.extension)) {
|
||||
if (compilerOptions.noImplicitAny) {
|
||||
if (moduleNotFoundError) {
|
||||
error(errorNode,
|
||||
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,
|
||||
moduleReference,
|
||||
resolvedModule.resolvedFileName);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Create a new symbol to represent the untyped module and store it in globals.
|
||||
// This provides a name to the module. See the test tests/cases/fourslash/untypedModuleImport.ts
|
||||
const newSymbol = createSymbol(SymbolFlags.ValueModule, quotedName);
|
||||
// Module symbols are expected to have 'exports', although since this is an untyped module it can be empty.
|
||||
newSymbol.exports = new StringMap<Symbol>();
|
||||
// Cache it so subsequent accesses will return the same module.
|
||||
globals.set(quotedName, newSymbol);
|
||||
return newSymbol;
|
||||
}
|
||||
|
||||
if (moduleNotFoundError) {
|
||||
// report errors only if it was requested
|
||||
if (resolutionDiagnostic) {
|
||||
@ -3470,7 +3493,7 @@ namespace ts {
|
||||
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
if (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && isShorthandAmbientModuleSymbol(symbol)) {
|
||||
if (symbol.flags & SymbolFlags.Module && isUntypedModuleSymbol(symbol)) {
|
||||
links.type = anyType;
|
||||
}
|
||||
else {
|
||||
@ -19014,7 +19037,7 @@ namespace ts {
|
||||
|
||||
function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
|
||||
let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression);
|
||||
if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) {
|
||||
if (!moduleSymbol || isUntypedModuleSymbol(moduleSymbol)) {
|
||||
// If the module is not found or is shorthand, assume that it may export a value.
|
||||
return true;
|
||||
}
|
||||
@ -19514,7 +19537,7 @@ namespace ts {
|
||||
(typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective);
|
||||
}
|
||||
else {
|
||||
// found at least one entry that does not originate from type reference directive
|
||||
// found at least one entry that does not originate from type reference directive
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,6 +99,13 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function zipWith<T, U>(arrayA: T[], arrayB: U[], callback: (a: T, b: U, index: number) => void): void {
|
||||
Debug.assert(arrayA.length === arrayB.length);
|
||||
for (let i = 0; i < arrayA.length; i++) {
|
||||
callback(arrayA[i], arrayB[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through `array` by index and performs the callback on each element of array until the callback
|
||||
* returns a falsey value, then returns false.
|
||||
|
||||
@ -2901,6 +2901,10 @@
|
||||
"category": "Error",
|
||||
"code": 7015
|
||||
},
|
||||
"Could not find a declaration file for module '{0}'. '{1}' implicitly has an 'any' type.": {
|
||||
"category": "Error",
|
||||
"code": 7016
|
||||
},
|
||||
"Index signature of object type implicitly has an 'any' type.": {
|
||||
"category": "Error",
|
||||
"code": 7017
|
||||
|
||||
@ -45,7 +45,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Adds `isExernalLibraryImport` to a Resolved to get a ResolvedModule. */
|
||||
function resolvedModuleFromResolved({ path, extension }: Resolved, isExternalLibraryImport: boolean): ResolvedModule {
|
||||
function resolvedModuleFromResolved({ path, extension }: Resolved, isExternalLibraryImport: boolean): ResolvedModuleFull {
|
||||
return { resolvedFileName: path, extension, isExternalLibraryImport };
|
||||
}
|
||||
|
||||
|
||||
@ -329,16 +329,16 @@ namespace ts {
|
||||
// Map storing if there is emit blocking diagnostics for given input
|
||||
const hasEmitBlockingDiagnostics = createFileMap<boolean>(getCanonicalFileName);
|
||||
|
||||
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string) => ResolvedModule[];
|
||||
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string) => ResolvedModuleFull[];
|
||||
if (host.resolveModuleNames) {
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile).map(resolved => {
|
||||
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
|
||||
if (!resolved || resolved.extension !== undefined) {
|
||||
return resolved;
|
||||
if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) {
|
||||
return resolved as ResolvedModuleFull;
|
||||
}
|
||||
resolved = clone(resolved);
|
||||
resolved.extension = extensionFromPath(resolved.resolvedFileName);
|
||||
return resolved;
|
||||
const withExtension = clone(resolved) as ResolvedModuleFull;
|
||||
withExtension.extension = extensionFromPath(resolved.resolvedFileName);
|
||||
return withExtension;
|
||||
});
|
||||
}
|
||||
else {
|
||||
@ -1290,7 +1290,7 @@ namespace ts {
|
||||
function processImportedModules(file: SourceFile) {
|
||||
collectExternalModuleReferences(file);
|
||||
if (file.imports.length || file.moduleAugmentations.length) {
|
||||
file.resolvedModules = new StringMap<ResolvedModule>();
|
||||
file.resolvedModules = new StringMap<ResolvedModuleFull>();
|
||||
const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral);
|
||||
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
|
||||
Debug.assert(resolutions.length === moduleNames.length);
|
||||
@ -1317,6 +1317,7 @@ namespace ts {
|
||||
// - it's not a top level JavaScript module that exceeded the search max
|
||||
const elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModuleJsDepth;
|
||||
// Don't add the file if it has a bad extension (e.g. 'tsx' if we don't have '--allowJs')
|
||||
// This may still end up being an untyped module -- the file won't be included but imports will be allowed.
|
||||
const shouldAddFile = resolvedFileName && !getResolutionDiagnostic(options, resolution) && !options.noResolve && i < file.imports.length && !elideImport;
|
||||
|
||||
if (elideImport) {
|
||||
@ -1564,22 +1565,29 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
/**
|
||||
* Returns a DiagnosticMessage if we can't use a resolved module due to its extension.
|
||||
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
|
||||
* The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to.
|
||||
* This returns a diagnostic even if the module will be an untyped module.
|
||||
*/
|
||||
export function getResolutionDiagnostic(options: CompilerOptions, { extension }: ResolvedModule): DiagnosticMessage | undefined {
|
||||
export function getResolutionDiagnostic(options: CompilerOptions, { extension }: ResolvedModuleFull): DiagnosticMessage | undefined {
|
||||
switch (extension) {
|
||||
case Extension.Ts:
|
||||
case Extension.Dts:
|
||||
// These are always allowed.
|
||||
return undefined;
|
||||
|
||||
case Extension.Tsx:
|
||||
return needJsx();
|
||||
case Extension.Jsx:
|
||||
return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set;
|
||||
|
||||
return needJsx() || needAllowJs();
|
||||
case Extension.Js:
|
||||
return options.allowJs ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_allowJs_is_not_set;
|
||||
return needAllowJs();
|
||||
}
|
||||
|
||||
function needJsx() {
|
||||
return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set;
|
||||
}
|
||||
function needAllowJs() {
|
||||
return options.allowJs ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_allowJs_is_not_set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,7 +458,7 @@ namespace ts {
|
||||
ThisNodeHasError = 1 << 19, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 20, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 21, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 22, // If we've computed data from children and cached it in this node
|
||||
HasAggregatedChildData = 1 << 22, // If we've computed data from children and cached it in this node
|
||||
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
@ -2118,7 +2118,7 @@ namespace ts {
|
||||
// Stores a mapping 'external module reference text' -> 'resolved file name' | undefined
|
||||
// It is used to resolve module names in the checker.
|
||||
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
|
||||
/* @internal */ resolvedModules: Map<string, ResolvedModule>;
|
||||
/* @internal */ resolvedModules: Map<string, ResolvedModuleFull>;
|
||||
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<string, ResolvedTypeReferenceDirective>;
|
||||
/* @internal */ imports: LiteralExpression[];
|
||||
/* @internal */ moduleAugmentations: LiteralExpression[];
|
||||
@ -3387,14 +3387,11 @@ namespace ts {
|
||||
* Module resolution will pick up tsx/jsx/js files even if '--jsx' and '--allowJs' are turned off.
|
||||
* The Program will then filter results based on these flags.
|
||||
*
|
||||
* At least one of `resolvedTsFileName` or `resolvedJsFileName` must be defined,
|
||||
* else resolution should just return `undefined` instead of a ResolvedModule.
|
||||
* Prefer to return a `ResolvedModuleFull` so that the file type does not have to be inferred.
|
||||
*/
|
||||
export interface ResolvedModule {
|
||||
/** Path of the file the module was resolved to. */
|
||||
resolvedFileName: string;
|
||||
/** Extension of resolvedFileName. This must match what's at the end of resolvedFileName. */
|
||||
extension: Extension;
|
||||
/**
|
||||
* Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be a proper external module:
|
||||
* - be a .d.ts file
|
||||
@ -3404,6 +3401,18 @@ namespace ts {
|
||||
isExternalLibraryImport?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* ResolvedModule with an explicitly provided `extension` property.
|
||||
* Prefer this over `ResolvedModule`.
|
||||
*/
|
||||
export interface ResolvedModuleFull extends ResolvedModule {
|
||||
/**
|
||||
* Extension of resolvedFileName. This must match what's at the end of resolvedFileName.
|
||||
* This is optional for backwards-compatibility, but will be added if not provided.
|
||||
*/
|
||||
extension: Extension;
|
||||
}
|
||||
|
||||
export enum Extension {
|
||||
Ts,
|
||||
Tsx,
|
||||
@ -3414,7 +3423,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface ResolvedModuleWithFailedLookupLocations {
|
||||
resolvedModule: ResolvedModule | undefined;
|
||||
resolvedModule: ResolvedModuleFull | undefined;
|
||||
failedLookupLocations: string[];
|
||||
}
|
||||
|
||||
|
||||
@ -87,13 +87,13 @@ namespace ts {
|
||||
return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules.get(moduleNameText));
|
||||
}
|
||||
|
||||
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule {
|
||||
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModuleFull {
|
||||
return hasResolvedModule(sourceFile, moduleNameText) ? sourceFile.resolvedModules.get(moduleNameText) : undefined;
|
||||
}
|
||||
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void {
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModuleFull): void {
|
||||
if (!sourceFile.resolvedModules) {
|
||||
sourceFile.resolvedModules = new StringMap<ResolvedModule>();
|
||||
sourceFile.resolvedModules = new StringMap<ResolvedModuleFull>();
|
||||
}
|
||||
|
||||
sourceFile.resolvedModules.set(moduleNameText, resolvedModule);
|
||||
@ -108,11 +108,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
/**
|
||||
* Considers two ResolvedModules equal if they have the same `resolvedFileName`.
|
||||
* Thus `{ ts: foo, js: bar }` is equal to `{ ts: foo, js: baz }` because `ts` is preferred.
|
||||
*/
|
||||
export function moduleResolutionIsEqualTo(oldResolution: ResolvedModule, newResolution: ResolvedModule): boolean {
|
||||
export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleFull, newResolution: ResolvedModuleFull): boolean {
|
||||
return oldResolution.isExternalLibraryImport === newResolution.isExternalLibraryImport &&
|
||||
oldResolution.extension === newResolution.extension &&
|
||||
oldResolution.resolvedFileName === newResolution.resolvedFileName;
|
||||
@ -406,8 +402,9 @@ namespace ts {
|
||||
((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(<ModuleDeclaration>node));
|
||||
}
|
||||
|
||||
export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean {
|
||||
return isShorthandAmbientModule(moduleSymbol.valueDeclaration);
|
||||
/** Given a symbol for a module, checks that it is either an untyped import or a shorthand ambient module. */
|
||||
export function isUntypedModuleSymbol(moduleSymbol: Symbol): boolean {
|
||||
return !moduleSymbol.valueDeclaration || isShorthandAmbientModule(moduleSymbol.valueDeclaration);
|
||||
}
|
||||
|
||||
function isShorthandAmbientModule(node: Node): boolean {
|
||||
|
||||
@ -438,9 +438,8 @@ namespace FourSlash {
|
||||
private getAllDiagnostics(): ts.Diagnostic[] {
|
||||
const diagnostics: ts.Diagnostic[] = [];
|
||||
|
||||
const fileNames = this.languageServiceAdapterHost.getFilenames();
|
||||
for (let i = 0, n = fileNames.length; i < n; i++) {
|
||||
diagnostics.push.apply(this.getDiagnostics(fileNames[i]));
|
||||
for (const fileName of this.languageServiceAdapterHost.getFilenames()) {
|
||||
diagnostics.push.apply(this.getDiagnostics(fileName));
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
@ -580,12 +579,12 @@ namespace FourSlash {
|
||||
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];
|
||||
ts.zipWith(endMarkers, definitions, (endMarker, definition, i) => {
|
||||
const marker = this.getMarkerByName(endMarker);
|
||||
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 {
|
||||
@ -602,10 +601,10 @@ namespace FourSlash {
|
||||
public verifyGetEmitOutputContentsForCurrentFile(expected: ts.OutputFile[]): void {
|
||||
const emit = this.languageService.getEmitOutput(this.activeFile.fileName);
|
||||
assert.equal(emit.outputFiles.length, expected.length, "Number of emit output files");
|
||||
for (let i = 0; i < emit.outputFiles.length; i++) {
|
||||
assert.equal(emit.outputFiles[i].name, expected[i].name, "FileName");
|
||||
assert.equal(emit.outputFiles[i].text, expected[i].text, "Content");
|
||||
}
|
||||
ts.zipWith(emit.outputFiles, expected, (outputFile, expected) => {
|
||||
assert.equal(outputFile.name, expected.name, "FileName");
|
||||
assert.equal(outputFile.text, expected.text, "Content");
|
||||
});
|
||||
}
|
||||
|
||||
public verifyMemberListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
|
||||
@ -668,9 +667,9 @@ namespace FourSlash {
|
||||
|
||||
const entries = this.getCompletionListAtCaret().entries;
|
||||
assert.isTrue(items.length <= entries.length, `Amount of expected items in completion list [ ${items.length} ] is greater than actual number of items in list [ ${entries.length} ]`);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
assert.equal(entries[i].name, items[i], `Unexpected item in completion list`);
|
||||
}
|
||||
ts.zipWith(entries, items, (entry, item) => {
|
||||
assert.equal(entry.name, item, `Unexpected item in completion list`);
|
||||
});
|
||||
}
|
||||
|
||||
public noItemsWithSameNameButDifferentKind(): void {
|
||||
@ -690,15 +689,7 @@ namespace FourSlash {
|
||||
this.raiseError("Member list is empty at Caret");
|
||||
}
|
||||
else if ((members && members.entries.length !== 0) && !negative) {
|
||||
|
||||
let errorMsg = "\n" + "Member List contains: [" + members.entries[0].name;
|
||||
for (let i = 1; i < members.entries.length; i++) {
|
||||
errorMsg += ", " + members.entries[i].name;
|
||||
}
|
||||
errorMsg += "]\n";
|
||||
|
||||
this.raiseError("Member list is not empty at Caret: " + errorMsg);
|
||||
|
||||
this.raiseError(`Member list is not empty at Caret:\nMember List contains: ${stringify(members.entries.map(e => e.name))}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,13 +699,8 @@ namespace FourSlash {
|
||||
this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition);
|
||||
}
|
||||
else if (completions && completions.entries.length !== 0 && !negative) {
|
||||
let errorMsg = "\n" + "Completion List contains: [" + completions.entries[0].name;
|
||||
for (let i = 1; i < completions.entries.length; i++) {
|
||||
errorMsg += ", " + completions.entries[i].name;
|
||||
}
|
||||
errorMsg += "]\n";
|
||||
|
||||
this.raiseError("Completion list is not empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition + errorMsg);
|
||||
this.raiseError(`Completion list is not empty at caret at position ${this.activeFile.fileName} ${this.currentCaretPosition}\n` +
|
||||
`Completion List contains: ${stringify(completions.entries.map(e => e.name))}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -888,8 +874,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
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];
|
||||
for (const reference of references) {
|
||||
if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) {
|
||||
if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) {
|
||||
this.raiseError(`verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ${reference.isWriteAccess}, expected: ${isWriteAccess}.`);
|
||||
@ -1007,16 +992,11 @@ namespace FourSlash {
|
||||
ranges = ranges.sort((r1, r2) => r1.start - r2.start);
|
||||
references = references.sort((r1, r2) => r1.textSpan.start - r2.textSpan.start);
|
||||
|
||||
for (let i = 0, n = ranges.length; i < n; i++) {
|
||||
const reference = references[i];
|
||||
const range = ranges[i];
|
||||
|
||||
if (reference.textSpan.start !== range.start ||
|
||||
ts.textSpanEnd(reference.textSpan) !== range.end) {
|
||||
|
||||
ts.zipWith(references, ranges, (reference, range) => {
|
||||
if (reference.textSpan.start !== range.start || ts.textSpanEnd(reference.textSpan) !== range.end) {
|
||||
this.raiseError("Rename location results do not match.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + JSON.stringify(references));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.raiseError("Expected rename to succeed, but it actually failed.");
|
||||
@ -1246,8 +1226,7 @@ namespace FourSlash {
|
||||
const emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on
|
||||
|
||||
const allFourSlashFiles = this.testData.files;
|
||||
for (let idx = 0; idx < allFourSlashFiles.length; idx++) {
|
||||
const file = allFourSlashFiles[idx];
|
||||
for (const file of allFourSlashFiles) {
|
||||
if (file.fileOptions[metadataOptionNames.emitThisFile] === "true") {
|
||||
// Find a file with the flag emitThisFile turned on
|
||||
emitFiles.push(file);
|
||||
@ -1272,8 +1251,8 @@ namespace FourSlash {
|
||||
if (emitOutput.emitSkipped) {
|
||||
resultString += "Diagnostics:" + Harness.IO.newLine();
|
||||
const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram());
|
||||
for (let i = 0, n = diagnostics.length; i < n; i++) {
|
||||
resultString += " " + diagnostics[0].messageText + Harness.IO.newLine();
|
||||
for (const diagnostic of diagnostics) {
|
||||
resultString += " " + diagnostic.messageText + Harness.IO.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1339,8 +1318,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public printCurrentFileState(makeWhitespaceVisible = false, makeCaretVisible = true) {
|
||||
for (let i = 0; i < this.testData.files.length; i++) {
|
||||
const file = this.testData.files[i];
|
||||
for (const file of this.testData.files) {
|
||||
const active = (this.activeFile === file);
|
||||
Harness.IO.log(`=== Script (${file.fileName}) ${(active ? "(active, cursor at |)" : "")} ===`);
|
||||
let content = this.getFileContent(file.fileName);
|
||||
@ -1575,10 +1553,10 @@ namespace FourSlash {
|
||||
edits = edits.sort((a, b) => a.span.start - b.span.start);
|
||||
// Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters
|
||||
const oldContent = this.getFileContent(this.activeFile.fileName);
|
||||
for (let j = 0; j < edits.length; j++) {
|
||||
this.languageServiceAdapterHost.editScript(fileName, edits[j].span.start + runningOffset, ts.textSpanEnd(edits[j].span) + runningOffset, edits[j].newText);
|
||||
this.updateMarkersForEdit(fileName, edits[j].span.start + runningOffset, ts.textSpanEnd(edits[j].span) + runningOffset, edits[j].newText);
|
||||
const change = (edits[j].span.start - ts.textSpanEnd(edits[j].span)) + edits[j].newText.length;
|
||||
for (const edit of edits) {
|
||||
this.languageServiceAdapterHost.editScript(fileName, edit.span.start + runningOffset, ts.textSpanEnd(edit.span) + runningOffset, edit.newText);
|
||||
this.updateMarkersForEdit(fileName, edit.span.start + runningOffset, ts.textSpanEnd(edit.span) + runningOffset, edit.newText);
|
||||
const change = (edit.span.start - ts.textSpanEnd(edit.span)) + edit.newText.length;
|
||||
runningOffset += change;
|
||||
// TODO: Consider doing this at least some of the time for higher fidelity. Currently causes a failure (bug 707150)
|
||||
// this.languageService.getScriptLexicalStructure(fileName);
|
||||
@ -1916,10 +1894,7 @@ namespace FourSlash {
|
||||
jsonMismatchString());
|
||||
}
|
||||
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
const expectedClassification = expected[i];
|
||||
const actualClassification = actual[i];
|
||||
|
||||
ts.zipWith(expected, actual, (expectedClassification, actualClassification) => {
|
||||
const expectedType: string = (<any>ts.ClassificationTypeNames)[expectedClassification.classificationType];
|
||||
if (expectedType !== actualClassification.classificationType) {
|
||||
this.raiseError("verifyClassifications failed - expected classifications type to be " +
|
||||
@ -1949,7 +1924,7 @@ namespace FourSlash {
|
||||
actualText +
|
||||
jsonMismatchString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function jsonMismatchString() {
|
||||
return Harness.IO.newLine() +
|
||||
@ -1994,13 +1969,11 @@ namespace FourSlash {
|
||||
this.raiseError(`verifyOutliningSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < spans.length; i++) {
|
||||
const expectedSpan = spans[i];
|
||||
const actualSpan = actual[i];
|
||||
ts.zipWith(spans, actual, (expectedSpan, actualSpan, i) => {
|
||||
if (expectedSpan.start !== actualSpan.textSpan.start || expectedSpan.end !== ts.textSpanEnd(actualSpan.textSpan)) {
|
||||
this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.start},${expectedSpan.end}), actual: (${actualSpan.textSpan.start},${ts.textSpanEnd(actualSpan.textSpan)})`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public verifyTodoComments(descriptors: string[], spans: TextSpan[]) {
|
||||
@ -2011,15 +1984,13 @@ namespace FourSlash {
|
||||
this.raiseError(`verifyTodoComments failed - expected total spans to be ${spans.length}, but was ${actual.length}`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < spans.length; i++) {
|
||||
const expectedSpan = spans[i];
|
||||
const actualComment = actual[i];
|
||||
ts.zipWith(spans, actual, (expectedSpan, actualComment, i) => {
|
||||
const actualCommentSpan = ts.createTextSpan(actualComment.position, actualComment.message.length);
|
||||
|
||||
if (expectedSpan.start !== actualCommentSpan.start || expectedSpan.end !== ts.textSpanEnd(actualCommentSpan)) {
|
||||
this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.start},${expectedSpan.end}), actual: (${actualCommentSpan.start},${ts.textSpanEnd(actualCommentSpan)})`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getCodeFixes(errorCode?: number) {
|
||||
@ -2166,11 +2137,9 @@ namespace FourSlash {
|
||||
public verifyNavigationItemsCount(expected: number, searchValue: string, matchKind?: string, fileName?: string) {
|
||||
const items = this.languageService.getNavigateToItems(searchValue, /*maxResultCount*/ undefined, fileName);
|
||||
let actual = 0;
|
||||
let item: ts.NavigateToItem;
|
||||
|
||||
// Count only the match that match the same MatchKind
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
item = items[i];
|
||||
for (const item of items) {
|
||||
if (!matchKind || item.matchKind === matchKind) {
|
||||
actual++;
|
||||
}
|
||||
@ -2198,8 +2167,7 @@ namespace FourSlash {
|
||||
this.raiseError("verifyNavigationItemsListContains failed - found 0 navigation items, expected at least one.");
|
||||
}
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
for (const item of items) {
|
||||
if (item && item.name === name && item.kind === kind &&
|
||||
(matchKind === undefined || item.matchKind === matchKind) &&
|
||||
(fileName === undefined || item.fileName === fileName) &&
|
||||
@ -2250,24 +2218,16 @@ namespace FourSlash {
|
||||
|
||||
public printNavigationItems(searchValue: string) {
|
||||
const items = this.languageService.getNavigateToItems(searchValue);
|
||||
const length = items && items.length;
|
||||
|
||||
Harness.IO.log(`NavigationItems list (${length} items)`);
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const item = items[i];
|
||||
Harness.IO.log(`NavigationItems list (${items.length} items)`);
|
||||
for (const item of items) {
|
||||
Harness.IO.log(`name: ${item.name}, kind: ${item.kind}, parentName: ${item.containerName}, fileName: ${item.fileName}`);
|
||||
}
|
||||
}
|
||||
|
||||
public printNavigationBar() {
|
||||
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
|
||||
const length = items && items.length;
|
||||
|
||||
Harness.IO.log(`Navigation bar (${length} items)`);
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const item = items[i];
|
||||
Harness.IO.log(`Navigation bar (${items.length} items)`);
|
||||
for (const item of items) {
|
||||
Harness.IO.log(`${repeatString(item.indent, " ")}name: ${item.text}, kind: ${item.kind}, childItems: ${item.childItems.map(child => child.text)}`);
|
||||
}
|
||||
}
|
||||
@ -2388,8 +2348,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
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];
|
||||
for (const item of items) {
|
||||
if (item.name === name) {
|
||||
if (documentation != undefined || text !== undefined) {
|
||||
const details = this.getCompletionEntryDetails(item.name);
|
||||
@ -2438,20 +2397,17 @@ namespace FourSlash {
|
||||
name = name.indexOf("/") === -1 ? (this.basePath + "/" + name) : name;
|
||||
|
||||
const availableNames: string[] = [];
|
||||
let foundIt = false;
|
||||
for (let i = 0; i < this.testData.files.length; i++) {
|
||||
const fn = this.testData.files[i].fileName;
|
||||
result = ts.forEach(this.testData.files, file => {
|
||||
const fn = file.fileName;
|
||||
if (fn) {
|
||||
if (fn === name) {
|
||||
result = this.testData.files[i];
|
||||
foundIt = true;
|
||||
break;
|
||||
return file;
|
||||
}
|
||||
availableNames.push(fn);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!foundIt) {
|
||||
if (!result) {
|
||||
throw new Error(`No test file named "${name}" exists. Available file names are: ${availableNames.join(", ")}`);
|
||||
}
|
||||
}
|
||||
@ -2552,8 +2508,8 @@ ${code}
|
||||
|
||||
function chompLeadingSpace(content: string) {
|
||||
const lines = content.split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if ((lines[i].length !== 0) && (lines[i].charAt(0) !== " ")) {
|
||||
for (const line of lines) {
|
||||
if ((line.length !== 0) && (line.charAt(0) !== " ")) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@ -2591,8 +2547,7 @@ ${code}
|
||||
currentFileName = fileName;
|
||||
}
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
for (let line of lines) {
|
||||
const lineLength = line.length;
|
||||
|
||||
if (lineLength > 0 && line.charAt(lineLength - 1) === "\r") {
|
||||
|
||||
@ -1108,22 +1108,7 @@ namespace Harness {
|
||||
const option = getCommandLineOption(name);
|
||||
if (option) {
|
||||
const errors: ts.Diagnostic[] = [];
|
||||
switch (option.type) {
|
||||
case "boolean":
|
||||
options[option.name] = value.toLowerCase() === "true";
|
||||
break;
|
||||
case "string":
|
||||
options[option.name] = value;
|
||||
break;
|
||||
// If not a primitive, the possible types are specified in what is effectively a map of options.
|
||||
case "list":
|
||||
options[option.name] = ts.parseListTypeOption(<ts.CommandLineOptionOfListType>option, value, errors);
|
||||
break;
|
||||
default:
|
||||
options[option.name] = ts.parseCustomTypeOption(<ts.CommandLineOptionOfCustomType>option, value, errors);
|
||||
break;
|
||||
}
|
||||
|
||||
options[option.name] = optionValue(option, value, errors);
|
||||
if (errors.length > 0) {
|
||||
throw new Error(`Unknown value '${value}' for compiler option '${name}'.`);
|
||||
}
|
||||
@ -1135,6 +1120,27 @@ namespace Harness {
|
||||
}
|
||||
}
|
||||
|
||||
function optionValue(option: ts.CommandLineOption, value: string, errors: ts.Diagnostic[]): any {
|
||||
switch (option.type) {
|
||||
case "boolean":
|
||||
return value.toLowerCase() === "true";
|
||||
case "string":
|
||||
return value;
|
||||
case "number": {
|
||||
const number = parseInt(value, 10);
|
||||
if (isNaN(number)) {
|
||||
throw new Error(`Value must be a number, got: ${JSON.stringify(value)}`);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
// If not a primitive, the possible types are specified in what is effectively a map of options.
|
||||
case "list":
|
||||
return ts.parseListTypeOption(<ts.CommandLineOptionOfListType>option, value, errors);
|
||||
default:
|
||||
return ts.parseCustomTypeOption(<ts.CommandLineOptionOfCustomType>option, value, errors);
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestFile {
|
||||
unitName: string;
|
||||
content: string;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
export function checkResolvedModule(expected: ResolvedModule, actual: ResolvedModule): boolean {
|
||||
export function checkResolvedModule(expected: ResolvedModuleFull, actual: ResolvedModuleFull): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
@ -13,13 +13,13 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function checkResolvedModuleWithFailedLookupLocations(actual: ResolvedModuleWithFailedLookupLocations, expectedResolvedModule: ResolvedModule, expectedFailedLookupLocations: string[]): void {
|
||||
export function checkResolvedModuleWithFailedLookupLocations(actual: ResolvedModuleWithFailedLookupLocations, expectedResolvedModule: ResolvedModuleFull, expectedFailedLookupLocations: string[]): void {
|
||||
assert.isTrue(actual.resolvedModule !== undefined, "module should be resolved");
|
||||
checkResolvedModule(actual.resolvedModule, expectedResolvedModule);
|
||||
assert.deepEqual(actual.failedLookupLocations, expectedFailedLookupLocations);
|
||||
}
|
||||
|
||||
export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false): ResolvedModule {
|
||||
export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false): ResolvedModuleFull {
|
||||
return { resolvedFileName, extension: extensionFromPath(resolvedFileName), isExternalLibraryImport };
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +151,7 @@ namespace ts.server {
|
||||
m => m.resolvedTypeReferenceDirective, r => r.resolvedFileName, /*logChanges*/ false);
|
||||
}
|
||||
|
||||
resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModule[] {
|
||||
resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModuleFull[] {
|
||||
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, this.resolveModuleName,
|
||||
m => m.resolvedModule, r => r.resolvedFileName, /*logChanges*/ true);
|
||||
}
|
||||
|
||||
@ -467,7 +467,7 @@ namespace ts {
|
||||
public languageVariant: LanguageVariant;
|
||||
public identifiers: Map<string, string>;
|
||||
public nameTable: Map<string, number>;
|
||||
public resolvedModules: Map<string, ResolvedModule>;
|
||||
public resolvedModules: Map<string, ResolvedModuleFull>;
|
||||
public resolvedTypeReferenceDirectiveNames: Map<string, ResolvedTypeReferenceDirective>;
|
||||
public imports: LiteralExpression[];
|
||||
public moduleAugmentations: LiteralExpression[];
|
||||
|
||||
@ -316,7 +316,7 @@ namespace ts {
|
||||
private loggingEnabled = false;
|
||||
private tracingEnabled = false;
|
||||
|
||||
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModule[];
|
||||
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModuleFull[];
|
||||
public resolveTypeReferenceDirectives: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[];
|
||||
public directoryExists: (directoryName: string) => boolean;
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
/a.ts(1,17): error TS6143: Module './jsx' was resolved to '/jsx.jsx', but '--allowJs' is not set.
|
||||
|
||||
|
||||
==== /a.ts (1 errors) ====
|
||||
import jsx from "./jsx";
|
||||
~~~~~~~
|
||||
!!! error TS6143: Module './jsx' was resolved to '/jsx.jsx', but '--allowJs' is not set.
|
||||
|
||||
==== /jsx.jsx (0 errors) ====
|
||||
// Test the error message if we have `--jsx` but not `--allowJw`.
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
//// [tests/cases/compiler/moduleResolutionWithExtensions_notSupported3.ts] ////
|
||||
|
||||
//// [jsx.jsx]
|
||||
// Test the error message if we have `--jsx` but not `--allowJw`.
|
||||
|
||||
|
||||
//// [a.ts]
|
||||
import jsx from "./jsx";
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
@ -0,0 +1,17 @@
|
||||
[
|
||||
"======== Resolving module './jsx' from '/a.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/jsx'.",
|
||||
"File '/jsx.ts' does not exist.",
|
||||
"File '/jsx.tsx' does not exist.",
|
||||
"File '/jsx.d.ts' does not exist.",
|
||||
"File '/jsx/package.json' does not exist.",
|
||||
"File '/jsx/index.ts' does not exist.",
|
||||
"File '/jsx/index.tsx' does not exist.",
|
||||
"File '/jsx/index.d.ts' does not exist.",
|
||||
"Loading module as file / folder, candidate module location '/jsx'.",
|
||||
"File '/jsx.js' does not exist.",
|
||||
"File '/jsx.jsx' exist - use it as a name resolution result.",
|
||||
"Resolving real path for '/jsx.jsx', result '/jsx.jsx'",
|
||||
"======== Module name './jsx' was successfully resolved to '/jsx.jsx'. ========"
|
||||
]
|
||||
37
tests/baselines/reference/untypedModuleImport.js
Normal file
37
tests/baselines/reference/untypedModuleImport.js
Normal file
@ -0,0 +1,37 @@
|
||||
//// [tests/cases/conformance/moduleResolution/untypedModuleImport.ts] ////
|
||||
|
||||
//// [index.js]
|
||||
// This tests that importing from a JS file globally works in an untyped way.
|
||||
// (Assuming we don't have `--noImplicitAny` or `--allowJs`.)
|
||||
|
||||
This file is not processed.
|
||||
|
||||
//// [a.ts]
|
||||
import * as foo from "foo";
|
||||
foo.bar();
|
||||
|
||||
//// [b.ts]
|
||||
import foo = require("foo");
|
||||
foo();
|
||||
|
||||
//// [c.ts]
|
||||
import foo, { bar } from "foo";
|
||||
import "./a";
|
||||
import "./b";
|
||||
foo(bar());
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
var foo = require("foo");
|
||||
foo.bar();
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
var foo = require("foo");
|
||||
foo();
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
var foo_1 = require("foo");
|
||||
require("./a");
|
||||
require("./b");
|
||||
foo_1["default"](foo_1.bar());
|
||||
25
tests/baselines/reference/untypedModuleImport.symbols
Normal file
25
tests/baselines/reference/untypedModuleImport.symbols
Normal file
@ -0,0 +1,25 @@
|
||||
=== /c.ts ===
|
||||
import foo, { bar } from "foo";
|
||||
>foo : Symbol(foo, Decl(c.ts, 0, 6))
|
||||
>bar : Symbol(bar, Decl(c.ts, 0, 13))
|
||||
|
||||
import "./a";
|
||||
import "./b";
|
||||
foo(bar());
|
||||
>foo : Symbol(foo, Decl(c.ts, 0, 6))
|
||||
>bar : Symbol(bar, Decl(c.ts, 0, 13))
|
||||
|
||||
=== /a.ts ===
|
||||
import * as foo from "foo";
|
||||
>foo : Symbol(foo, Decl(a.ts, 0, 6))
|
||||
|
||||
foo.bar();
|
||||
>foo : Symbol(foo, Decl(a.ts, 0, 6))
|
||||
|
||||
=== /b.ts ===
|
||||
import foo = require("foo");
|
||||
>foo : Symbol(foo, Decl(b.ts, 0, 0))
|
||||
|
||||
foo();
|
||||
>foo : Symbol(foo, Decl(b.ts, 0, 0))
|
||||
|
||||
31
tests/baselines/reference/untypedModuleImport.types
Normal file
31
tests/baselines/reference/untypedModuleImport.types
Normal file
@ -0,0 +1,31 @@
|
||||
=== /c.ts ===
|
||||
import foo, { bar } from "foo";
|
||||
>foo : any
|
||||
>bar : any
|
||||
|
||||
import "./a";
|
||||
import "./b";
|
||||
foo(bar());
|
||||
>foo(bar()) : any
|
||||
>foo : any
|
||||
>bar() : any
|
||||
>bar : any
|
||||
|
||||
=== /a.ts ===
|
||||
import * as foo from "foo";
|
||||
>foo : any
|
||||
|
||||
foo.bar();
|
||||
>foo.bar() : any
|
||||
>foo.bar : any
|
||||
>foo : any
|
||||
>bar : any
|
||||
|
||||
=== /b.ts ===
|
||||
import foo = require("foo");
|
||||
>foo : any
|
||||
|
||||
foo();
|
||||
>foo() : any
|
||||
>foo : any
|
||||
|
||||
16
tests/baselines/reference/untypedModuleImport_allowJs.js
Normal file
16
tests/baselines/reference/untypedModuleImport_allowJs.js
Normal file
@ -0,0 +1,16 @@
|
||||
//// [tests/cases/conformance/moduleResolution/untypedModuleImport_allowJs.ts] ////
|
||||
|
||||
//// [index.js]
|
||||
// Same as untypedModuleImport.ts but with --allowJs, so the package will actually be typed.
|
||||
|
||||
exports.default = { bar() { return 0; } }
|
||||
|
||||
//// [a.ts]
|
||||
import foo from "foo";
|
||||
foo.bar();
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
var foo_1 = require("foo");
|
||||
foo_1["default"].bar();
|
||||
@ -0,0 +1,17 @@
|
||||
=== /a.ts ===
|
||||
import foo from "foo";
|
||||
>foo : Symbol(foo, Decl(a.ts, 0, 6))
|
||||
|
||||
foo.bar();
|
||||
>foo.bar : Symbol(bar, Decl(index.js, 2, 19))
|
||||
>foo : Symbol(foo, Decl(a.ts, 0, 6))
|
||||
>bar : Symbol(bar, Decl(index.js, 2, 19))
|
||||
|
||||
=== /node_modules/foo/index.js ===
|
||||
// Same as untypedModuleImport.ts but with --allowJs, so the package will actually be typed.
|
||||
|
||||
exports.default = { bar() { return 0; } }
|
||||
>exports : Symbol(default, Decl(index.js, 0, 0))
|
||||
>default : Symbol(default, Decl(index.js, 0, 0))
|
||||
>bar : Symbol(bar, Decl(index.js, 2, 19))
|
||||
|
||||
22
tests/baselines/reference/untypedModuleImport_allowJs.types
Normal file
22
tests/baselines/reference/untypedModuleImport_allowJs.types
Normal file
@ -0,0 +1,22 @@
|
||||
=== /a.ts ===
|
||||
import foo from "foo";
|
||||
>foo : { bar(): number; }
|
||||
|
||||
foo.bar();
|
||||
>foo.bar() : number
|
||||
>foo.bar : () => number
|
||||
>foo : { bar(): number; }
|
||||
>bar : () => number
|
||||
|
||||
=== /node_modules/foo/index.js ===
|
||||
// Same as untypedModuleImport.ts but with --allowJs, so the package will actually be typed.
|
||||
|
||||
exports.default = { bar() { return 0; } }
|
||||
>exports.default = { bar() { return 0; } } : { bar(): number; }
|
||||
>exports.default : any
|
||||
>exports : any
|
||||
>default : any
|
||||
>{ bar() { return 0; } } : { bar(): number; }
|
||||
>bar : () => number
|
||||
>0 : 0
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
/a.ts(1,22): error TS7016: Could not find a declaration file for module 'foo'. '/node_modules/foo/index.js' implicitly has an 'any' type.
|
||||
|
||||
|
||||
==== /a.ts (1 errors) ====
|
||||
import * as foo from "foo";
|
||||
~~~~~
|
||||
!!! error TS7016: Could not find a declaration file for module 'foo'. '/node_modules/foo/index.js' implicitly has an 'any' type.
|
||||
|
||||
==== /node_modules/foo/index.js (0 errors) ====
|
||||
// This tests that `--noImplicitAny` disables untyped modules.
|
||||
|
||||
This file is not processed.
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
//// [tests/cases/conformance/moduleResolution/untypedModuleImport_noImplicitAny.ts] ////
|
||||
|
||||
//// [index.js]
|
||||
// This tests that `--noImplicitAny` disables untyped modules.
|
||||
|
||||
This file is not processed.
|
||||
|
||||
//// [a.ts]
|
||||
import * as foo from "foo";
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
@ -0,0 +1,13 @@
|
||||
/a.ts(1,22): error TS6143: Module './foo' was resolved to '/foo.js', but '--allowJs' is not set.
|
||||
|
||||
|
||||
==== /a.ts (1 errors) ====
|
||||
import * as foo from "./foo";
|
||||
~~~~~~~
|
||||
!!! error TS6143: Module './foo' was resolved to '/foo.js', but '--allowJs' is not set.
|
||||
|
||||
==== /foo.js (0 errors) ====
|
||||
// This tests that untyped module imports don't happen with local imports.
|
||||
|
||||
This file is not processed.
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
//// [tests/cases/conformance/moduleResolution/untypedModuleImport_noLocalImports.ts] ////
|
||||
|
||||
//// [foo.js]
|
||||
// This tests that untyped module imports don't happen with local imports.
|
||||
|
||||
This file is not processed.
|
||||
|
||||
//// [a.ts]
|
||||
import * as foo from "./foo";
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
23
tests/baselines/reference/untypedModuleImport_vsAmbient.js
Normal file
23
tests/baselines/reference/untypedModuleImport_vsAmbient.js
Normal file
@ -0,0 +1,23 @@
|
||||
//// [tests/cases/conformance/moduleResolution/untypedModuleImport_vsAmbient.ts] ////
|
||||
|
||||
//// [index.js]
|
||||
// This tests that an ambient module declaration overrides an untyped import.
|
||||
|
||||
This file is not processed.
|
||||
|
||||
//// [declarations.d.ts]
|
||||
declare module "foo" {
|
||||
export const x: number;
|
||||
}
|
||||
|
||||
//// [a.ts]
|
||||
/// <reference path="./declarations.d.ts" />
|
||||
import { x } from "foo";
|
||||
x;
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
/// <reference path="./declarations.d.ts" />
|
||||
var foo_1 = require("foo");
|
||||
foo_1.x;
|
||||
@ -0,0 +1,14 @@
|
||||
=== /a.ts ===
|
||||
/// <reference path="./declarations.d.ts" />
|
||||
import { x } from "foo";
|
||||
>x : Symbol(x, Decl(a.ts, 1, 8))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(a.ts, 1, 8))
|
||||
|
||||
=== /declarations.d.ts ===
|
||||
declare module "foo" {
|
||||
export const x: number;
|
||||
>x : Symbol(x, Decl(declarations.d.ts, 1, 16))
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
=== /a.ts ===
|
||||
/// <reference path="./declarations.d.ts" />
|
||||
import { x } from "foo";
|
||||
>x : number
|
||||
|
||||
x;
|
||||
>x : number
|
||||
|
||||
=== /declarations.d.ts ===
|
||||
declare module "foo" {
|
||||
export const x: number;
|
||||
>x : number
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
// @noImplicitReferences: true
|
||||
// @jsx: preserve
|
||||
// @traceResolution: true
|
||||
// Test the error message if we have `--jsx` but not `--allowJw`.
|
||||
|
||||
// @Filename: /jsx.jsx
|
||||
|
||||
// @Filename: /a.ts
|
||||
import jsx from "./jsx";
|
||||
@ -0,0 +1,21 @@
|
||||
// @noImplicitReferences: true
|
||||
// @currentDirectory: /
|
||||
// This tests that importing from a JS file globally works in an untyped way.
|
||||
// (Assuming we don't have `--noImplicitAny` or `--allowJs`.)
|
||||
|
||||
// @filename: /node_modules/foo/index.js
|
||||
This file is not processed.
|
||||
|
||||
// @filename: /a.ts
|
||||
import * as foo from "foo";
|
||||
foo.bar();
|
||||
|
||||
// @filename: /b.ts
|
||||
import foo = require("foo");
|
||||
foo();
|
||||
|
||||
// @filename: /c.ts
|
||||
import foo, { bar } from "foo";
|
||||
import "./a";
|
||||
import "./b";
|
||||
foo(bar());
|
||||
@ -0,0 +1,12 @@
|
||||
// @noImplicitReferences: true
|
||||
// @currentDirectory: /
|
||||
// @allowJs: true
|
||||
// @maxNodeModuleJsDepth: 1
|
||||
// Same as untypedModuleImport.ts but with --allowJs, so the package will actually be typed.
|
||||
|
||||
// @filename: /node_modules/foo/index.js
|
||||
exports.default = { bar() { return 0; } }
|
||||
|
||||
// @filename: /a.ts
|
||||
import foo from "foo";
|
||||
foo.bar();
|
||||
@ -0,0 +1,10 @@
|
||||
// @noImplicitReferences: true
|
||||
// @currentDirectory: /
|
||||
// @noImplicitAny: true
|
||||
// This tests that `--noImplicitAny` disables untyped modules.
|
||||
|
||||
// @filename: /node_modules/foo/index.js
|
||||
This file is not processed.
|
||||
|
||||
// @filename: /a.ts
|
||||
import * as foo from "foo";
|
||||
@ -0,0 +1,9 @@
|
||||
// @noImplicitReferences: true
|
||||
// @currentDirectory: /
|
||||
// This tests that untyped module imports don't happen with local imports.
|
||||
|
||||
// @filename: /foo.js
|
||||
This file is not processed.
|
||||
|
||||
// @filename: /a.ts
|
||||
import * as foo from "./foo";
|
||||
@ -0,0 +1,16 @@
|
||||
// @noImplicitReferences: true
|
||||
// @currentDirectory: /
|
||||
// This tests that an ambient module declaration overrides an untyped import.
|
||||
|
||||
// @filename: /node_modules/foo/index.js
|
||||
This file is not processed.
|
||||
|
||||
// @filename: /declarations.d.ts
|
||||
declare module "foo" {
|
||||
export const x: number;
|
||||
}
|
||||
|
||||
// @filename: /a.ts
|
||||
/// <reference path="./declarations.d.ts" />
|
||||
import { x } from "foo";
|
||||
x;
|
||||
22
tests/cases/fourslash/untypedModuleImport.ts
Normal file
22
tests/cases/fourslash/untypedModuleImport.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: node_modules/foo/index.js
|
||||
////{}
|
||||
|
||||
// @Filename: a.ts
|
||||
////import /*foo*/[|foo|] from /*fooModule*/"foo";
|
||||
////[|foo|]();
|
||||
|
||||
goTo.file("a.ts");
|
||||
debug.printErrorList();
|
||||
verify.numberOfErrorsInCurrentFile(0);
|
||||
|
||||
goTo.marker("fooModule");
|
||||
verify.goToDefinitionIs([]);
|
||||
verify.quickInfoIs('module "foo"');
|
||||
verify.referencesAre([])
|
||||
|
||||
goTo.marker("foo");
|
||||
verify.goToDefinitionIs([]);
|
||||
verify.quickInfoIs("import foo");
|
||||
verify.rangesReferenceEachOther();
|
||||
Loading…
x
Reference in New Issue
Block a user