@zzzen/pyright-internal 1.2.0-dev.20260222 → 1.2.0-dev.20260422

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/dist/analyzer/backgroundAnalysisProgram.d.ts +1 -1
  2. package/dist/analyzer/backgroundAnalysisProgram.js +9 -6
  3. package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
  4. package/dist/analyzer/binder.d.ts +10 -1
  5. package/dist/analyzer/binder.js +258 -41
  6. package/dist/analyzer/binder.js.map +1 -1
  7. package/dist/analyzer/cellChainIndex.d.ts +34 -0
  8. package/dist/analyzer/cellChainIndex.js +126 -0
  9. package/dist/analyzer/cellChainIndex.js.map +1 -0
  10. package/dist/analyzer/checker.js +0 -1
  11. package/dist/analyzer/checker.js.map +1 -1
  12. package/dist/analyzer/codeFlowEngine.js +16 -1
  13. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  14. package/dist/analyzer/constructors.js +9 -2
  15. package/dist/analyzer/constructors.js.map +1 -1
  16. package/dist/analyzer/importResolver.d.ts +3 -21
  17. package/dist/analyzer/importResolver.js +42 -316
  18. package/dist/analyzer/importResolver.js.map +1 -1
  19. package/dist/analyzer/importResolverFileSystem.d.ts +3 -0
  20. package/dist/analyzer/importResolverFileSystem.js +160 -0
  21. package/dist/analyzer/importResolverFileSystem.js.map +1 -0
  22. package/dist/analyzer/importResolverTypes.d.ts +24 -0
  23. package/dist/analyzer/importResolverTypes.js +8 -0
  24. package/dist/analyzer/importResolverTypes.js.map +1 -0
  25. package/dist/analyzer/importStatementUtils.js +9 -0
  26. package/dist/analyzer/importStatementUtils.js.map +1 -1
  27. package/dist/analyzer/parseTreeUtils.d.ts +1 -0
  28. package/dist/analyzer/parseTreeUtils.js +24 -7
  29. package/dist/analyzer/parseTreeUtils.js.map +1 -1
  30. package/dist/analyzer/patternMatching.js +14 -2
  31. package/dist/analyzer/patternMatching.js.map +1 -1
  32. package/dist/analyzer/program.d.ts +5 -3
  33. package/dist/analyzer/program.js +40 -51
  34. package/dist/analyzer/program.js.map +1 -1
  35. package/dist/analyzer/pythonPathUtils.d.ts +1 -1
  36. package/dist/analyzer/pythonPathUtils.js +3 -1
  37. package/dist/analyzer/pythonPathUtils.js.map +1 -1
  38. package/dist/analyzer/scope.d.ts +10 -1
  39. package/dist/analyzer/scope.js +14 -1
  40. package/dist/analyzer/scope.js.map +1 -1
  41. package/dist/analyzer/service.d.ts +11 -6
  42. package/dist/analyzer/service.js +82 -83
  43. package/dist/analyzer/service.js.map +1 -1
  44. package/dist/analyzer/sourceEnumerator.d.ts +3 -0
  45. package/dist/analyzer/sourceEnumerator.js +27 -1
  46. package/dist/analyzer/sourceEnumerator.js.map +1 -1
  47. package/dist/analyzer/sourceFile.d.ts +2 -1
  48. package/dist/analyzer/sourceFile.js +2 -2
  49. package/dist/analyzer/sourceFile.js.map +1 -1
  50. package/dist/analyzer/sourceFileInfo.d.ts +4 -0
  51. package/dist/analyzer/sourceFileInfo.js +9 -0
  52. package/dist/analyzer/sourceFileInfo.js.map +1 -1
  53. package/dist/analyzer/sourceMapper.d.ts +1 -0
  54. package/dist/analyzer/sourceMapper.js +44 -0
  55. package/dist/analyzer/sourceMapper.js.map +1 -1
  56. package/dist/analyzer/tuples.js +3 -1
  57. package/dist/analyzer/tuples.js.map +1 -1
  58. package/dist/analyzer/typeEvaluator.js +102 -51
  59. package/dist/analyzer/typeEvaluator.js.map +1 -1
  60. package/dist/analyzer/typeEvaluatorTypes.d.ts +2 -0
  61. package/dist/analyzer/typeEvaluatorTypes.js +4 -0
  62. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  63. package/dist/analyzer/typeGuards.js +28 -6
  64. package/dist/analyzer/typeGuards.js.map +1 -1
  65. package/dist/analyzer/typeStubWriter.d.ts +15 -50
  66. package/dist/analyzer/typeStubWriter.js +91 -9
  67. package/dist/analyzer/typeStubWriter.js.map +1 -1
  68. package/dist/analyzer/typeUtils.d.ts +1 -0
  69. package/dist/analyzer/typeUtils.js +27 -3
  70. package/dist/analyzer/typeUtils.js.map +1 -1
  71. package/dist/analyzer/typeshedInfoProvider.d.ts +2 -0
  72. package/dist/analyzer/typeshedInfoProvider.js +232 -0
  73. package/dist/analyzer/typeshedInfoProvider.js.map +1 -0
  74. package/dist/backgroundAnalysisBase.d.ts +3 -3
  75. package/dist/backgroundAnalysisBase.js +12 -9
  76. package/dist/backgroundAnalysisBase.js.map +1 -1
  77. package/dist/commands/createTypeStub.d.ts +16 -8
  78. package/dist/commands/createTypeStub.js +58 -36
  79. package/dist/commands/createTypeStub.js.map +1 -1
  80. package/dist/common/cancellationUtils.d.ts +7 -0
  81. package/dist/common/cancellationUtils.js +34 -0
  82. package/dist/common/cancellationUtils.js.map +1 -1
  83. package/dist/common/collectionUtils.d.ts +3 -3
  84. package/dist/common/collectionUtils.js.map +1 -1
  85. package/dist/common/core.d.ts +1 -1
  86. package/dist/common/core.js.map +1 -1
  87. package/dist/common/crypto.js +11 -0
  88. package/dist/common/crypto.js.map +1 -1
  89. package/dist/common/extensibility.d.ts +7 -0
  90. package/dist/common/extensibility.js.map +1 -1
  91. package/dist/common/fullAccessHost.js +4 -2
  92. package/dist/common/fullAccessHost.js.map +1 -1
  93. package/dist/common/pathUtils.d.ts +4 -1
  94. package/dist/common/pathUtils.js.map +1 -1
  95. package/dist/common/realFileSystem.js +42 -3
  96. package/dist/common/realFileSystem.js.map +1 -1
  97. package/dist/common/serviceKeys.d.ts +3 -0
  98. package/dist/common/serviceKeys.js +2 -0
  99. package/dist/common/serviceKeys.js.map +1 -1
  100. package/dist/common/serviceProviderExtensions.js.map +1 -1
  101. package/dist/common/uri/uriUtils.d.ts +4 -0
  102. package/dist/common/uri/uriUtils.js +19 -3
  103. package/dist/common/uri/uriUtils.js.map +1 -1
  104. package/dist/common/workspaceEditUtils.js +0 -2
  105. package/dist/common/workspaceEditUtils.js.map +1 -1
  106. package/dist/languageServerBase.d.ts +1 -0
  107. package/dist/languageServerBase.js +6 -0
  108. package/dist/languageServerBase.js.map +1 -1
  109. package/dist/languageService/completionProvider.d.ts +6 -0
  110. package/dist/languageService/completionProvider.js +252 -75
  111. package/dist/languageService/completionProvider.js.map +1 -1
  112. package/dist/languageService/definitionProvider.js +1 -1
  113. package/dist/languageService/definitionProvider.js.map +1 -1
  114. package/dist/languageService/documentSymbolCollector.js +34 -4
  115. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  116. package/dist/languageService/dynamicFeature.d.ts +3 -0
  117. package/dist/languageService/dynamicFeature.js +5 -0
  118. package/dist/languageService/dynamicFeature.js.map +1 -1
  119. package/dist/languageService/hoverProvider.d.ts +2 -1
  120. package/dist/languageService/hoverProvider.js +13 -5
  121. package/dist/languageService/hoverProvider.js.map +1 -1
  122. package/dist/languageService/pullDiagnosticsDynamicFeature.d.ts +1 -0
  123. package/dist/languageService/pullDiagnosticsDynamicFeature.js +4 -0
  124. package/dist/languageService/pullDiagnosticsDynamicFeature.js.map +1 -1
  125. package/dist/languageService/referencesProvider.js +5 -4
  126. package/dist/languageService/referencesProvider.js.map +1 -1
  127. package/dist/languageService/signatureHelpProvider.d.ts +1 -0
  128. package/dist/languageService/signatureHelpProvider.js +76 -2
  129. package/dist/languageService/signatureHelpProvider.js.map +1 -1
  130. package/dist/languageService/symbolIndexer.d.ts +1 -0
  131. package/dist/languageService/symbolIndexer.js.map +1 -1
  132. package/dist/languageService/tooltipUtils.d.ts +11 -4
  133. package/dist/languageService/tooltipUtils.js +195 -7
  134. package/dist/languageService/tooltipUtils.js.map +1 -1
  135. package/dist/parser/tokenizer.js +6 -2
  136. package/dist/parser/tokenizer.js.map +1 -1
  137. package/dist/partialStubService.d.ts +11 -0
  138. package/dist/partialStubService.js +23 -1
  139. package/dist/partialStubService.js.map +1 -1
  140. package/dist/pyright.js +13 -2
  141. package/dist/pyright.js.map +1 -1
  142. package/dist/tests/chainedSourceFiles.test.js +138 -0
  143. package/dist/tests/chainedSourceFiles.test.js.map +1 -1
  144. package/dist/tests/checker.test.js +12 -0
  145. package/dist/tests/checker.test.js.map +1 -1
  146. package/dist/tests/completions.test.js +328 -0
  147. package/dist/tests/completions.test.js.map +1 -1
  148. package/dist/tests/config.test.js +54 -0
  149. package/dist/tests/config.test.js.map +1 -1
  150. package/dist/tests/filesystem.test.js +44 -0
  151. package/dist/tests/filesystem.test.js.map +1 -1
  152. package/dist/tests/fourSlashRunner.test.js +1 -1
  153. package/dist/tests/fourSlashRunner.test.js.map +1 -1
  154. package/dist/tests/fourslash/findDefinitions.definitionFilter.preferSource.fourslash.js +25 -1
  155. package/dist/tests/fourslash/findDefinitions.definitionFilter.preferSource.fourslash.js.map +1 -1
  156. package/dist/tests/fourslash/import.multipart3.fourslash.d.ts +1 -0
  157. package/dist/tests/fourslash/import.multipart3.fourslash.js +46 -0
  158. package/dist/tests/fourslash/import.multipart3.fourslash.js.map +1 -0
  159. package/dist/tests/fourslash/import.pytyped.unsupportedDunderAll.fourslash.d.ts +1 -0
  160. package/dist/tests/fourslash/import.pytyped.unsupportedDunderAll.fourslash.js +33 -0
  161. package/dist/tests/fourslash/import.pytyped.unsupportedDunderAll.fourslash.js.map +1 -0
  162. package/dist/tests/harness/fourslash/runner.d.ts +4 -4
  163. package/dist/tests/harness/fourslash/runner.js +5 -5
  164. package/dist/tests/harness/fourslash/runner.js.map +1 -1
  165. package/dist/tests/harness/fourslash/testState.d.ts +20 -5
  166. package/dist/tests/harness/fourslash/testState.js +11 -26
  167. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  168. package/dist/tests/harness/fourslash/testStateUtils.js +2 -0
  169. package/dist/tests/harness/fourslash/testStateUtils.js.map +1 -1
  170. package/dist/tests/harness/testAccessHost.d.ts +3 -1
  171. package/dist/tests/harness/testAccessHost.js +6 -2
  172. package/dist/tests/harness/testAccessHost.js.map +1 -1
  173. package/dist/tests/harness/testHost.js +20 -18
  174. package/dist/tests/harness/testHost.js.map +1 -1
  175. package/dist/tests/harness/vfs/factory.js +4 -1
  176. package/dist/tests/harness/vfs/factory.js.map +1 -1
  177. package/dist/tests/harness/vfs/filesystem.d.ts +8 -1
  178. package/dist/tests/harness/vfs/filesystem.js +84 -30
  179. package/dist/tests/harness/vfs/filesystem.js.map +1 -1
  180. package/dist/tests/hoverProvider.test.js +290 -0
  181. package/dist/tests/hoverProvider.test.js.map +1 -1
  182. package/dist/tests/importResolverSupport.test.d.ts +1 -0
  183. package/dist/tests/importResolverSupport.test.js +319 -0
  184. package/dist/tests/importResolverSupport.test.js.map +1 -0
  185. package/dist/tests/importStatementUtils.test.js +66 -0
  186. package/dist/tests/importStatementUtils.test.js.map +1 -1
  187. package/dist/tests/lsp/{webpack.testserver.config.d.ts → rspack.testserver.config.d.ts} +1 -1
  188. package/dist/tests/lsp/{webpack.testserver.config.js → rspack.testserver.config.js} +4 -11
  189. package/dist/tests/lsp/rspack.testserver.config.js.map +1 -0
  190. package/dist/tests/realTempFile.test.d.ts +1 -0
  191. package/dist/tests/realTempFile.test.js +144 -0
  192. package/dist/tests/realTempFile.test.js.map +1 -0
  193. package/dist/tests/service.test.js +182 -3
  194. package/dist/tests/service.test.js.map +1 -1
  195. package/dist/tests/signatureHelp.test.js +391 -6
  196. package/dist/tests/signatureHelp.test.js.map +1 -1
  197. package/dist/tests/testState.test.js +19 -0
  198. package/dist/tests/testState.test.js.map +1 -1
  199. package/dist/tests/tokenizer.test.js +42 -0
  200. package/dist/tests/tokenizer.test.js.map +1 -1
  201. package/dist/tests/typeEvaluator1.test.js +4 -0
  202. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  203. package/dist/tests/typeEvaluator2.test.js +12 -0
  204. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  205. package/dist/tests/typeEvaluator3.test.js +8 -1
  206. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  207. package/dist/tests/typeEvaluator6.test.js +7 -0
  208. package/dist/tests/typeEvaluator6.test.js.map +1 -1
  209. package/dist/tests/typeEvaluator8.test.js +13 -1
  210. package/dist/tests/typeEvaluator8.test.js.map +1 -1
  211. package/dist/tests/uri.test.js +29 -0
  212. package/dist/tests/uri.test.js.map +1 -1
  213. package/dist/tests/wildcardImportPackageMerge.test.d.ts +1 -0
  214. package/dist/tests/wildcardImportPackageMerge.test.js +97 -0
  215. package/dist/tests/wildcardImportPackageMerge.test.js.map +1 -0
  216. package/dist/tests/workspaceEditUtils.test.js +0 -1
  217. package/dist/tests/workspaceEditUtils.test.js.map +1 -1
  218. package/package.json +12 -11
  219. package/dist/tests/lsp/webpack.testserver.config.js.map +0 -1
