@zzzen/pyright-internal 1.2.0-dev.20260621 → 1.2.0-dev.20260628

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 (113) hide show
  1. package/dist/analyzer/codeFlowEngine.js +6 -0
  2. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  3. package/dist/analyzer/docStringUtils.d.ts +1 -0
  4. package/dist/analyzer/docStringUtils.js +78 -0
  5. package/dist/analyzer/docStringUtils.js.map +1 -1
  6. package/dist/analyzer/importResolver.js +69 -4
  7. package/dist/analyzer/importResolver.js.map +1 -1
  8. package/dist/analyzer/importStatementUtils.js +19 -1
  9. package/dist/analyzer/importStatementUtils.js.map +1 -1
  10. package/dist/analyzer/parseTreeUtils.js +8 -0
  11. package/dist/analyzer/parseTreeUtils.js.map +1 -1
  12. package/dist/analyzer/patternMatching.js +44 -0
  13. package/dist/analyzer/patternMatching.js.map +1 -1
  14. package/dist/analyzer/program.js +6 -1
  15. package/dist/analyzer/program.js.map +1 -1
  16. package/dist/analyzer/pythonPathUtils.js +2 -2
  17. package/dist/analyzer/pythonPathUtils.js.map +1 -1
  18. package/dist/analyzer/staticExpressions.js +91 -19
  19. package/dist/analyzer/staticExpressions.js.map +1 -1
  20. package/dist/analyzer/typeEvaluator.js +53 -61
  21. package/dist/analyzer/typeEvaluator.js.map +1 -1
  22. package/dist/analyzer/typeEvaluatorTypes.d.ts +1 -0
  23. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  24. package/dist/analyzer/typeGuards.js +52 -4
  25. package/dist/analyzer/typeGuards.js.map +1 -1
  26. package/dist/common/docStringService.d.ts +2 -0
  27. package/dist/common/docStringService.js +5 -1
  28. package/dist/common/docStringService.js.map +1 -1
  29. package/dist/common/fullAccessHost.d.ts +2 -1
  30. package/dist/common/fullAccessHost.js +43 -9
  31. package/dist/common/fullAccessHost.js.map +1 -1
  32. package/dist/common/host.d.ts +2 -2
  33. package/dist/common/host.js +1 -1
  34. package/dist/common/host.js.map +1 -1
  35. package/dist/common/uri/fileUri.d.ts +1 -0
  36. package/dist/common/uri/fileUri.js +20 -0
  37. package/dist/common/uri/fileUri.js.map +1 -1
  38. package/dist/common/uri/memoization.js +5 -1
  39. package/dist/common/uri/memoization.js.map +1 -1
  40. package/dist/common/uri/uriUtils.d.ts +2 -0
  41. package/dist/common/uri/uriUtils.js +22 -0
  42. package/dist/common/uri/uriUtils.js.map +1 -1
  43. package/dist/languageServerBase.js +6 -1
  44. package/dist/languageServerBase.js.map +1 -1
  45. package/dist/languageService/completionProvider.d.ts +6 -0
  46. package/dist/languageService/completionProvider.js +194 -46
  47. package/dist/languageService/completionProvider.js.map +1 -1
  48. package/dist/languageService/completionProviderUtils.d.ts +2 -0
  49. package/dist/languageService/completionProviderUtils.js.map +1 -1
  50. package/dist/languageService/documentSymbolCollector.d.ts +15 -1
  51. package/dist/languageService/documentSymbolCollector.js +64 -41
  52. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  53. package/dist/languageService/hoverProvider.js +22 -0
  54. package/dist/languageService/hoverProvider.js.map +1 -1
  55. package/dist/languageService/importStatementCandidates.d.ts +16 -0
  56. package/dist/languageService/importStatementCandidates.js +100 -0
  57. package/dist/languageService/importStatementCandidates.js.map +1 -0
  58. package/dist/languageService/referencesProvider.d.ts +16 -9
  59. package/dist/languageService/referencesProvider.js +188 -32
  60. package/dist/languageService/referencesProvider.js.map +1 -1
  61. package/dist/languageService/renameProvider.d.ts +7 -2
  62. package/dist/languageService/renameProvider.js +45 -17
  63. package/dist/languageService/renameProvider.js.map +1 -1
  64. package/dist/localization/localize.d.ts +6 -0
  65. package/dist/localization/localize.js +4 -0
  66. package/dist/localization/localize.js.map +1 -1
  67. package/dist/localization/package.nls.en-us.json +3 -0
  68. package/dist/parser/parser.js +9 -0
  69. package/dist/parser/parser.js.map +1 -1
  70. package/dist/readonlyAugmentedFileSystem.js +13 -6
  71. package/dist/readonlyAugmentedFileSystem.js.map +1 -1
  72. package/dist/tests/checker.test.js +4 -0
  73. package/dist/tests/checker.test.js.map +1 -1
  74. package/dist/tests/completions.test.js +118 -9
  75. package/dist/tests/completions.test.js.map +1 -1
  76. package/dist/tests/docStringReturnExtraction.test.d.ts +1 -0
  77. package/dist/tests/docStringReturnExtraction.test.js +125 -0
  78. package/dist/tests/docStringReturnExtraction.test.js.map +1 -0
  79. package/dist/tests/fourslash/completions.call.unpackedGenericTypedDict.fourslash.d.ts +1 -0
  80. package/dist/tests/fourslash/completions.call.unpackedGenericTypedDict.fourslash.js +35 -0
  81. package/dist/tests/fourslash/completions.call.unpackedGenericTypedDict.fourslash.js.map +1 -0
  82. package/dist/tests/fourslash/completions.keywords.expressionContext.fourslash.d.ts +1 -0
  83. package/dist/tests/fourslash/completions.keywords.expressionContext.fourslash.js +86 -0
  84. package/dist/tests/fourslash/completions.keywords.expressionContext.fourslash.js.map +1 -0
  85. package/dist/tests/fourslash/diagnostics.missingModuleSource.compiledModule.fourslash.d.ts +1 -0
  86. package/dist/tests/fourslash/diagnostics.missingModuleSource.compiledModule.fourslash.js +122 -0
  87. package/dist/tests/fourslash/diagnostics.missingModuleSource.compiledModule.fourslash.js.map +1 -0
  88. package/dist/tests/harness/testAccessHost.d.ts +1 -1
  89. package/dist/tests/harness/testAccessHost.js +1 -1
  90. package/dist/tests/harness/testAccessHost.js.map +1 -1
  91. package/dist/tests/importResolver.test.js +33 -0
  92. package/dist/tests/importResolver.test.js.map +1 -1
  93. package/dist/tests/importStatementUtils.test.js +92 -0
  94. package/dist/tests/importStatementUtils.test.js.map +1 -1
  95. package/dist/tests/lsp/languageServerTestUtils.d.ts +1 -1
  96. package/dist/tests/lsp/languageServerTestUtils.js +1 -1
  97. package/dist/tests/lsp/languageServerTestUtils.js.map +1 -1
  98. package/dist/tests/parser.test.js +18 -0
  99. package/dist/tests/parser.test.js.map +1 -1
  100. package/dist/tests/pyrightFileSystem.test.js +25 -0
  101. package/dist/tests/pyrightFileSystem.test.js.map +1 -1
  102. package/dist/tests/signatureHelp.test.js +73 -0
  103. package/dist/tests/signatureHelp.test.js.map +1 -1
  104. package/dist/tests/typeEvaluator1.test.js +4 -0
  105. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  106. package/dist/tests/typeEvaluator2.test.js +6 -0
  107. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  108. package/dist/tests/typeEvaluator4.test.js +22 -0
  109. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  110. package/dist/tests/typeEvaluator8.test.js +23 -21
  111. package/dist/tests/typeEvaluator8.test.js.map +1 -1
  112. package/dist/types.d.ts +1 -0
  113. package/package.json +4 -4
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /*
3
+ * docStringReturnExtraction.test.ts
4
+ * Copyright (c) Microsoft Corporation.
5
+ * Licensed under the MIT license.
6
+ *
7
+ * Tests for extractReturnDocumentation, which pulls the return-value description
8
+ * out of a function docstring (reST, Epytext, and Google styles).
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const assert = require("assert");
12
+ const docStringUtils_1 = require("../analyzer/docStringUtils");
13
+ describe('extractReturnDocumentation', () => {
14
+ test('reST :returns: (plural)', () => {
15
+ const doc = `Compute a value.
16
+
17
+ :returns: The computed integer value.`;
18
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
19
+ });
20
+ test('reST :return: (singular)', () => {
21
+ const doc = `Compute a value.
22
+
23
+ :return: The computed integer value.`;
24
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
25
+ });
26
+ test('Epytext @returns: (plural)', () => {
27
+ const doc = `Compute a value.
28
+
29
+ @returns: The computed integer value.`;
30
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
31
+ });
32
+ test('Epytext @return (singular, no colon)', () => {
33
+ const doc = `Compute a value.
34
+
35
+ @return The computed integer value.`;
36
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
37
+ });
38
+ test('Epytext @returns:description (no space after colon)', () => {
39
+ // Mirrors reST: a missing space after the colon must still extract the description.
40
+ const doc = `Compute a value.
41
+
42
+ @returns:The computed integer value.`;
43
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
44
+ });
45
+ test('Google Returns: single line', () => {
46
+ const doc = `Compute a value.
47
+
48
+ Returns:
49
+ The computed integer value.`;
50
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
51
+ });
52
+ test('Google Returns: multi-line stops at next section (dedent)', () => {
53
+ const doc = `Compute a value.
54
+
55
+ Returns:
56
+ The computed integer value.
57
+ Spanning two lines.
58
+ Raises:
59
+ ValueError: if the value is bad.`;
60
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.\nSpanning two lines.');
61
+ });
62
+ test('Google Returns: multi-line stops at blank line after collecting', () => {
63
+ const doc = `Compute a value.
64
+
65
+ Returns:
66
+ The computed integer value.
67
+ Spanning two lines.
68
+
69
+ Some trailing prose that is not part of the return section.`;
70
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.\nSpanning two lines.');
71
+ });
72
+ test('Google Returns: type: description form', () => {
73
+ const doc = `Compute a value.
74
+
75
+ Returns:
76
+ int: The computed integer value.`;
77
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'int: The computed integer value.');
78
+ });
79
+ test('Google Return: (singular header)', () => {
80
+ const doc = `Compute a value.
81
+
82
+ Return:
83
+ The computed integer value.`;
84
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
85
+ });
86
+ test('reST empty :returns: yields undefined', () => {
87
+ const doc = `Compute a value.
88
+
89
+ :returns:`;
90
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), undefined);
91
+ });
92
+ test('Google Returns: with no indented body yields undefined', () => {
93
+ const doc = `Compute a value.
94
+
95
+ Returns:
96
+ Raises:
97
+ ValueError: if the value is bad.`;
98
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), undefined);
99
+ });
100
+ test('no return section yields undefined', () => {
101
+ const doc = `Compute a value.
102
+
103
+ Args:
104
+ x: the input.`;
105
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), undefined);
106
+ });
107
+ test('Google Returns: header on the first physical line', () => {
108
+ // The "Returns:" header sits on the docstring's first physical line, so its indentation
109
+ // must still be recovered correctly even though the first line is special-cased during
110
+ // docstring cleanup.
111
+ const doc = `Returns:
112
+ The computed integer value.`;
113
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.');
114
+ });
115
+ test('Google Returns: header on the first physical line, multi-line body', () => {
116
+ const doc = `Returns:
117
+ The computed integer value.
118
+ Spanning two lines.`;
119
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(doc), 'The computed integer value.\nSpanning two lines.');
120
+ });
121
+ test('empty docstring yields undefined', () => {
122
+ assert.strictEqual((0, docStringUtils_1.extractReturnDocumentation)(''), undefined);
123
+ });
124
+ });
125
+ //# sourceMappingURL=docStringReturnExtraction.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docStringReturnExtraction.test.js","sourceRoot":"","sources":["../../../../../src/tests/docStringReturnExtraction.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /// <reference path="typings/fourslash.d.ts" />
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ // Unpacked parameterized TypedDict as a variadic keyword parameter.
5
+ // expandTypedKwargs() (consumed by both signature help and completion literal-value suggestions)
6
+ // must substitute the TypedDict type argument. Before the fix, the `t` entry kept the unspecialized
7
+ // TypeVar `T@TD`, so no literal-value completions were offered; after the fix the entry is
8
+ // `Literal['a', 'b']`, so the literal values are offered at the call site.
9
+ // @filename: test.py
10
+ //// from typing import Generic, Literal, TypedDict, TypeVar, Unpack
11
+ ////
12
+ //// T = TypeVar('T')
13
+ ////
14
+ //// class TD(TypedDict, Generic[T]):
15
+ //// t: T
16
+ ////
17
+ //// def func(**kwargs: Unpack[TD[Literal['a', 'b']]]) -> None: ...
18
+ ////
19
+ //// func(t=[|/*marker*/|])
20
+ // @ts-ignore
21
+ await helper.verifyCompletion('included', 'markdown', {
22
+ marker: {
23
+ completions: [
24
+ {
25
+ label: "'a'",
26
+ kind: Consts.CompletionItemKind.Constant,
27
+ },
28
+ {
29
+ label: "'b'",
30
+ kind: Consts.CompletionItemKind.Constant,
31
+ },
32
+ ],
33
+ },
34
+ });
35
+ //# sourceMappingURL=completions.call.unpackedGenericTypedDict.fourslash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completions.call.unpackedGenericTypedDict.fourslash.js","sourceRoot":"","sources":["../../../../../../src/tests/fourslash/completions.call.unpackedGenericTypedDict.fourslash.ts"],"names":[],"mappings":";AAAA,+CAA+C;;AAE/C,oEAAoE;AACpE,iGAAiG;AACjG,oGAAoG;AACpG,2FAA2F;AAC3F,2EAA2E;AAE3E,qBAAqB;AACrB,oEAAoE;AACpE,IAAI;AACJ,qBAAqB;AACrB,IAAI;AACJ,qCAAqC;AACrC,aAAa;AACb,IAAI;AACJ,mEAAmE;AACnE,IAAI;AACJ,2BAA2B;AAE3B,aAAa;AACb,MAAM,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE;IAClD,MAAM,EAAE;QACJ,WAAW,EAAE;YACT;gBACI,KAAK,EAAE,KAAK;gBACZ,IAAI,EAAE,MAAM,CAAC,kBAAkB,CAAC,QAAQ;aAC3C;YACD;gBACI,KAAK,EAAE,KAAK;gBACZ,IAAI,EAAE,MAAM,CAAC,kBAAkB,CAAC,QAAQ;aAC3C;SACJ;KACJ;CACJ,CAAC,CAAC"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /// <reference path="typings/fourslash.d.ts" />
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ // Statement-only keywords (e.g. `raise`, `return`) should be suppressed in
5
+ // slots that can only contain an expression, while still being offered at the
6
+ // start of a statement. Expression-valid keywords (e.g. `lambda`) must keep
7
+ // appearing in expression slots.
8
+ // @filename: stmtStart.py
9
+ //// def func():
10
+ //// re[|/*stmtStart*/|]
11
+ // @filename: forIterable.py
12
+ //// for item in ra[|/*forIterable*/|]
13
+ // @filename: forIterableExprKeyword.py
14
+ //// for item in la[|/*forIterableExprKeyword*/|]
15
+ // @filename: assignRhs.py
16
+ //// x = re[|/*assignRhs*/|]
17
+ // @filename: assignRhsExprKeyword.py
18
+ //// x = la[|/*assignRhsExprKeyword*/|]
19
+ // @filename: walrusRhs.py
20
+ //// if (n := re[|/*walrusRhs*/|]):
21
+ //// pass
22
+ // @filename: comprehensionIterable.py
23
+ //// z = [i for i in re[|/*comprehensionIterable*/|]]
24
+ // @filename: callArg.py
25
+ //// print(re[|/*callArg*/|])
26
+ // @filename: subscript.py
27
+ //// data = [1, 2]
28
+ //// w = data[re[|/*subscript*/|]]
29
+ // @filename: returnValue.py
30
+ //// def func():
31
+ //// return ra[|/*returnValue*/|]
32
+ // @filename: whileCondition.py
33
+ //// while re[|/*whileCondition*/|]:
34
+ //// pass
35
+ // @filename: ifCondition.py
36
+ //// if re[|/*ifCondition*/|]:
37
+ //// pass
38
+ {
39
+ helper.openFiles(helper.getMarkers().map((m) => m.fileName));
40
+ // Statement-only keywords are still offered at statement start, and
41
+ // expression-valid keywords are still offered in expression slots.
42
+ // @ts-ignore
43
+ await helper.verifyCompletion('included', 'markdown', {
44
+ stmtStart: {
45
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
46
+ },
47
+ forIterableExprKeyword: {
48
+ completions: [{ label: 'lambda', kind: Consts.CompletionItemKind.Keyword }],
49
+ },
50
+ assignRhsExprKeyword: {
51
+ completions: [{ label: 'lambda', kind: Consts.CompletionItemKind.Keyword }],
52
+ },
53
+ });
54
+ // Statement-only keywords are suppressed in expression-only slots.
55
+ // @ts-ignore
56
+ await helper.verifyCompletion('excluded', 'markdown', {
57
+ forIterable: {
58
+ completions: [{ label: 'raise', kind: Consts.CompletionItemKind.Keyword }],
59
+ },
60
+ assignRhs: {
61
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
62
+ },
63
+ walrusRhs: {
64
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
65
+ },
66
+ comprehensionIterable: {
67
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
68
+ },
69
+ callArg: {
70
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
71
+ },
72
+ subscript: {
73
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
74
+ },
75
+ returnValue: {
76
+ completions: [{ label: 'raise', kind: Consts.CompletionItemKind.Keyword }],
77
+ },
78
+ whileCondition: {
79
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
80
+ },
81
+ ifCondition: {
82
+ completions: [{ label: 'return', kind: Consts.CompletionItemKind.Keyword }],
83
+ },
84
+ });
85
+ }
86
+ //# sourceMappingURL=completions.keywords.expressionContext.fourslash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completions.keywords.expressionContext.fourslash.js","sourceRoot":"","sources":["../../../../../../src/tests/fourslash/completions.keywords.expressionContext.fourslash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ /// <reference path="typings/fourslash.d.ts" />
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ // A package shipped as a "sourceless distribution": a compiled `.pyc` module sits
5
+ // where the `.py` source would be (directly beside its `.pyi` stub, NOT under
6
+ // `__pycache__`), with no `.py` file. Python imports such a `.pyc` directly, so the
7
+ // module exists at runtime even though it has no Python source. The
8
+ // `reportMissingModuleSource` warning ("could not be resolved from source") is
9
+ // therefore misleading and should NOT fire.
10
+ //
11
+ // This mirrors the native-extension case (a `.pyd`/`.so` backing a `.pyi` stub):
12
+ // a compiled implementation with no Python source is still a real runtime module.
13
+ // --- Top-level compiled module: `mod.pyc` beside `mod.pyi`, no `mod.py`. ---
14
+ // @filename: compiledmod.pyi
15
+ // @library: true
16
+ //// VALUE: int
17
+ // @filename: compiledmod.pyc
18
+ // @library: true
19
+ //// # Compiled bytecode placeholder. Only the file's presence matters to import
20
+ //// # resolution; the text content is never parsed.
21
+ // --- Compiled package + compiled submodule: `__init__.pyc`/`sub.pyc` beside the
22
+ // stubs, no `.py` anywhere. Exercises the package (`__init__`) layout and the
23
+ // dotted/submodule resolution paths.
24
+ //
25
+ // Note: `import compiledpkg` itself does NOT exercise the new `.pyc` branch --
26
+ // the non-stub pass resolves the package via the pre-existing namespace-package
27
+ // directory fallback (`foundDirectory` -> `isImportFound`), and `__init__.pyc`
28
+ // is never probed. The genuinely new-branch cases are the top-level
29
+ // `compiledmod` and the submodule `compiledpkg.sub` (dotted + `from ... import`). ---
30
+ // @filename: compiledpkg/__init__.pyi
31
+ // @library: true
32
+ //// PKGVALUE: int
33
+ // @filename: compiledpkg/__init__.pyc
34
+ // @library: true
35
+ //// # Compiled bytecode placeholder for the package __init__.
36
+ // @filename: compiledpkg/sub.pyi
37
+ // @library: true
38
+ //// SUBVALUE: int
39
+ // @filename: compiledpkg/sub.pyc
40
+ // @library: true
41
+ //// # Compiled bytecode placeholder for the submodule.
42
+ // --- Compiled module WITHOUT a stub (`.pyc` only, no `.pyi`/`.py`). The `.pyc`
43
+ // branch is gated on `!allowPyi`, so the stub (primary) resolution must still
44
+ // fail here and `reportMissingImports` must fire. Regression guard. ---
45
+ // @filename: pyconlymod.pyc
46
+ // @library: true
47
+ //// # Compiled bytecode placeholder; there is no stub for this module.
48
+ // --- `isLastPart` gate guard: a `.pyc` at a NON-leaf (mid-path) position must NOT
49
+ // partially resolve a dotted import. `midpathmod.pyc` exists but there is no
50
+ // `midpathmod/` package directory, so `import midpathmod.sub` must still fail
51
+ // with reportMissingImports. The new branch is gated on `isLastPart`, so a
52
+ // mid-path `.pyc` can never satisfy a non-leaf component. ---
53
+ // @filename: midpathmod.pyc
54
+ // @library: true
55
+ //// # Compiled bytecode placeholder at a mid-path position; no package directory.
56
+ // --- Stub-only controls (no `.pyc`, no `.py`): `reportMissingModuleSource` MUST
57
+ // still fire for both a top-level module and a submodule. ---
58
+ // @filename: stubonlymod.pyi
59
+ // @library: true
60
+ //// HELPER: int
61
+ // @filename: stubonlypkg/__init__.pyi
62
+ // @library: true
63
+ //// # Stub-only package (control).
64
+ // @filename: stubonlypkg/missing.pyi
65
+ // @library: true
66
+ //// def helper() -> int: ...
67
+ // @filename: test.py
68
+ //// # Compiled `.pyc` sits beside the `.pyi` stub (no `.py`) -> NO warning.
69
+ //// from compiledmod import VALUE
70
+ //// import compiledmod
71
+ ////
72
+ //// # Compiled package (`__init__.pyc` beside `__init__.pyi`, no `__init__.py`) -> NO warning.
73
+ //// import compiledpkg
74
+ //// from compiledpkg import PKGVALUE
75
+ ////
76
+ //// # Compiled submodule, dotted (visitModuleName path) -> NO warning.
77
+ //// import compiledpkg.sub
78
+ //// from compiledpkg.sub import SUBVALUE
79
+ ////
80
+ //// # Compiled submodule imported as a name (visitImportFromAs submoduleFallback) -> NO warning.
81
+ //// from compiledpkg import sub
82
+ ////
83
+ //// # `.pyc` only, no stub: primary (stub) resolution must still fail -> reportMissingImports.
84
+ //// import [|/*markerMissing*/pyconlymod|]
85
+ ////
86
+ //// # Mid-path `.pyc` (no package directory): dotted import must still fail (isLastPart gate).
87
+ //// import [|/*markerMidpath*/midpathmod.sub|]
88
+ ////
89
+ //// # Stub-only module (no `.pyc`, no `.py`) -> warning MUST still fire (control).
90
+ //// from [|/*marker1*/stubonlymod|] import HELPER
91
+ //// import [|/*marker2*/stubonlymod|]
92
+ ////
93
+ //// # Stub-only submodule (no `.pyc`, no `.py`) -> warning MUST still fire (control).
94
+ //// from [|/*marker3*/stubonlypkg.missing|] import helper
95
+ //// from stubonlypkg import [|/*marker4*/missing|]
96
+ helper.verifyDiagnostics({
97
+ markerMissing: {
98
+ category: 'error',
99
+ message: 'Import "pyconlymod" could not be resolved',
100
+ },
101
+ markerMidpath: {
102
+ category: 'error',
103
+ message: 'Import "midpathmod.sub" could not be resolved',
104
+ },
105
+ marker1: {
106
+ category: 'warning',
107
+ message: 'Import "stubonlymod" could not be resolved from source',
108
+ },
109
+ marker2: {
110
+ category: 'warning',
111
+ message: 'Import "stubonlymod" could not be resolved from source',
112
+ },
113
+ marker3: {
114
+ category: 'warning',
115
+ message: 'Import "stubonlypkg.missing" could not be resolved from source',
116
+ },
117
+ marker4: {
118
+ category: 'warning',
119
+ message: 'Import "stubonlypkg.missing" could not be resolved from source',
120
+ },
121
+ });
122
+ //# sourceMappingURL=diagnostics.missingModuleSource.compiledModule.fourslash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.missingModuleSource.compiledModule.fourslash.js","sourceRoot":"","sources":["../../../../../../src/tests/fourslash/diagnostics.missingModuleSource.compiledModule.fourslash.ts"],"names":[],"mappings":";AAAA,+CAA+C;;AAE/C,kFAAkF;AAClF,8EAA8E;AAC9E,oFAAoF;AACpF,oEAAoE;AACpE,+EAA+E;AAC/E,4CAA4C;AAC5C,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAElF,8EAA8E;AAC9E,6BAA6B;AAC7B,iBAAiB;AACjB,eAAe;AAEf,6BAA6B;AAC7B,iBAAiB;AACjB,gFAAgF;AAChF,oDAAoD;AAEpD,iFAAiF;AACjF,kFAAkF;AAClF,yCAAyC;AACzC,EAAE;AACF,mFAAmF;AACnF,oFAAoF;AACpF,mFAAmF;AACnF,wEAAwE;AACxE,0FAA0F;AAC1F,sCAAsC;AACtC,iBAAiB;AACjB,kBAAkB;AAElB,sCAAsC;AACtC,iBAAiB;AACjB,8DAA8D;AAE9D,iCAAiC;AACjC,iBAAiB;AACjB,kBAAkB;AAElB,iCAAiC;AACjC,iBAAiB;AACjB,uDAAuD;AAEvD,gFAAgF;AAChF,kFAAkF;AAClF,4EAA4E;AAC5E,4BAA4B;AAC5B,iBAAiB;AACjB,uEAAuE;AAEvE,mFAAmF;AACnF,iFAAiF;AACjF,kFAAkF;AAClF,+EAA+E;AAC/E,kEAAkE;AAClE,4BAA4B;AAC5B,iBAAiB;AACjB,kFAAkF;AAElF,iFAAiF;AACjF,kEAAkE;AAClE,6BAA6B;AAC7B,iBAAiB;AACjB,gBAAgB;AAEhB,sCAAsC;AACtC,iBAAiB;AACjB,mCAAmC;AAEnC,qCAAqC;AACrC,iBAAiB;AACjB,6BAA6B;AAE7B,qBAAqB;AACrB,4EAA4E;AAC5E,kCAAkC;AAClC,uBAAuB;AACvB,IAAI;AACJ,+FAA+F;AAC/F,uBAAuB;AACvB,qCAAqC;AACrC,IAAI;AACJ,uEAAuE;AACvE,2BAA2B;AAC3B,yCAAyC;AACzC,IAAI;AACJ,iGAAiG;AACjG,gCAAgC;AAChC,IAAI;AACJ,+FAA+F;AAC/F,2CAA2C;AAC3C,IAAI;AACJ,+FAA+F;AAC/F,+CAA+C;AAC/C,IAAI;AACJ,mFAAmF;AACnF,kDAAkD;AAClD,sCAAsC;AACtC,IAAI;AACJ,sFAAsF;AACtF,0DAA0D;AAC1D,mDAAmD;AAEnD,MAAM,CAAC,iBAAiB,CAAC;IACrB,aAAa,EAAE;QACX,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,2CAA2C;KACvD;IACD,aAAa,EAAE;QACX,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,+CAA+C;KAC3D;IACD,OAAO,EAAE;QACL,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,wDAAwD;KACpE;IACD,OAAO,EAAE;QACL,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,wDAAwD;KACpE;IACD,OAAO,EAAE;QACL,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,gEAAgE;KAC5E;IACD,OAAO,EAAE;QACL,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,gEAAgE;KAC5E;CACJ,CAAC,CAAC"}
@@ -8,5 +8,5 @@ export declare class TestAccessHost extends NoAccessHost {
8
8
  private _searchPaths;
9
9
  private _fs?;
10
10
  constructor(_modulePath?: Uri, _searchPaths?: Uri[], _fs?: FileSystem | undefined);
11
- getPythonSearchPaths(pythonPath?: Uri, importLogger?: ImportLogger): PythonPathResult;
11
+ getPythonSearchPaths(pythonPath?: Uri, importLogger?: ImportLogger, cwd?: Uri): PythonPathResult;
12
12
  }
