Compare commits
9 commits
main
...
duplicate-
Author | SHA1 | Date | |
---|---|---|---|
b425453767 | |||
ee57dc894b | |||
619a5152df | |||
51feae52b4 | |||
62e079520d | |||
2648af160d | |||
8a8ceebbac | |||
5335dfa31a | |||
5a816980e2 |
|
@ -9278,6 +9278,10 @@ namespace ts {
|
|||
let result = Ternary.True;
|
||||
const properties = getPropertiesOfObjectType(target);
|
||||
const requireOptionalProperties = relation === subtypeRelation && !(getObjectFlags(source) & ObjectFlags.ObjectLiteral);
|
||||
|
||||
let _privatesCompatible: boolean | undefined;
|
||||
const privatesCompatible = () => _privatesCompatible !== undefined ? _privatesCompatible : _privatesCompatible = classPrivatesAreCompatible(source, target);
|
||||
|
||||
for (const targetProp of properties) {
|
||||
const sourceProp = getPropertyOfType(source, targetProp.name);
|
||||
|
||||
|
@ -9293,7 +9297,7 @@ namespace ts {
|
|||
else if (!(targetProp.flags & SymbolFlags.Prototype)) {
|
||||
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
|
||||
if ((sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) && !privatesCompatible()) {
|
||||
if (getCheckFlags(sourceProp) & CheckFlags.ContainsPrivate) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source));
|
||||
|
@ -9314,7 +9318,7 @@ namespace ts {
|
|||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (targetPropFlags & ModifierFlags.Protected) {
|
||||
else if (targetPropFlags & ModifierFlags.Protected && !privatesCompatible()) {
|
||||
if (!isValidOverrideOf(sourceProp, targetProp)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp),
|
||||
|
@ -9323,7 +9327,7 @@ namespace ts {
|
|||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (sourcePropFlags & ModifierFlags.Protected) {
|
||||
else if (sourcePropFlags & ModifierFlags.Protected && !privatesCompatible()) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2,
|
||||
symbolToString(targetProp), typeToString(source), typeToString(target));
|
||||
|
@ -24636,4 +24640,30 @@ namespace ts {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
function classPrivatesAreCompatible(a: Type, b: Type): boolean {
|
||||
const classA = a.symbol.valueDeclaration;
|
||||
const classB = b.symbol.valueDeclaration;
|
||||
return classA && classB && isClassLike(classA) && isClassLike(classB) && nodesHavePrivateCompatibleOrigins(classA, classB);
|
||||
}
|
||||
|
||||
function nodesHavePrivateCompatibleOrigins<T extends ClassLikeDeclaration | ModuleDeclaration>(a: T, b: T): boolean {
|
||||
return (a.name && a.name.text) === (b.name && b.name.text)
|
||||
&& getModifierFlags(a) === getModifierFlags(b)
|
||||
&& parentsHavePrivateCompatibleOrigins(a.parent, b.parent);
|
||||
}
|
||||
|
||||
function parentsHavePrivateCompatibleOrigins(parentA: Node, parentB: Node): boolean {
|
||||
if (parentA.kind !== parentB.kind) return false;
|
||||
switch (parentA.kind) {
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return parentsHavePrivateCompatibleOrigins(parentA.parent, parentB.parent);
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return nodesHavePrivateCompatibleOrigins((parentA as ModuleBlock).parent, (parentB as ModuleBlock).parent);
|
||||
case SyntaxKind.SourceFile:
|
||||
return (parentA as SourceFile).packageName !== undefined && (parentA as SourceFile).packageName === (parentB as SourceFile).packageName;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,33 @@ namespace ts {
|
|||
push(value: T): void;
|
||||
}
|
||||
|
||||
//name
|
||||
interface ResolvedMini {
|
||||
path: string;
|
||||
extension: Extension;
|
||||
}
|
||||
|
||||
function maybeWithPackageName(packageName: string | undefined, r: ResolvedMini | undefined): Resolved | undefined {
|
||||
return r && { ...r, packageName: packageName && normalizePackageName(packageName) };
|
||||
}
|
||||
|
||||
function normalizePackageName(packageName: string): string {
|
||||
let components = getNormalizedPathComponents(packageName, "");
|
||||
if (components[0] === "") {
|
||||
components = components.slice(1);
|
||||
}
|
||||
if (components[0] === "@types") {
|
||||
components = components.slice(1);
|
||||
}
|
||||
return getNormalizedPathFromPathComponents(components);
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of trying to resolve a module.
|
||||
* At least one of `ts` and `js` should be defined, or the whole thing should be `undefined`.
|
||||
*/
|
||||
interface Resolved {
|
||||
path: string;
|
||||
extension: Extension;
|
||||
interface Resolved extends ResolvedMini {
|
||||
packageName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,7 +59,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
/** Used with `Extensions.DtsOnly` to extract the path from TypeScript results. */
|
||||
function resolvedTypeScriptOnly(resolved: Resolved | undefined): string | undefined {
|
||||
function resolvedTypeScriptOnly(resolved: ResolvedMini | undefined): string | undefined {
|
||||
if (!resolved) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -48,8 +68,9 @@ namespace ts {
|
|||
}
|
||||
|
||||
function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | undefined, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations {
|
||||
Debug.assert(!resolved || resolved.path !== undefined); //kill
|
||||
return {
|
||||
resolvedModule: resolved && { resolvedFileName: resolved.path, extension: resolved.extension, isExternalLibraryImport },
|
||||
resolvedModule: resolved && { resolvedFileName: resolved.path, extension: resolved.extension, packageName: resolved.packageName, isExternalLibraryImport },
|
||||
failedLookupLocations
|
||||
};
|
||||
}
|
||||
|
@ -474,7 +495,7 @@ namespace ts {
|
|||
* 'typings' entry or file 'index' with some supported extension
|
||||
* - Classic loader will only try to interpret '/a/b/c' as file.
|
||||
*/
|
||||
type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState) => Resolved | undefined;
|
||||
type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState) => ResolvedMini | undefined;
|
||||
|
||||
/**
|
||||
* Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to
|
||||
|
@ -540,15 +561,15 @@ namespace ts {
|
|||
failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state);
|
||||
return maybeWithPackageName(moduleName, tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state)); //TODO: Test with baseUrl settings...
|
||||
}
|
||||
else {
|
||||
return tryLoadModuleUsingRootDirs(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state);
|
||||
return maybeWithPackageName(undefined, tryLoadModuleUsingRootDirs(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state));
|
||||
}
|
||||
}
|
||||
|
||||
function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
|
||||
failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
failedLookupLocations: Push<string>, state: ModuleResolutionState): ResolvedMini | undefined {
|
||||
|
||||
if (!state.compilerOptions.rootDirs) {
|
||||
return undefined;
|
||||
|
@ -624,7 +645,7 @@ namespace ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, failedLookupLocations: Push<string>, state: ModuleResolutionState): ResolvedMini | undefined {
|
||||
if (!state.compilerOptions.baseUrl) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -658,7 +679,8 @@ namespace ts {
|
|||
if (extension !== undefined) {
|
||||
const path = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
if (path !== undefined) {
|
||||
return { path, extension };
|
||||
const packageName = ts.removeExtension(candidate, extensionToString(extension)); //test
|
||||
return { path, packageName, extension };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,11 +743,16 @@ namespace ts {
|
|||
}
|
||||
const resolved = loadModuleFromNodeModules(extensions, moduleName, containingDirectory, failedLookupLocations, state, cache);
|
||||
// For node_modules lookups, get the real path so that multiple accesses to an `npm link`-ed module do not create duplicate files.
|
||||
return resolved && { value: resolved.value && { resolved: { path: realpath(resolved.value.path, host, traceEnabled), extension: resolved.value.extension }, isExternalLibraryImport: true } };
|
||||
return resolved && {
|
||||
value: resolved.value && {
|
||||
resolved: maybeWithPackageName(moduleName, { path: realpath(resolved.value.path, host, traceEnabled), extension: resolved.value.extension }),
|
||||
isExternalLibraryImport: true
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true);
|
||||
const resolved = maybeWithPackageName(undefined, nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true));
|
||||
return resolved && toSearchResult({ resolved, isExternalLibraryImport: false });
|
||||
}
|
||||
}
|
||||
|
@ -743,7 +770,7 @@ namespace ts {
|
|||
return real;
|
||||
}
|
||||
|
||||
function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson: boolean): Resolved | undefined {
|
||||
function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson: boolean): ResolvedMini | undefined {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_type_1, candidate, Extensions[extensions]);
|
||||
}
|
||||
|
@ -784,7 +811,7 @@ namespace ts {
|
|||
* @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
|
||||
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
|
||||
*/
|
||||
function loadModuleFromFile(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
function loadModuleFromFile(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): ResolvedMini | undefined {
|
||||
// First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts"
|
||||
const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocations, onlyRecordFailures, state);
|
||||
if (resolvedByAddingExtension) {
|
||||
|
@ -804,7 +831,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
/** Try to return an existing file that adds one of the `extensions` to `candidate`. */
|
||||
function tryAddingExtensions(candidate: string, extensions: Extensions, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
function tryAddingExtensions(candidate: string, extensions: Extensions, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): ResolvedMini | undefined {
|
||||
if (!onlyRecordFailures) {
|
||||
// check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
|
||||
const directory = getDirectoryPath(candidate);
|
||||
|
@ -815,20 +842,33 @@ namespace ts {
|
|||
|
||||
switch (extensions) {
|
||||
case Extensions.DtsOnly:
|
||||
return tryExtension(".d.ts", Extension.Dts);
|
||||
return tryExtension(Extension.Dts);
|
||||
case Extensions.TypeScript:
|
||||
return tryExtension(".ts", Extension.Ts) || tryExtension(".tsx", Extension.Tsx) || tryExtension(".d.ts", Extension.Dts);
|
||||
return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || tryExtension(Extension.Dts);
|
||||
case Extensions.JavaScript:
|
||||
return tryExtension(".js", Extension.Js) || tryExtension(".jsx", Extension.Jsx);
|
||||
return tryExtension(Extension.Js) || tryExtension(Extension.Jsx);
|
||||
}
|
||||
|
||||
function tryExtension(ext: string, extension: Extension): Resolved | undefined {
|
||||
const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state);
|
||||
function tryExtension(extension: Extension): ResolvedMini | undefined {
|
||||
const path = tryFile(candidate + extensionToString(extension), failedLookupLocations, onlyRecordFailures, state);
|
||||
return path && { path, extension };
|
||||
}
|
||||
}
|
||||
|
||||
//mv
|
||||
function extensionToString(ext: Extension): string {
|
||||
switch (ext) {
|
||||
case Extension.Dts: return ".d.ts";
|
||||
case Extension.Ts: return ".ts";
|
||||
case Extension.Tsx: return ".tsx";
|
||||
case Extension.Dts: return ".d.ts";
|
||||
case Extension.Js: return ".js";
|
||||
case Extension.Jsx: return ".jsx";
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the file if it exists. */
|
||||
//This returns its input. Silly.
|
||||
function tryFile(fileName: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
if (!onlyRecordFailures) {
|
||||
if (state.host.fileExists(fileName)) {
|
||||
|
@ -847,7 +887,7 @@ namespace ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true): Resolved | undefined {
|
||||
function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true): ResolvedMini | undefined {
|
||||
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
|
||||
|
||||
if (considerPackageJson) {
|
||||
|
@ -870,7 +910,7 @@ namespace ts {
|
|||
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocations, !directoryExists, state);
|
||||
}
|
||||
|
||||
function loadModuleFromPackageJson(packageJsonPath: string, extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
function loadModuleFromPackageJson(packageJsonPath: string, extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): ResolvedMini | undefined { //this should of course be global...
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath);
|
||||
}
|
||||
|
@ -899,7 +939,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
|
||||
function resolvedIfExtensionMatches(extensions: Extensions, path: string): Resolved | undefined {
|
||||
function resolvedIfExtensionMatches(extensions: Extensions, path: string): ResolvedMini | undefined {
|
||||
const extension = tryGetExtensionFromPath(path);
|
||||
return extension !== undefined && extensionIsOk(extensions, extension) ? { path, extension } : undefined;
|
||||
}
|
||||
|
@ -920,22 +960,22 @@ namespace ts {
|
|||
return combinePaths(directory, "package.json");
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push<string>, state: ModuleResolutionState): ResolvedMini | undefined {
|
||||
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
|
||||
|
||||
return loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) ||
|
||||
loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state);
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache): SearchResult<Resolved> {
|
||||
function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache): SearchResult<ResolvedMini> {
|
||||
return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache);
|
||||
}
|
||||
function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): SearchResult<Resolved> {
|
||||
function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): SearchResult<ResolvedMini> {
|
||||
// Extensions parameter here doesn't actually matter, because typesOnly ensures we're just doing @types lookup, which is always DtsOnly.
|
||||
return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined);
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache): SearchResult<Resolved> {
|
||||
function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache): SearchResult<ResolvedMini> {
|
||||
const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName);
|
||||
return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => {
|
||||
if (getBaseFileName(ancestorDirectory) !== "node_modules") {
|
||||
|
@ -949,7 +989,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
/** Load a module from a single node_modules directory, but not from any ancestors' node_modules directories. */
|
||||
function loadModuleFromNodeModulesOneLevel(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, typesOnly = false): Resolved | undefined {
|
||||
function loadModuleFromNodeModulesOneLevel(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push<string>, state: ModuleResolutionState, typesOnly = false): ResolvedMini | undefined {
|
||||
const nodeModulesFolder = combinePaths(directory, "node_modules");
|
||||
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
|
||||
if (!nodeModulesFolderExists && state.traceEnabled) {
|
||||
|
@ -1008,7 +1048,7 @@ namespace ts {
|
|||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName);
|
||||
}
|
||||
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension } };
|
||||
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, packageName: result.resolvedModule.packageName, extension: result.resolvedModule.extension } };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1036,19 +1076,20 @@ namespace ts {
|
|||
return resolutionFromCache;
|
||||
}
|
||||
const searchName = normalizePath(combinePaths(directory, moduleName));
|
||||
return toSearchResult(loadModuleFromFile(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state));
|
||||
return toSearchResult(maybeWithPackageName(moduleName, loadModuleFromFile(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state)));
|
||||
});
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
}
|
||||
if (extensions === Extensions.TypeScript) {
|
||||
// If we didn't find the file normally, look it up in @types.
|
||||
return loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state);
|
||||
const x = loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state);
|
||||
return x && { value: maybeWithPackageName(moduleName, x.value) }
|
||||
}
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
return toSearchResult(loadModuleFromFile(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state));
|
||||
return toSearchResult(maybeWithPackageName(undefined, loadModuleFromFile(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1065,7 +1106,7 @@ namespace ts {
|
|||
}
|
||||
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
|
||||
const failedLookupLocations: string[] = [];
|
||||
const resolved = loadModuleFromNodeModulesOneLevel(Extensions.DtsOnly, moduleName, globalCache, failedLookupLocations, state);
|
||||
const resolved = maybeWithPackageName(moduleName, loadModuleFromNodeModulesOneLevel(Extensions.DtsOnly, moduleName, globalCache, failedLookupLocations, state));
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations);
|
||||
}
|
||||
|
||||
|
|
|
@ -756,6 +756,8 @@ namespace ts {
|
|||
sourceFile.languageVariant = getLanguageVariant(scriptKind);
|
||||
sourceFile.isDeclarationFile = fileExtensionIs(sourceFile.fileName, ".d.ts");
|
||||
sourceFile.scriptKind = scriptKind;
|
||||
// This will be set in 'program.ts' if the file is imported from an external package.
|
||||
sourceFile.packageName = undefined;
|
||||
|
||||
return sourceFile;
|
||||
}
|
||||
|
|
|
@ -449,6 +449,7 @@ namespace ts {
|
|||
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 as ResolvedModuleFull).extension !== undefined) {
|
||||
// Host may not have set packageName, but it's OK to leave it as undefined.
|
||||
return resolved as ResolvedModuleFull;
|
||||
}
|
||||
const withExtension = clone(resolved) as ResolvedModuleFull;
|
||||
|
@ -767,8 +768,9 @@ namespace ts {
|
|||
|
||||
for (const oldSourceFile of oldProgram.getSourceFiles()) {
|
||||
const newSourceFile = host.getSourceFileByPath
|
||||
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target)
|
||||
: host.getSourceFile(oldSourceFile.fileName, options.target);
|
||||
? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target, undefined)
|
||||
: host.getSourceFile(oldSourceFile.fileName, options.target, undefined);
|
||||
//may need to set newSourceFile.packageName === oldSourceFile.packageName ?
|
||||
|
||||
if (!newSourceFile) {
|
||||
return oldProgram.structureIsReused = StructureIsReused.Not;
|
||||
|
@ -1501,7 +1503,8 @@ namespace ts {
|
|||
/** This has side effects through `findSourceFile`. */
|
||||
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
|
||||
getSourceFileFromReferenceWorker(fileName,
|
||||
fileName => findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd),
|
||||
//OK for packageName to be undefined?
|
||||
fileName => findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), /*packageName*/ undefined, isDefaultLib, refFile, refPos, refEnd),
|
||||
(diagnostic, ...args) => {
|
||||
fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined
|
||||
? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args)
|
||||
|
@ -1521,18 +1524,22 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Get source file from normalized fileName
|
||||
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
|
||||
function findSourceFile(fileName: string, path: Path, packageName: string | undefined, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
|
||||
if (filesByName.contains(path)) {
|
||||
const file = filesByName.get(path);
|
||||
if (!file) return undefined;
|
||||
|
||||
setPackageName(file, packageName);
|
||||
|
||||
// try to check if we've already seen this file but with a different casing in path
|
||||
// NOTE: this only makes sense for case-insensitive file systems
|
||||
if (file && options.forceConsistentCasingInFileNames && getNormalizedAbsolutePath(file.fileName, currentDirectory) !== getNormalizedAbsolutePath(fileName, currentDirectory)) {
|
||||
if (options.forceConsistentCasingInFileNames && getNormalizedAbsolutePath(file.fileName, currentDirectory) !== getNormalizedAbsolutePath(fileName, currentDirectory)) {
|
||||
reportFileNamesDifferOnlyInCasingError(fileName, file.fileName, refFile, refPos, refEnd);
|
||||
}
|
||||
|
||||
// If the file was previously found via a node_modules search, but is now being processed as a root file,
|
||||
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
|
||||
if (file && sourceFilesFoundSearchingNodeModules.get(file.path) && currentNodeModulesDepth === 0) {
|
||||
if (sourceFilesFoundSearchingNodeModules.get(file.path) && currentNodeModulesDepth === 0) {
|
||||
sourceFilesFoundSearchingNodeModules.set(file.path, false);
|
||||
if (!options.noResolve) {
|
||||
processReferencedFiles(file, isDefaultLib);
|
||||
|
@ -1543,7 +1550,7 @@ namespace ts {
|
|||
processImportedModules(file);
|
||||
}
|
||||
// See if we need to reprocess the imports due to prior skipped imports
|
||||
else if (file && modulesWithElidedImports.get(file.path)) {
|
||||
else if (modulesWithElidedImports.get(file.path)) {
|
||||
if (currentNodeModulesDepth < maxNodeModuleJsDepth) {
|
||||
modulesWithElidedImports.set(file.path, false);
|
||||
processImportedModules(file);
|
||||
|
@ -1565,42 +1572,56 @@ namespace ts {
|
|||
});
|
||||
|
||||
filesByName.set(path, file);
|
||||
if (file) {
|
||||
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
|
||||
file.path = path;
|
||||
if (!file) return undefined;
|
||||
|
||||
if (host.useCaseSensitiveFileNames()) {
|
||||
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
|
||||
const existingFile = filesByNameIgnoreCase.get(path);
|
||||
if (existingFile) {
|
||||
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
|
||||
}
|
||||
else {
|
||||
filesByNameIgnoreCase.set(path, file);
|
||||
}
|
||||
}
|
||||
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
|
||||
setPackageName(file, packageName);
|
||||
file.path = path;
|
||||
|
||||
skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib;
|
||||
|
||||
if (!options.noResolve) {
|
||||
processReferencedFiles(file, isDefaultLib);
|
||||
processTypeReferenceDirectives(file);
|
||||
}
|
||||
|
||||
// always process imported modules to record module name resolutions
|
||||
processImportedModules(file);
|
||||
|
||||
if (isDefaultLib) {
|
||||
files.unshift(file);
|
||||
if (host.useCaseSensitiveFileNames()) {
|
||||
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
|
||||
const existingFile = filesByNameIgnoreCase.get(path);
|
||||
if (existingFile) {
|
||||
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
|
||||
}
|
||||
else {
|
||||
files.push(file);
|
||||
filesByNameIgnoreCase.set(path, file);
|
||||
}
|
||||
}
|
||||
|
||||
skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib;
|
||||
|
||||
if (!options.noResolve) {
|
||||
processReferencedFiles(file, isDefaultLib);
|
||||
processTypeReferenceDirectives(file);
|
||||
}
|
||||
|
||||
// always process imported modules to record module name resolutions
|
||||
processImportedModules(file);
|
||||
|
||||
if (isDefaultLib) {
|
||||
files.unshift(file);
|
||||
}
|
||||
else {
|
||||
files.push(file);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
function setPackageName(file: SourceFile, packageName: string | undefined): void {
|
||||
if (packageName === undefined) {
|
||||
return;
|
||||
}
|
||||
else if (file.packageName === undefined) {
|
||||
file.packageName = packageName;
|
||||
}
|
||||
else {
|
||||
Debug.assert(file.packageName === packageName, "Same source file loaded from two different packages", () =>
|
||||
`Packages are ${file.packageName} and ${packageName}`);
|
||||
}
|
||||
}
|
||||
|
||||
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
|
||||
forEach(file.referencedFiles, ref => {
|
||||
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
|
||||
|
@ -1634,6 +1655,7 @@ namespace ts {
|
|||
let saveResolution = true;
|
||||
if (resolvedTypeReferenceDirective) {
|
||||
if (resolvedTypeReferenceDirective.primary) {
|
||||
//pass along resolvedTypeReferenceDirective.packageName?
|
||||
// resolved from the primary path
|
||||
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, refFile, refPos, refEnd);
|
||||
}
|
||||
|
@ -1725,7 +1747,7 @@ namespace ts {
|
|||
else if (shouldAddFile) {
|
||||
const path = toPath(resolvedFileName, currentDirectory, getCanonicalFileName);
|
||||
const pos = skipTrivia(file.text, file.imports[i].pos);
|
||||
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, file, pos, file.imports[i].end);
|
||||
findSourceFile(resolvedFileName, path, resolution.packageName, /*isDefaultLib*/ false, file, pos, file.imports[i].end);
|
||||
}
|
||||
|
||||
if (isFromNodeModulesSearch) {
|
||||
|
|
|
@ -1976,7 +1976,7 @@ namespace ts {
|
|||
|
||||
export interface ExportAssignment extends DeclarationStatement {
|
||||
kind: SyntaxKind.ExportAssignment;
|
||||
parent?: SourceFile;
|
||||
parent?: SourceFile | ModuleBlock;
|
||||
isExportEquals?: boolean;
|
||||
expression: Expression;
|
||||
}
|
||||
|
@ -2280,10 +2280,12 @@ namespace ts {
|
|||
|
||||
fileName: string;
|
||||
/* @internal */ path: Path;
|
||||
/** This will be set if the source file is resolved from an external library import. */
|
||||
/* @internal */ packageName: string | undefined;
|
||||
text: string;
|
||||
|
||||
amdDependencies: AmdDependency[];
|
||||
moduleName: string;
|
||||
moduleName: string; // This is set by an `/// <amd-module name="foo" />` directive.
|
||||
referencedFiles: FileReference[];
|
||||
typeReferenceDirectives: FileReference[];
|
||||
languageVariant: LanguageVariant;
|
||||
|
@ -3849,6 +3851,11 @@ namespace ts {
|
|||
* This is optional for backwards-compatibility, but will be added if not provided.
|
||||
*/
|
||||
extension: Extension;
|
||||
/**
|
||||
* Name of the external library that the resolution came from.
|
||||
* For `node_modules/@types/foo/bar.d.ts`, the packageName should be `foo/bar`.
|
||||
*/
|
||||
packageName?: string;
|
||||
}
|
||||
|
||||
export enum Extension {
|
||||
|
@ -3866,6 +3873,7 @@ namespace ts {
|
|||
failedLookupLocations: string[];
|
||||
}
|
||||
|
||||
//packageName here?
|
||||
export interface ResolvedTypeReferenceDirective {
|
||||
// True if the type declaration file was found in a primary lookup location
|
||||
primary: boolean;
|
||||
|
|
|
@ -19,8 +19,8 @@ namespace ts {
|
|||
assert.deepEqual(actual.failedLookupLocations, expectedFailedLookupLocations);
|
||||
}
|
||||
|
||||
export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false): ResolvedModuleFull {
|
||||
return { resolvedFileName, extension: extensionFromPath(resolvedFileName), isExternalLibraryImport };
|
||||
export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false, packageName?: string): ResolvedModuleFull {
|
||||
return { resolvedFileName, extension: extensionFromPath(resolvedFileName), packageName, isExternalLibraryImport };
|
||||
}
|
||||
|
||||
interface File {
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace ts {
|
|||
};
|
||||
}
|
||||
|
||||
describe("printFile", () => {
|
||||
it("printFile", () => {
|
||||
const printsCorrectly = makePrintsCorrectly("printsFileCorrectly");
|
||||
const sourceFile = createSourceFile("source.ts", `
|
||||
interface A<T> {
|
||||
|
@ -57,7 +57,7 @@ namespace ts {
|
|||
printsCorrectly("templateLiteral", {}, printer => printer.printFile(createSourceFile("source.ts", "let greeting = `Hi ${name}, how are you?`;", ScriptTarget.ES2017)));
|
||||
});
|
||||
|
||||
describe("printBundle", () => {
|
||||
it("printBundle", () => {
|
||||
const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly");
|
||||
const bundle = createBundle([
|
||||
createSourceFile("a.ts", `
|
||||
|
@ -77,7 +77,7 @@ namespace ts {
|
|||
printsCorrectly("removeComments", { removeComments: true }, printer => printer.printBundle(bundle));
|
||||
});
|
||||
|
||||
describe("printNode", () => {
|
||||
it("printNode", () => {
|
||||
const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly");
|
||||
const sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015);
|
||||
// tslint:disable boolean-trivia
|
||||
|
|
|
@ -482,6 +482,7 @@ namespace ts {
|
|||
public kind: SyntaxKind.SourceFile;
|
||||
public _declarationBrand: any;
|
||||
public fileName: string;
|
||||
/* @internal */ public packageName: string | undefined;
|
||||
public path: Path;
|
||||
public text: string;
|
||||
public scriptSnapshot: IScriptSnapshot;
|
||||
|
|
|
@ -327,7 +327,7 @@ namespace ts {
|
|||
const resolutionsInFile = <MapLike<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
return map(moduleNames, name => {
|
||||
const result = getProperty(resolutionsInFile, name);
|
||||
return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined;
|
||||
return result ? { resolvedFileName: result, extension: extensionFromPath(result), packageName: undefined, isExternalLibraryImport: false } : undefined;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/a.ts(6,23): error TS6137: Cannot import type declaration files. Consider importing 'foo/' instead of '@types/foo/'.
|
||||
|
||||
|
||||
==== /a.ts (1 errors) ====
|
||||
// These imports must all resolve with the same packageName of "foo",
|
||||
// or else it will trigger an assertion in `setPackageName` in `program.ts`
|
||||
|
||||
import * as foo from "foo";
|
||||
import * as foo2 from "foo/";
|
||||
import * as foo3 from "@types/foo/";
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS6137: Cannot import type declaration files. Consider importing 'foo/' instead of '@types/foo/'.
|
||||
import * as foo4 from "@types\\foo\\";
|
||||
// Relative imports do not have any packageName, so ignored.
|
||||
import * as foo5 from "./node_modules/@types/foo";
|
||||
|
||||
==== /node_modules/@types/foo/index.d.ts (0 errors) ====
|
||||
export const x: number;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//// [tests/cases/compiler/moduleResolution_packageNameConsistent.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
// These imports must all resolve with the same packageName of "foo",
|
||||
// or else it will trigger an assertion in `setPackageName` in `program.ts`
|
||||
|
||||
import * as foo from "foo";
|
||||
import * as foo2 from "foo/";
|
||||
import * as foo3 from "@types/foo/";
|
||||
import * as foo4 from "@types\\foo\\";
|
||||
// Relative imports do not have any packageName, so ignored.
|
||||
import * as foo5 from "./node_modules/@types/foo";
|
||||
|
||||
//// [index.d.ts]
|
||||
export const x: number;
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
// These imports must all resolve with the same packageName of "foo",
|
||||
// or else it will trigger an assertion in `setPackageName` in `program.ts`
|
||||
exports.__esModule = true;
|
|
@ -0,0 +1,62 @@
|
|||
/src/a.ts(6,3): error TS2345: Argument of type 'X' is not assignable to parameter of type 'X'.
|
||||
Types of property 'x' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
/src/a.ts(7,3): error TS2345: Argument of type 'X' is not assignable to parameter of type 'X'.
|
||||
Types have separate declarations of a private property 'x'.
|
||||
|
||||
|
||||
==== /node_modules/a/index.d.ts (0 errors) ====
|
||||
import X from "x";
|
||||
export function a(x: X): void;
|
||||
|
||||
==== /node_modules/a/node_modules/x/index.d.ts (0 errors) ====
|
||||
export default class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
==== /node_modules/b/index.d.ts (0 errors) ====
|
||||
import X from "x";
|
||||
export const b: X;
|
||||
|
||||
==== /node_modules/b/node_modules/x/index.d.ts (0 errors) ====
|
||||
export default class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
==== /node_modules/c/index.d.ts (0 errors) ====
|
||||
import X from "x";
|
||||
export const c: X;
|
||||
|
||||
==== /node_modules/c/node_modules/x/index.d.ts (0 errors) ====
|
||||
// Mismatch -- different type
|
||||
export default class X {
|
||||
private x: string;
|
||||
}
|
||||
|
||||
==== /node_modules/d/index.d.ts (0 errors) ====
|
||||
import { X } from "x";
|
||||
export const d: X;
|
||||
|
||||
==== /node_modules/d/node_modules/x/index.d.ts (0 errors) ====
|
||||
// Mismatch -- is a named export, not a default export
|
||||
export class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
==== /src/a.ts (2 errors) ====
|
||||
import { a } from "a";
|
||||
import { b } from "b";
|
||||
import { c } from "c";
|
||||
import { d } from "d";
|
||||
a(b); // Works
|
||||
a(c); // Error
|
||||
~
|
||||
!!! error TS2345: Argument of type 'X' is not assignable to parameter of type 'X'.
|
||||
!!! error TS2345: Types of property 'x' are incompatible.
|
||||
!!! error TS2345: Type 'string' is not assignable to type 'number'.
|
||||
a(d); // Error
|
||||
~
|
||||
!!! error TS2345: Argument of type 'X' is not assignable to parameter of type 'X'.
|
||||
!!! error TS2345: Types have separate declarations of a private property 'x'.
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//// [tests/cases/compiler/nominalTypeMatchingDuplicateDeclarations0.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
import X from "x";
|
||||
export function a(x: X): void;
|
||||
|
||||
//// [index.d.ts]
|
||||
export default class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
//// [index.d.ts]
|
||||
import X from "x";
|
||||
export const b: X;
|
||||
|
||||
//// [index.d.ts]
|
||||
export default class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
//// [index.d.ts]
|
||||
import X from "x";
|
||||
export const c: X;
|
||||
|
||||
//// [index.d.ts]
|
||||
// Mismatch -- different type
|
||||
export default class X {
|
||||
private x: string;
|
||||
}
|
||||
|
||||
//// [index.d.ts]
|
||||
import { X } from "x";
|
||||
export const d: X;
|
||||
|
||||
//// [index.d.ts]
|
||||
// Mismatch -- is a named export, not a default export
|
||||
export class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
//// [a.ts]
|
||||
import { a } from "a";
|
||||
import { b } from "b";
|
||||
import { c } from "c";
|
||||
import { d } from "d";
|
||||
a(b); // Works
|
||||
a(c); // Error
|
||||
a(d); // Error
|
||||
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a_1 = require("a");
|
||||
var b_1 = require("b");
|
||||
var c_1 = require("c");
|
||||
var d_1 = require("d");
|
||||
a_1.a(b_1.b); // Works
|
||||
a_1.a(c_1.c); // Error
|
||||
a_1.a(d_1.d); // Error
|
|
@ -0,0 +1,64 @@
|
|||
/src/a.ts(9,7): error TS2345: Argument of type 'G.N.X' is not assignable to parameter of type 'G.M.X'.
|
||||
Types have separate declarations of a private property 'x'.
|
||||
/src/a.ts(10,7): error TS2345: Argument of type 'G.N.X' is not assignable to parameter of type 'G.M.X'.
|
||||
Types have separate declarations of a private property 'x'.
|
||||
|
||||
|
||||
==== /node_modules/a/index.d.ts (0 errors) ====
|
||||
import { G } from "x";
|
||||
export function useMX(x: G.M.X): void;
|
||||
export function useNX(x: G.N.X): void;
|
||||
export const an: G.N.X;
|
||||
|
||||
==== /node_modules/a/node_modules/x/index.d.ts (0 errors) ====
|
||||
export namespace G {
|
||||
namespace M {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
namespace N {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
==== /node_modules/b/index.d.ts (0 errors) ====
|
||||
import { G } from "x";
|
||||
export const bm: G.M.X;
|
||||
export const bn: G.N.X;
|
||||
|
||||
==== /node_modules/b/node_modules/x/index.d.ts (0 errors) ====
|
||||
export namespace G {
|
||||
namespace M {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
|
||||
namespace N {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
==== /src/a.ts (2 errors) ====
|
||||
import { an, useMX, useNX } from "a";
|
||||
import { bm, bn } from "b";
|
||||
|
||||
// Works:
|
||||
useMX(bm);
|
||||
useNX(bn);
|
||||
|
||||
// Error:
|
||||
useMX(an);
|
||||
~~
|
||||
!!! error TS2345: Argument of type 'G.N.X' is not assignable to parameter of type 'G.M.X'.
|
||||
!!! error TS2345: Types have separate declarations of a private property 'x'.
|
||||
useMX(bn);
|
||||
~~
|
||||
!!! error TS2345: Argument of type 'G.N.X' is not assignable to parameter of type 'G.M.X'.
|
||||
!!! error TS2345: Types have separate declarations of a private property 'x'.
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//// [tests/cases/compiler/nominalTypeMatchingDuplicateDeclarations1.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
import { G } from "x";
|
||||
export function useMX(x: G.M.X): void;
|
||||
export function useNX(x: G.N.X): void;
|
||||
export const an: G.N.X;
|
||||
|
||||
//// [index.d.ts]
|
||||
export namespace G {
|
||||
namespace M {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
namespace N {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [index.d.ts]
|
||||
import { G } from "x";
|
||||
export const bm: G.M.X;
|
||||
export const bn: G.N.X;
|
||||
|
||||
//// [index.d.ts]
|
||||
export namespace G {
|
||||
namespace M {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
|
||||
namespace N {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [a.ts]
|
||||
import { an, useMX, useNX } from "a";
|
||||
import { bm, bn } from "b";
|
||||
|
||||
// Works:
|
||||
useMX(bm);
|
||||
useNX(bn);
|
||||
|
||||
// Error:
|
||||
useMX(an);
|
||||
useMX(bn);
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a_1 = require("a");
|
||||
var b_1 = require("b");
|
||||
// Works:
|
||||
a_1.useMX(b_1.bm);
|
||||
a_1.useNX(b_1.bn);
|
||||
// Error:
|
||||
a_1.useMX(a_1.an);
|
||||
a_1.useMX(b_1.bn);
|
|
@ -0,0 +1,46 @@
|
|||
/src/a.ts(5,3): error TS2345: Argument of type 'X' is not assignable to parameter of type 'X'.
|
||||
Property 'x' is missing in type 'X'.
|
||||
|
||||
|
||||
==== /node_modules/a/index.d.ts (0 errors) ====
|
||||
import X from "x";
|
||||
export function a(x: X): void;
|
||||
|
||||
==== /node_modules/a/node_modules/x/index.d.ts (0 errors) ====
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
private x: number;
|
||||
}
|
||||
|
||||
==== /node_modules/b/index.d.ts (0 errors) ====
|
||||
import X from "x";
|
||||
export const b: X;
|
||||
|
||||
==== /node_modules/b/node_modules/x/index.d.ts (0 errors) ====
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
private x: number;
|
||||
// OK to provide more members
|
||||
private y: number;
|
||||
}
|
||||
|
||||
==== /node_modules/c/index.d.ts (0 errors) ====
|
||||
import X from "x";
|
||||
export const c: X;
|
||||
|
||||
==== /node_modules/c/node_modules/x/index.d.ts (0 errors) ====
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
// Not OK to be missing a member
|
||||
}
|
||||
|
||||
==== /src/a.ts (1 errors) ====
|
||||
import { a } from "a";
|
||||
import { b } from "b";
|
||||
import { c } from "c";
|
||||
a(b);
|
||||
a(c); // Error
|
||||
~
|
||||
!!! error TS2345: Argument of type 'X' is not assignable to parameter of type 'X'.
|
||||
!!! error TS2345: Property 'x' is missing in type 'X'.
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//// [tests/cases/compiler/nominalTypeMatchingDuplicateDeclarations2.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
import X from "x";
|
||||
export function a(x: X): void;
|
||||
|
||||
//// [index.d.ts]
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
private x: number;
|
||||
}
|
||||
|
||||
//// [index.d.ts]
|
||||
import X from "x";
|
||||
export const b: X;
|
||||
|
||||
//// [index.d.ts]
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
private x: number;
|
||||
// OK to provide more members
|
||||
private y: number;
|
||||
}
|
||||
|
||||
//// [index.d.ts]
|
||||
import X from "x";
|
||||
export const c: X;
|
||||
|
||||
//// [index.d.ts]
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
// Not OK to be missing a member
|
||||
}
|
||||
|
||||
//// [a.ts]
|
||||
import { a } from "a";
|
||||
import { b } from "b";
|
||||
import { c } from "c";
|
||||
a(b);
|
||||
a(c); // Error
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a_1 = require("a");
|
||||
var b_1 = require("b");
|
||||
var c_1 = require("c");
|
||||
a_1.a(b_1.b);
|
||||
a_1.a(c_1.c); // Error
|
|
@ -0,0 +1,34 @@
|
|||
//// [tests/cases/compiler/nominalTypeMatchingDuplicateDeclarations3.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
import X = require("x");
|
||||
export { X as A };
|
||||
|
||||
//// [index.d.ts]
|
||||
export = class {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
//// [index.d.ts]
|
||||
import X = require("x");
|
||||
export { X as B };
|
||||
|
||||
//// [index.d.ts]
|
||||
export = class {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
//// [a.ts]
|
||||
import { A } from "a";
|
||||
import { B } from "b";
|
||||
let a = new A();
|
||||
a = new B();
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a_1 = require("a");
|
||||
var b_1 = require("b");
|
||||
var a = new a_1.A();
|
||||
a = new b_1.B();
|
|
@ -0,0 +1,43 @@
|
|||
=== /node_modules/a/index.d.ts ===
|
||||
import X = require("x");
|
||||
>X : Symbol(X, Decl(index.d.ts, 0, 0))
|
||||
|
||||
export { X as A };
|
||||
>X : Symbol(A, Decl(index.d.ts, 1, 8))
|
||||
>A : Symbol(A, Decl(index.d.ts, 1, 8))
|
||||
|
||||
=== /node_modules/a/node_modules/x/index.d.ts ===
|
||||
export = class {
|
||||
private m(): void;
|
||||
>m : Symbol((Anonymous class).m, Decl(index.d.ts, 0, 16))
|
||||
}
|
||||
|
||||
=== /node_modules/b/index.d.ts ===
|
||||
import X = require("x");
|
||||
>X : Symbol(X, Decl(index.d.ts, 0, 0))
|
||||
|
||||
export { X as B };
|
||||
>X : Symbol(B, Decl(index.d.ts, 1, 8))
|
||||
>B : Symbol(B, Decl(index.d.ts, 1, 8))
|
||||
|
||||
=== /node_modules/b/node_modules/x/index.d.ts ===
|
||||
export = class {
|
||||
private m(): void;
|
||||
>m : Symbol((Anonymous class).m, Decl(index.d.ts, 0, 16))
|
||||
}
|
||||
|
||||
=== /src/a.ts ===
|
||||
import { A } from "a";
|
||||
>A : Symbol(A, Decl(a.ts, 0, 8))
|
||||
|
||||
import { B } from "b";
|
||||
>B : Symbol(B, Decl(a.ts, 1, 8))
|
||||
|
||||
let a = new A();
|
||||
>a : Symbol(a, Decl(a.ts, 2, 3))
|
||||
>A : Symbol(A, Decl(a.ts, 0, 8))
|
||||
|
||||
a = new B();
|
||||
>a : Symbol(a, Decl(a.ts, 2, 3))
|
||||
>B : Symbol(B, Decl(a.ts, 1, 8))
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
=== /node_modules/a/index.d.ts ===
|
||||
import X = require("x");
|
||||
>X : typeof (Anonymous class)
|
||||
|
||||
export { X as A };
|
||||
>X : typeof (Anonymous class)
|
||||
>A : typeof (Anonymous class)
|
||||
|
||||
=== /node_modules/a/node_modules/x/index.d.ts ===
|
||||
export = class {
|
||||
>class { private m(): void;} : typeof (Anonymous class)
|
||||
|
||||
private m(): void;
|
||||
>m : () => void
|
||||
}
|
||||
|
||||
=== /node_modules/b/index.d.ts ===
|
||||
import X = require("x");
|
||||
>X : typeof (Anonymous class)
|
||||
|
||||
export { X as B };
|
||||
>X : typeof (Anonymous class)
|
||||
>B : typeof (Anonymous class)
|
||||
|
||||
=== /node_modules/b/node_modules/x/index.d.ts ===
|
||||
export = class {
|
||||
>class { private m(): void;} : typeof (Anonymous class)
|
||||
|
||||
private m(): void;
|
||||
>m : () => void
|
||||
}
|
||||
|
||||
=== /src/a.ts ===
|
||||
import { A } from "a";
|
||||
>A : typeof (Anonymous class)
|
||||
|
||||
import { B } from "b";
|
||||
>B : typeof (Anonymous class)
|
||||
|
||||
let a = new A();
|
||||
>a : (Anonymous class)
|
||||
>new A() : (Anonymous class)
|
||||
>A : typeof (Anonymous class)
|
||||
|
||||
a = new B();
|
||||
>a = new B() : (Anonymous class)
|
||||
>a : (Anonymous class)
|
||||
>new B() : (Anonymous class)
|
||||
>B : typeof (Anonymous class)
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/src/a.ts(4,1): error TS90010: Type 'C' is not assignable to type 'C'. Two different types with this name exist, but they are unrelated.
|
||||
Types have separate declarations of a private property 'm'.
|
||||
|
||||
|
||||
==== /node_modules/a/c0.d.ts (0 errors) ====
|
||||
export class C {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
==== /node_modules/a/c1.d.ts (0 errors) ====
|
||||
export class C {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
==== /src/a.ts (1 errors) ====
|
||||
import { C as C0 } from "a/c0";
|
||||
import { C as C1 } from "a/c1";
|
||||
let c = new C0();
|
||||
c = new C1();
|
||||
~
|
||||
!!! error TS90010: Type 'C' is not assignable to type 'C'. Two different types with this name exist, but they are unrelated.
|
||||
!!! error TS90010: Types have separate declarations of a private property 'm'.
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
//// [tests/cases/compiler/nominalTypeMatchingDuplicateDeclarations4.ts] ////
|
||||
|
||||
//// [c0.d.ts]
|
||||
export class C {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
//// [c1.d.ts]
|
||||
export class C {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
//// [a.ts]
|
||||
import { C as C0 } from "a/c0";
|
||||
import { C as C1 } from "a/c1";
|
||||
let c = new C0();
|
||||
c = new C1();
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var c0_1 = require("a/c0");
|
||||
var c1_1 = require("a/c1");
|
||||
var c = new c0_1.C();
|
||||
c = new c1_1.C();
|
|
@ -0,0 +1,13 @@
|
|||
// These imports must all resolve with the same packageName of "foo",
|
||||
// or else it will trigger an assertion in `setPackageName` in `program.ts`
|
||||
|
||||
// @Filename: /a.ts
|
||||
import * as foo from "foo";
|
||||
import * as foo2 from "foo/";
|
||||
import * as foo3 from "@types/foo/";
|
||||
import * as foo4 from "@types\\foo\\";
|
||||
// Relative imports do not have any packageName, so ignored.
|
||||
import * as foo5 from "./node_modules/@types/foo";
|
||||
|
||||
// @Filename: /node_modules/@types/foo/index.d.ts
|
||||
export const x: number;
|
|
@ -0,0 +1,47 @@
|
|||
// @Filename: /node_modules/a/index.d.ts
|
||||
import X from "x";
|
||||
export function a(x: X): void;
|
||||
|
||||
// @Filename: /node_modules/a/node_modules/x/index.d.ts
|
||||
export default class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/b/index.d.ts
|
||||
import X from "x";
|
||||
export const b: X;
|
||||
|
||||
// @Filename: /node_modules/b/node_modules/x/index.d.ts
|
||||
export default class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/c/index.d.ts
|
||||
import X from "x";
|
||||
export const c: X;
|
||||
|
||||
// @Filename: /node_modules/c/node_modules/x/index.d.ts
|
||||
// Mismatch -- different type
|
||||
export default class X {
|
||||
private x: string;
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/d/index.d.ts
|
||||
import { X } from "x";
|
||||
export const d: X;
|
||||
|
||||
// @Filename: /node_modules/d/node_modules/x/index.d.ts
|
||||
// Mismatch -- is a named export, not a default export
|
||||
export class X {
|
||||
private x: number;
|
||||
}
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
import { a } from "a";
|
||||
import { b } from "b";
|
||||
import { c } from "c";
|
||||
import { d } from "d";
|
||||
a(b); // Works
|
||||
a(c); // Error
|
||||
a(d); // Error
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// @Filename: /node_modules/a/index.d.ts
|
||||
import { G } from "x";
|
||||
export function useMX(x: G.M.X): void;
|
||||
export function useNX(x: G.N.X): void;
|
||||
export const an: G.N.X;
|
||||
|
||||
// @Filename: /node_modules/a/node_modules/x/index.d.ts
|
||||
export namespace G {
|
||||
namespace M {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
namespace N {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/b/index.d.ts
|
||||
import { G } from "x";
|
||||
export const bm: G.M.X;
|
||||
export const bn: G.N.X;
|
||||
|
||||
// @Filename: /node_modules/b/node_modules/x/index.d.ts
|
||||
export namespace G {
|
||||
namespace M {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
|
||||
namespace N {
|
||||
class X {
|
||||
private x: number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
import { an, useMX, useNX } from "a";
|
||||
import { bm, bn } from "b";
|
||||
|
||||
// Works:
|
||||
useMX(bm);
|
||||
useNX(bn);
|
||||
|
||||
// Error:
|
||||
useMX(an);
|
||||
useMX(bn);
|
|
@ -0,0 +1,38 @@
|
|||
// @Filename: /node_modules/a/index.d.ts
|
||||
import X from "x";
|
||||
export function a(x: X): void;
|
||||
|
||||
// @Filename: /node_modules/a/node_modules/x/index.d.ts
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
private x: number;
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/b/index.d.ts
|
||||
import X from "x";
|
||||
export const b: X;
|
||||
|
||||
// @Filename: /node_modules/b/node_modules/x/index.d.ts
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
private x: number;
|
||||
// OK to provide more members
|
||||
private y: number;
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/c/index.d.ts
|
||||
import X from "x";
|
||||
export const c: X;
|
||||
|
||||
// @Filename: /node_modules/c/node_modules/x/index.d.ts
|
||||
export default class X {
|
||||
protected m(): void;
|
||||
// Not OK to be missing a member
|
||||
}
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
import { a } from "a";
|
||||
import { b } from "b";
|
||||
import { c } from "c";
|
||||
a(b);
|
||||
a(c); // Error
|
|
@ -0,0 +1,23 @@
|
|||
// @Filename: /node_modules/a/index.d.ts
|
||||
import X = require("x");
|
||||
export { X as A };
|
||||
|
||||
// @Filename: /node_modules/a/node_modules/x/index.d.ts
|
||||
export = class {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/b/index.d.ts
|
||||
import X = require("x");
|
||||
export { X as B };
|
||||
|
||||
// @Filename: /node_modules/b/node_modules/x/index.d.ts
|
||||
export = class {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
import { A } from "a";
|
||||
import { B } from "b";
|
||||
let a = new A();
|
||||
a = new B();
|
|
@ -0,0 +1,15 @@
|
|||
// @Filename: /node_modules/a/c0.d.ts
|
||||
export class C {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
// @Filename: /node_modules/a/c1.d.ts
|
||||
export class C {
|
||||
private m(): void;
|
||||
}
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
import { C as C0 } from "a/c0";
|
||||
import { C as C1 } from "a/c1";
|
||||
let c = new C0();
|
||||
c = new C1();
|
Loading…
Reference in a new issue