@@ -43,15 +43,18 @@ const configOptions_1 = require("../common/configOptions");
43
43
  const pathConsts_1 = require("../common/pathConsts");
44
44
  const pathUtils_1 = require("../common/pathUtils");
45
45
  const pythonVersion_1 = require("../common/pythonVersion");
46
+ const serviceKeys_1 = require("../common/serviceKeys");
46
47
  const StringUtils = __importStar(require("../common/stringUtils"));
47
48
  const stringUtils_1 = require("../common/stringUtils");
48
49
  const uri_1 = require("../common/uri/uri");
49
50
  const uriUtils_1 = require("../common/uri/uriUtils");
50
51
  const tokenizer_1 = require("../parser/tokenizer");
51
52
  const importLogger_1 = require("./importLogger");
53
+ const importResolverFileSystem_1 = require("./importResolverFileSystem");
52
54
  const importStatementUtils_1 = require("./importStatementUtils");
53
55
  const parentDirectoryCache_1 = require("./parentDirectoryCache");
54
56
  const pyTypedUtils_1 = require("./pyTypedUtils");
57
+ const typeshedInfoProvider_1 = require("./typeshedInfoProvider");
55
58
  const PythonPathUtils = __importStar(require("./pythonPathUtils"));
56
59
  const SymbolNameUtils = __importStar(require("./symbolNameUtils"));