@@ -18,7 +18,7 @@ class TestAccessHost extends host_1.NoAccessHost {
18
18
  this._searchPaths = _searchPaths;
19
19
  this._fs = _fs;
20
20
  }
21
- getPythonSearchPaths(pythonPath, importLogger) {
21
+ getPythonSearchPaths(pythonPath, importLogger, cwd) {
22
22
  // Filter out non-directory paths if filesystem is available
23
23
  const filteredPaths = this._fs ? this._searchPaths.filter((p) => (0, uriUtils_1.isDirectory)(this._fs, p)) : this._searchPaths;
24
24
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"testAccessHost.js","sourceRoot":"","sources":["../../../../../../src/tests/harness/testAccessHost.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAKH,4CAAiD;AACjD,8CAA2C;AAC3C,wDAAwD;AAExD,MAAa,cAAe,SAAQ,mBAAY;IAC5C,YAAoB,cAAc,SAAG,CAAC,KAAK,EAAE,EAAU,eAAsB,EAAE,EAAU,GAAgB;QACrG,KAAK,EAAE,CAAC;QADQ,gBAAW,GAAX,WAAW,CAAc;QAAU,iBAAY,GAAZ,YAAY,CAAY;QAAU,QAAG,GAAH,GAAG,CAAa;IAEzG,CAAC;IAEQ,oBAAoB,CAAC,UAAgB,EAAE,YAA2B;QACvE,4DAA4D;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,sBAAW,EAAC,IAAI,CAAC,GAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;QAEhH,OAAO;YACH,KAAK,EAAE,aAAa;YACpB,MAAM,EAAE,IAAI,CAAC,WAAW;SAC3B,CAAC;IACN,CAAC;CACJ;AAdD,wCAcC"}
1
+ {"version":3,"file":"testAccessHost.js","sourceRoot":"","sources":["../../../../../../src/tests/harness/testAccessHost.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAKH,4CAAiD;AACjD,8CAA2C;AAC3C,wDAAwD;AAExD,MAAa,cAAe,SAAQ,mBAAY;IAC5C,YAAoB,cAAc,SAAG,CAAC,KAAK,EAAE,EAAU,eAAsB,EAAE,EAAU,GAAgB;QACrG,KAAK,EAAE,CAAC;QADQ,gBAAW,GAAX,WAAW,CAAc;QAAU,iBAAY,GAAZ,YAAY,CAAY;QAAU,QAAG,GAAH,GAAG,CAAa;IAEzG,CAAC;IAEQ,oBAAoB,CAAC,UAAgB,EAAE,YAA2B,EAAE,GAAS;QAClF,4DAA4D;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,sBAAW,EAAC,IAAI,CAAC,GAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;QAEhH,OAAO;YACH,KAAK,EAAE,aAAa;YACpB,MAAM,EAAE,IAAI,CAAC,WAAW;SAC3B,CAAC;IACN,CAAC;CACJ;AAdD,wCAcC"}
@@ -52,6 +52,39 @@ describe('Import tests with fake venv', () => {
52
52
  (0, assert_1.default)(importResult.isStubFile);
53
53
  assert_1.default.strictEqual(1, importResult.resolvedUris.filter((f) => !f.isEmpty() && f.getFilePath() === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi')).length);
54
54
  });
55
+ test('symlinked partial stub file exists', () => {
56
+ const stubSource = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), 'wheel', 'partialStub.pyi');
57
+ const files = [
58
+ {
59
+ path: stubSource,
60
+ content: 'def test(): ...',
61
+ },
62
+ {
63
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
64
+ content: 'partial\n',
65
+ },
66
+ {
67
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
68
+ content: 'def test(): pass',
69
+ },
70
+ ];
71
+ const testFS = createTestFileSystem(files);
72
+ testFS.symlinkSync(stubSource, (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'partialStub.pyi'));
73
+ const fs = new pyrightFileSystem_1.PyrightFileSystem(testFS);
74
+ const partialStubService = new partialStubService_1.PartialStubService(fs);
75
+ const sp = (0, serviceProviderExtensions_1.createServiceProvider)(testFS, fs, partialStubService);
76
+ const configOptions = new configOptions_1.ConfigOptions(uriUtils_1.UriEx.file('/'));
77
+ const uri = uriUtils_1.UriEx.file(files[files.length - 1].path);
78
+ const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [uriUtils_1.UriEx.file(libraryRoot)]));
79
+ const importResult = importResolver.resolveImport(uri, configOptions.findExecEnvironment(uri), {
80
+ leadingDots: 0,
81
+ nameParts: ['myLib', 'partialStub'],
82
+ importedSymbols: new Set(),
83
+ });
84
+ (0, assert_1.default)(importResult.isImportFound);
85
+ (0, assert_1.default)(importResult.isStubFile);
86
+ assert_1.default.strictEqual(1, importResult.resolvedUris.filter((f) => f.getFilePath() === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi')).length);
87
+ });
55
88
  test('partial stub __init__ exists', () => {
56
89
  const files = [
57
90
  {