57
60
  const symbolNameUtils_1 = require("./symbolNameUtils");
@@ -89,10 +92,16 @@ class ImportResolver {
89
92
  this.host = host;
90
93
  this._cachedImportResults = new Map();
91
94
  this._cachedModuleNameResults = new Map();
92
- this._cachedEntriesForPath = new Map();
93
- this._cachedFilesForPath = new Map();
94
- this._cachedDirExistenceForRoot = new Map();
95
95
  this.cachedParentImportResults = new parentDirectoryCache_1.ParentDirectoryCache(() => this.getPythonSearchPaths());
96
+ // These are optionally provided via the ServiceProvider so callers/tests can share
97
+ // caching across ImportResolver/Typeshed operations and avoid re-walking the same
98
+ // filesystem paths when multiple resolvers are created.
99
+ this._fileSystemCache =
100
+ serviceProvider.tryGet(serviceKeys_1.ServiceKeys.importResolverFileSystem) ??
101
+ (0, importResolverFileSystem_1.createImportResolverFileSystem)(this.fileSystem);
102
+ this._typeshedInfoProvider =
103
+ serviceProvider.tryGet(serviceKeys_1.ServiceKeys.typeshedInfoProvider) ??
104
+ (0, typeshedInfoProvider_1.createDefaultTypeshedInfoProvider)(this._fileSystemCache);
96
105
  }
97
106
  get fileSystem() {
98
107
  return this.serviceProvider.fs();
@@ -338,10 +347,8 @@ class ImportResolver {
338
347
  if (!typeshedStdlibPath) {
339
348
  return excludes;
340
349
  }
341
- if (!this._cachedTypeshedStdLibModuleVersionInfo) {
342
- this._cachedTypeshedStdLibModuleVersionInfo = this._readTypeshedStdLibVersions(customTypeshedPath);
343
- }
344
- this._cachedTypeshedStdLibModuleVersionInfo.forEach((versionInfo, moduleName) => {
350
+ const versions = this._getTypeshedInfoProvider().getStdLibModuleVersionInfo(customTypeshedPath);
351
+ versions.forEach((versionInfo, moduleName) => {
345
352
  let shouldExcludeModule = false;
346
353
  if (versionInfo.max !== undefined && pythonVersion_1.PythonVersion.isGreaterThan(pythonVersion, versionInfo.max)) {
347
354
  shouldExcludeModule = true;
@@ -378,42 +385,6 @@ class ImportResolver {
378
385
  getTypeshedPathEx(execEnv, importLogger) {
379
386
  return undefined;
380
387
  }
381
- readdirEntriesCached(uri) {
382
- const cachedValue = this._cachedEntriesForPath.get(uri.key);
383
- if (cachedValue) {
384
- return cachedValue;
385
- }
386
- const newCachedDir = {
387
- entries: new Map(),
388
- resolvableNames: new Set(),
389
- };
390
- try {
391
- const entries = this.fileSystem.readdirEntriesSync(uri);
392
- entries.forEach((entry) => {
393
- newCachedDir.entries.set(entry.name, entry);
394
- let isFile = entry.isFile();
395
- let isDirectory = entry.isDirectory();
396
- if (entry.isSymbolicLink()) {
397
- const stat = (0, uriUtils_1.tryStat)(this.fileSystem, uri.combinePaths(entry.name));
398
- isFile = !!stat?.isFile();
399
- isDirectory = !!stat?.isDirectory();
400
- }
401
- const resolvableName = isFile
402
- ? (0, pathUtils_1.stripFileExtension)(entry.name, /* multiDotExtension */ true)
403
- : entry.name;
404
- newCachedDir.resolvableNames.add(resolvableName);
405
- if (isDirectory && entry.name.endsWith(pathConsts_1.stubsSuffix)) {
406
- newCachedDir.resolvableNames.add(resolvableName.substring(0, resolvableName.length - pathConsts_1.stubsSuffix.length));
407
- }
408
- });
409
- }
410
- catch {
411
- // Swallow error
412
- }
413
- // Populate cache.
414
- this._cachedEntriesForPath.set(uri.key, newCachedDir);
415
- return newCachedDir;
416
- }
417
388
  // Resolves the import and returns the path if it exists, otherwise
418
389
  // returns undefined.
419
390
  resolveImportInternal(sourceFileUri, execEnv, moduleDescriptor) {
@@ -437,7 +408,6 @@ class ImportResolver {
437
408
  return importResult;
438
409
  }
439
410
  const importLogger = this._configOptions.verboseOutput ? new importLogger_1.ImportLogger() : undefined;
440
- importLogger?.log(`Attempting to resolve using local imports: ${importName}`);
441
411
  const importPath = { importPath: undefined };
442
412
  // Going up the given folder one by one until we can resolve the import.
443
413
  let current = origin;
@@ -470,50 +440,10 @@ class ImportResolver {
470
440
  return importResult;
471
441
  }
472
442
  fileExistsCached(uri) {
473
- const directory = uri.getDirectory();
474
- if (directory.equals(uri)) {
475
- // Started at root, so this can't be a file.
476
- return false;
477
- }
478
- const cachedDir = this.readdirEntriesCached(directory);
479
- const entry = cachedDir.entries.get(uri.fileName);
480
- if (entry?.isFile()) {
481
- return true;
482
- }
483
- if (entry?.isSymbolicLink()) {
484
- const realPath = (0, uriUtils_1.tryRealpath)(this.fileSystem, uri);
485
- if (realPath && this.fileSystem.existsSync(realPath) && (0, uriUtils_1.isFile)(this.fileSystem, realPath)) {
486
- return true;
487
- }
488
- }
489
- return false;
443
+ return this._fileSystemCache.fileExists(uri);
490
444
  }
491
445
  dirExistsCached(uri) {
492
- const parent = uri.getDirectory();
493
- if (parent.equals(uri)) {
494
- // Started at root. No entries to read, so have to check ourselves.
495
- let cachedExistence = this._cachedDirExistenceForRoot.get(uri.key);
496
- // Check if the value was in the cache or not. Undefined means it wasn't.
497
- if (cachedExistence === undefined) {
498
- cachedExistence = (0, uriUtils_1.tryStat)(this.fileSystem, uri)?.isDirectory() ?? false;
499
- this._cachedDirExistenceForRoot.set(uri.key, cachedExistence);
500
- }
501
- return cachedExistence;
502
- }
503
- // Otherwise not a root, so read the entries we have cached to see if
504
- // the directory exists or not.
505
- const cachedDir = this.readdirEntriesCached(parent);
506
- const entry = cachedDir.entries.get(uri.fileName);
507
- if (entry?.isDirectory()) {
508
- return true;
509
- }
510
- if (entry?.isSymbolicLink()) {
511
- const realPath = (0, uriUtils_1.tryRealpath)(this.fileSystem, uri);
512
- if (realPath && this.fileSystem.existsSync(realPath) && (0, uriUtils_1.isDirectory)(this.fileSystem, realPath)) {
513
- return true;
514
- }
515
- }
516
- return false;
446
+ return this._fileSystemCache.dirExists(uri);
517
447
  }
518
448
  addResultsToCache(sourceFileUri, execEnv, importName, importResult, moduleDescriptor, fromUserFile) {
519
449
  // If the import is relative, include the source file path in the key.
@@ -599,7 +529,7 @@ class ImportResolver {
599
529
  findImplicitImports(importingModuleName, dirPath, exclusions) {
600
530
  const implicitImportMap = new Map();
601
531
  // Enumerate all of the files and directories in the path, expanding links.
602
- const entries = (0, uriUtils_1.getFileSystemEntriesFromDirEntries)(this.readdirEntriesCached(dirPath).entries.values(), this.fileSystem, dirPath);
532
+ const entries = (0, uriUtils_1.getFileSystemEntriesFromDirEntries)(this._fileSystemCache.readdirEntriesSync(dirPath), this.fileSystem, dirPath);
603
533
  // Add implicit file-based modules.
604
534
  for (const filePath of entries.files) {
605
535
  const fileExt = filePath.lastExtension;
@@ -670,9 +600,9 @@ class ImportResolver {
670
600
  return implicitImportMap.size > 0 ? implicitImportMap : undefined;
671
601
  }
672
602
  _isPossibleImportDir(rootPath, moduleDescriptor) {
673
- const cachedDir = this.readdirEntriesCached(rootPath);
603
+ const resolvableNames = this._fileSystemCache.getResolvableNamesInDirectory(rootPath);
674
604
  const isPotentialMatch = (name) => {
675
- return cachedDir.resolvableNames.has(name);
605
+ return resolvableNames.has(name);
676
606
  };
677
607
  if (moduleDescriptor.nameParts.length > 0) {
678
608
  return isPotentialMatch(moduleDescriptor.nameParts[0]);
@@ -942,9 +872,7 @@ class ImportResolver {
942
872
  };
943
873
  }
944
874
  _invalidateFileSystemCache() {
945
- this._cachedEntriesForPath.clear();
946
- this._cachedFilesForPath.clear();
947
- this._cachedDirExistenceForRoot.clear();
875
+ this._fileSystemCache.invalidateCache();
948
876
  }
949
877
  _resolveAbsoluteImport(rootPath, execEnv, moduleDescriptor, importName, importLogger, allowPartial, allowNativeLib, useStubPackage, allowPyi, lookForPyTyped) {
950
878
  if (useStubPackage) {
@@ -1219,7 +1147,8 @@ class ImportResolver {
1219
1147
  // If a library is fully py.typed, then we have found the best match,
1220
1148
  // unless the execution environment is typeshed itself, in which case
1221
1149
  // we don't want to favor py.typed libraries. Use the typeshed lookup below.
1222
- if (execEnv.root !== this._getTypeshedRoot(this._configOptions.typeshedPath, importLogger)) {
1150
+ if (execEnv.root !==
1151
+ this._getTypeshedInfoProvider().getTypeshedRoot(this._configOptions.typeshedPath, importLogger)) {
1223
1152
  if (bestResultSoFar?.pyTypedInfo && !bestResultSoFar.isPartlyResolved) {
1224
1153
  return bestResultSoFar;
1225
1154
  }
@@ -1372,7 +1301,7 @@ class ImportResolver {
1372
1301
  const cache = new Set();
1373
1302
  if (stdlibRoot) {
1374
1303
  const readDir = (root, prefix) => {
1375
- this.readdirEntriesCached(root).entries.forEach((entry) => {
1304
+ this._fileSystemCache.readdirEntriesSync(root).forEach((entry) => {
1376
1305
  if (entry.isDirectory()) {
1377
1306
  const dirRoot = root.combinePaths(entry.name);
1378
1307
  readDir(dirRoot, prefix ? `${prefix}.${entry.name}` : entry.name);
@@ -1397,46 +1326,9 @@ class ImportResolver {
1397
1326
  // the pypi-registered name of the package and an inner directory contains
1398
1327
  // the name of the package as it is referenced by import statements. These
1399
1328
  // don't always match.
1400
- _buildTypeshedThirdPartyPackageMap(thirdPartyDir) {
1401
- this._cachedTypeshedThirdPartyPackagePaths = new Map();
1402
- if (thirdPartyDir) {
1403
- this.readdirEntriesCached(thirdPartyDir).entries.forEach((outerEntry) => {
1404
- if (outerEntry.isDirectory()) {
1405
- const innerDirPath = thirdPartyDir.combinePaths(outerEntry.name);
1406
- this.readdirEntriesCached(innerDirPath).entries.forEach((innerEntry) => {
1407
- if (innerEntry.name === '@python2') {
1408
- return;
1409
- }
1410
- if (innerEntry.isDirectory()) {
1411
- const pathList = this._cachedTypeshedThirdPartyPackagePaths.get(innerEntry.name);
1412
- if (pathList) {
1413
- pathList.push(innerDirPath);
1414
- }
1415
- else {
1416
- this._cachedTypeshedThirdPartyPackagePaths.set(innerEntry.name, [innerDirPath]);
1417
- }
1418
- }
1419
- else if (innerEntry.isFile()) {
1420
- if (innerEntry.name.endsWith('.pyi')) {
1421
- const strippedFileName = (0, pathUtils_1.stripFileExtension)(innerEntry.name);
1422
- const pathList = this._cachedTypeshedThirdPartyPackagePaths.get(strippedFileName);
1423
- if (pathList) {
1424
- pathList.push(innerDirPath);
1425
- }
1426
- else {
1427
- this._cachedTypeshedThirdPartyPackagePaths.set(strippedFileName, [innerDirPath]);
1428
- }
1429
- }
1430
- }
1431
- });
1432
- }
1433
- });
1434
- }
1435
- const flattenPaths = Array.from(this._cachedTypeshedThirdPartyPackagePaths.values()).flatMap((v) => v);
1436
- this._cachedTypeshedThirdPartyPackageRoots = Array.from(new Set(flattenPaths)).sort();
1437
- }
1438
1329
  _getCompletionSuggestionsTypeshedPath(sourceFileUri, execEnv, moduleDescriptor, isStdLib, suggestions) {
1439
1330
  let typeshedPaths;
1331
+ let typeshedPathEx;
1440
1332
  if (isStdLib) {
1441
1333
  const path = this._getStdlibTypeshedPath(this._configOptions.typeshedPath, execEnv.pythonVersion, execEnv.pythonPlatform,
1442
1334
  /* importLogger */ undefined, moduleDescriptor);
@@ -1448,16 +1340,12 @@ class ImportResolver {
1448
1340
  typeshedPaths = this._getThirdPartyTypeshedPackagePaths(moduleDescriptor,
1449
1341
  /* importLogger */ undefined,
1450
1342
  /* includeMatchOnly */ false);
1451
- const typeshedPathEx = this.getTypeshedPathEx(execEnv);
1452
- if (typeshedPathEx) {
1453
- typeshedPaths = typeshedPaths ?? [];
1454
- typeshedPaths.push(typeshedPathEx);
1455
- }
1343
+ typeshedPathEx = this.getTypeshedPathEx(execEnv);
1456
1344
  }
1457
- if (!typeshedPaths) {
1345
+ if (!typeshedPaths && !typeshedPathEx) {
1458
1346
  return;
1459
1347
  }
1460
- typeshedPaths.forEach((typeshedPath) => {
1348
+ (typeshedPaths ?? []).concat(typeshedPathEx ?? []).forEach((typeshedPath) => {
1461
1349
  if (this.dirExistsCached(typeshedPath)) {
1462
1350
  this._getCompletionSuggestionsAbsolute(sourceFileUri, execEnv, typeshedPath, moduleDescriptor, suggestions);
1463
1351
  }
@@ -1467,7 +1355,8 @@ class ImportResolver {
1467
1355
  // If moduleDescriptor is provided, it is filtered based on the VERSIONS
1468
1356
  // file in the typeshed stubs.
1469
1357
  _getStdlibTypeshedPath(customTypeshedPath, pythonVersion, pythonPlatform, importLogger, moduleDescriptor) {
1470
- const subdirectory = this._getTypeshedSubdirectory(/* isStdLib */ true, customTypeshedPath, importLogger);
1358
+ const subdirectory = this._getTypeshedInfoProvider().getTypeshedSubdirectory(
1359
+ /* isStdLib */ true, customTypeshedPath, importLogger);
1471
1360
  if (subdirectory &&
1472
1361
  moduleDescriptor &&
1473
1362
  !this._isStdlibTypeshedStubValidForVersion(moduleDescriptor, customTypeshedPath, pythonVersion, pythonPlatform, importLogger)) {
@@ -1476,17 +1365,16 @@ class ImportResolver {
1476
1365
  return subdirectory;
1477
1366
  }
1478
1367
  _getThirdPartyTypeshedPath(customTypeshedPath, importLogger) {
1479
- return this._getTypeshedSubdirectory(/* isStdLib */ false, customTypeshedPath, importLogger);
1368
+ return this._getTypeshedInfoProvider().getTypeshedSubdirectory(
1369
+ /* isStdLib */ false, customTypeshedPath, importLogger);
1480
1370
  }
1481
1371
  _isStdlibTypeshedStubValidForVersion(moduleDescriptor, customTypeshedPath, pythonVersion, pythonPlatform, importLogger) {
1482
- if (!this._cachedTypeshedStdLibModuleVersionInfo) {
1483
- this._cachedTypeshedStdLibModuleVersionInfo = this._readTypeshedStdLibVersions(customTypeshedPath, importLogger);
1484
- }
1372
+ const versions = this._getTypeshedInfoProvider().getStdLibModuleVersionInfo(customTypeshedPath, importLogger);
1485
1373
  // Loop through the name parts to make sure the module and submodules
1486
1374
  // referenced in the import statement are valid for this version of Python.
1487
1375
  for (let namePartCount = 1; namePartCount <= moduleDescriptor.nameParts.length; namePartCount++) {
1488
1376
  const namePartsToConsider = moduleDescriptor.nameParts.slice(0, namePartCount);
1489
- const versionInfo = this._cachedTypeshedStdLibModuleVersionInfo.get(namePartsToConsider.join('.'));
1377
+ const versionInfo = versions.get(namePartsToConsider.join('.'));
1490
1378
  if (versionInfo) {
1491
1379
  if (pythonVersion_1.PythonVersion.isLessThan(pythonVersion, versionInfo.min)) {
1492
1380
  return false;
@@ -1511,159 +1399,23 @@ class ImportResolver {
1511
1399
  }
1512
1400
  return true;
1513
1401
  }
1514
- _readTypeshedStdLibVersions(customTypeshedPath, importLogger) {
1515
- const versionRangeMap = new Map();
1516
- // Read the VERSIONS file from typeshed.
1517
- const typeshedStdLibPath = this._getTypeshedSubdirectory(/* isStdLib */ true, customTypeshedPath, importLogger);
1518
- if (typeshedStdLibPath) {
1519
- const versionsFilePath = typeshedStdLibPath.combinePaths('VERSIONS');
1520
- try {
1521
- const fileStats = this.fileSystem.statSync(versionsFilePath);
1522
- if (fileStats.size > 0 && fileStats.size < 256 * 1024) {
1523
- const fileContents = this.fileSystem.readFileSync(versionsFilePath, 'utf8');
1524
- fileContents.split(/\r?\n/).forEach((line) => {
1525
- const commentSplit = line.split('#');
1526
- // Platform-specific information can be specified after a semicolon.
1527
- const semicolonSplit = commentSplit[0].split(';').map((s) => s.trim());
1528
- // Version information is found after a colon.
1529
- const colonSplit = semicolonSplit[0].split(':');
1530
- if (colonSplit.length !== 2) {
1531
- return;
1532
- }
1533
- const versionSplit = colonSplit[1].split('-');
1534
- if (versionSplit.length > 2) {
1535
- return;
1536
- }
1537
- const moduleName = colonSplit[0].trim();
1538
- if (!moduleName) {
1539
- return;
1540
- }
1541
- let minVersionString = versionSplit[0].trim();
1542
- if (minVersionString.endsWith('+')) {
1543
- // If the version ends in "+", strip it off.
1544
- minVersionString = minVersionString.substr(0, minVersionString.length - 1);
1545
- }
1546
- let minVersion = pythonVersion_1.PythonVersion.fromString(minVersionString);
1547
- if (!minVersion) {
1548
- minVersion = pythonVersion_1.pythonVersion3_0;
1549
- }
1550
- let maxVersion;
1551
- if (versionSplit.length > 1) {
1552
- maxVersion = pythonVersion_1.PythonVersion.fromString(versionSplit[1].trim());
1553
- }
1554
- // A semicolon can be followed by a semicolon-delimited list of other
1555
- // exclusions. The "platform" exclusion is a comma delimited list platforms
1556
- // that are supported or not supported.
1557
- let supportedPlatforms;
1558
- let unsupportedPlatforms;
1559
- const platformsHeader = 'platforms=';
1560
- let platformExclusions = semicolonSplit.slice(1).find((s) => s.startsWith(platformsHeader));
1561
- if (platformExclusions) {
1562
- platformExclusions = platformExclusions.trim().substring(platformsHeader.length);
1563
- const commaSplit = platformExclusions.split(',');
1564
- for (let platform of commaSplit) {
1565
- platform = platform.trim();
1566
- let isUnsupported = false;
1567
- // Remove the '!' from the start if it's an exclusion.
1568
- if (platform.startsWith('!')) {
1569
- isUnsupported = true;
1570
- platform = platform.substring(1);
1571
- }
1572
- if (isUnsupported) {
1573
- unsupportedPlatforms = unsupportedPlatforms ?? [];
1574
- unsupportedPlatforms.push(platform);
1575
- }
1576
- else {
1577
- supportedPlatforms = supportedPlatforms ?? [];
1578
- supportedPlatforms.push(platform);
1579
- }
1580
- }
1581
- }
1582
- versionRangeMap.set(moduleName, {
1583
- min: minVersion,
1584
- max: maxVersion,
1585
- supportedPlatforms,
1586
- unsupportedPlatforms,
1587
- });
1588
- });
1589
- }
1590
- else {
1591
- importLogger?.log(`Typeshed stdlib VERSIONS file is unexpectedly large`);
1592
- }
1593
- }
1594
- catch (e) {
1595
- importLogger?.log(`Could not read typeshed stdlib VERSIONS file: '${JSON.stringify(e)}'`);
1596
- }
1597
- }
1598
- return versionRangeMap;
1599
- }
1600
1402
  _getThirdPartyTypeshedPackagePaths(moduleDescriptor, importLogger, includeMatchOnly = true) {
1601
- const typeshedPath = this._getThirdPartyTypeshedPath(this._configOptions.typeshedPath, importLogger);
1602
- if (!this._cachedTypeshedThirdPartyPackagePaths) {
1603
- this._buildTypeshedThirdPartyPackageMap(typeshedPath);
1604
- }
1403
+ const [packagePaths] = this._getTypeshedInfoProvider().getThirdPartyPackageMap(this._configOptions.typeshedPath, importLogger);
1605
1404
  const firstNamePart = moduleDescriptor.nameParts.length > 0 ? moduleDescriptor.nameParts[0] : '';
1606
1405
  if (includeMatchOnly) {
1607
- return this._cachedTypeshedThirdPartyPackagePaths.get(firstNamePart);
1406
+ return packagePaths.get(firstNamePart);
1608
1407
  }
1609
1408
  if (firstNamePart) {
1610
- return (0, collectionUtils_1.flatten)((0, collectionUtils_1.getMapValues)(this._cachedTypeshedThirdPartyPackagePaths, (k) => k.startsWith(firstNamePart)));
1409
+ return (0, collectionUtils_1.flatten)((0, collectionUtils_1.getMapValues)(packagePaths, (k) => k.startsWith(firstNamePart)));
1611
1410
  }
1612
1411
  return [];
1613
1412
  }
1614
1413
  _getThirdPartyTypeshedPackageRoots(importLogger) {
1615
- const typeshedPath = this._getThirdPartyTypeshedPath(this._configOptions.typeshedPath, importLogger);
1616
- if (!this._cachedTypeshedThirdPartyPackagePaths) {
1617
- this._buildTypeshedThirdPartyPackageMap(typeshedPath);
1618
- }
1619
- return this._cachedTypeshedThirdPartyPackageRoots;
1620
- }
1621
- _getTypeshedRoot(customTypeshedPath, importLogger) {
1622
- if (this._cachedTypeshedRoot === undefined) {
1623
- let typeshedPath = undefined;
1624
- // Did the user specify a typeshed path? If not, we'll look in the
1625
- // python search paths, then in the typeshed-fallback directory.
1626
- if (customTypeshedPath) {
1627
- if (this.dirExistsCached(customTypeshedPath)) {
1628
- typeshedPath = customTypeshedPath;
1629
- }
1630
- }
1631
- // If typeshed directory wasn't found in other locations, use the fallback.
1632
- if (!typeshedPath) {
1633
- typeshedPath = PythonPathUtils.getTypeShedFallbackPath(this.fileSystem) ?? uri_1.Uri.empty();
1634
- }
1635
- this._cachedTypeshedRoot = typeshedPath;
1636
- }
1637
- return this._cachedTypeshedRoot.isEmpty() ? undefined : this._cachedTypeshedRoot;
1414
+ const [, packageRoots] = this._getTypeshedInfoProvider().getThirdPartyPackageMap(this._configOptions.typeshedPath, importLogger);
1415
+ return packageRoots;
1638
1416
  }
1639
- _getTypeshedSubdirectory(isStdLib, customTypeshedPath, importLogger) {
1640
- // See if we have it cached.
1641
- if (isStdLib) {
1642
- if (this._cachedTypeshedStdLibPath !== undefined) {
1643
- return this._cachedTypeshedStdLibPath;
1644
- }
1645
- }
1646
- else {
1647
- if (this._cachedTypeshedThirdPartyPath !== undefined) {
1648
- return this._cachedTypeshedThirdPartyPath;
1649
- }
1650
- }
1651
- let typeshedPath = this._getTypeshedRoot(customTypeshedPath, importLogger);
1652
- if (typeshedPath === undefined) {
1653
- return undefined;
1654
- }
1655
- typeshedPath = PythonPathUtils.getTypeshedSubdirectory(typeshedPath, isStdLib);
1656
- if (!this.dirExistsCached(typeshedPath)) {
1657
- return undefined;
1658
- }
1659
- // Cache the results.
1660
- if (isStdLib) {
1661
- this._cachedTypeshedStdLibPath = typeshedPath;
1662
- }
1663
- else {
1664
- this._cachedTypeshedThirdPartyPath = typeshedPath;
1665
- }
1666
- return typeshedPath;
1417
+ _getTypeshedInfoProvider() {
1418
+ return this._typeshedInfoProvider;
1667
1419
  }
1668
1420
  _resolveRelativeImport(sourceFileUri, execEnv, moduleDescriptor, importName, importLogger) {
1669
1421
  importLogger?.log('Attempting to resolve relative import');
@@ -1713,32 +1465,6 @@ class ImportResolver {
1713
1465
  // Now try to match the module parts from the current directory location.
1714
1466
  this._getCompletionSuggestionsAbsolute(sourceFileUri, execEnv, directory, moduleDescriptor, suggestions);
1715
1467
  }
1716
- _getFilesInDirectory(dirPath) {
1717
- const cachedValue = this._cachedFilesForPath.get(dirPath.key);
1718
- if (cachedValue) {
1719
- return cachedValue;
1720
- }
1721
- let newCacheValue = [];
1722
- try {
1723
- const entriesInDir = this.readdirEntriesCached(dirPath);
1724
- const filesInDir = [];
1725
- // Add any files or symbolic links that point to files.
1726
- entriesInDir.entries.forEach((f) => {
1727
- if (f.isFile()) {
1728
- filesInDir.push(f);
1729
- }
1730
- else if (f.isSymbolicLink() && (0, uriUtils_1.tryStat)(this.fileSystem, dirPath.combinePaths(f.name))?.isFile()) {
1731
- filesInDir.push(f);
1732
- }
1733
- });
1734
- newCacheValue = filesInDir.map((f) => dirPath.combinePaths(f.name));
1735
- }
1736
- catch {
1737
- newCacheValue = [];
1738
- }
1739
- this._cachedFilesForPath.set(dirPath.key, newCacheValue);
1740
- return newCacheValue;
1741
- }
1742
1468
  _getCompletionSuggestionsAbsolute(sourceFileUri, execEnv, rootPath, moduleDescriptor, suggestions, strictOnly = true) {
1743
1469
  // Starting at the specified path, walk the file system to find the
1744
1470
  // specified module.
@@ -1774,7 +1500,7 @@ class ImportResolver {
1774
1500
  }
1775
1501
  _addFilteredSuggestionsAbsolute(sourceFileUri, execEnv, currentPath, filter, suggestions, leadingDots, parentNameParts, strictOnly) {
1776
1502
  // Enumerate all of the files and directories in the path, expanding links.
1777
- const entries = (0, uriUtils_1.getFileSystemEntriesFromDirEntries)(this.readdirEntriesCached(currentPath).entries.values(), this.fileSystem, currentPath);
1503
+ const entries = (0, uriUtils_1.getFileSystemEntriesFromDirEntries)(this._fileSystemCache.readdirEntriesSync(currentPath).values(), this.fileSystem, currentPath);
1778
1504
  entries.files.forEach((file) => {
1779
1505
  // Strip multi-dot extensions to handle file names like "foo.cpython-32m.so". We want
1780
1506
  // to detect the ".so" but strip off the entire ".cpython-32m.so" extension.
@@ -1868,7 +1594,7 @@ class ImportResolver {
1868
1594
  _findAndResolveNativeModule(fileDirectory, dirPath, execEnv, importName, moduleDescriptor, importLogger, resolvedPaths) {
1869
1595
  let isNativeLib = false;
1870
1596
  if (!execEnv.skipNativeLibraries && this.dirExistsCached(fileDirectory)) {
1871
- const filesInDir = this._getFilesInDirectory(fileDirectory);
1597
+ const filesInDir = this._fileSystemCache.getFilesInDirectory(fileDirectory);
1872
1598
  const dirName = dirPath.fileName;
1873
1599
  const nativeLibPath = filesInDir.find((f) => this._isNativeModuleFileName(dirName, f));
1874
1600
  if (nativeLibPath) {