@zzzen/pyright-internal 1.2.0-dev.20261011 → 1.2.0-dev.20261101
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.
- package/dist/analyzer/binder.js +28 -9
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/checker.js +8 -3
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/codeFlowEngine.js +76 -30
- package/dist/analyzer/codeFlowEngine.js.map +1 -1
- package/dist/analyzer/dataClasses.js +14 -5
- package/dist/analyzer/dataClasses.js.map +1 -1
- package/dist/analyzer/decorators.d.ts +1 -1
- package/dist/analyzer/decorators.js +22 -2
- package/dist/analyzer/decorators.js.map +1 -1
- package/dist/analyzer/namedTuples.d.ts +2 -1
- package/dist/analyzer/namedTuples.js +63 -35
- package/dist/analyzer/namedTuples.js.map +1 -1
- package/dist/analyzer/operations.js +45 -1
- package/dist/analyzer/operations.js.map +1 -1
- package/dist/analyzer/overloadResultAdmission.js +115 -3
- package/dist/analyzer/overloadResultAdmission.js.map +1 -1
- package/dist/analyzer/overloadResultController.js +36 -10
- package/dist/analyzer/overloadResultController.js.map +1 -1
- package/dist/analyzer/overloadResultSelector.js +32 -12
- package/dist/analyzer/overloadResultSelector.js.map +1 -1
- package/dist/analyzer/parseTreeUtils.d.ts +3 -0
- package/dist/analyzer/parseTreeUtils.js +56 -0
- package/dist/analyzer/parseTreeUtils.js.map +1 -1
- package/dist/analyzer/patternMatching.js +67 -27
- package/dist/analyzer/patternMatching.js.map +1 -1
- package/dist/analyzer/program.d.ts +3 -0
- package/dist/analyzer/program.js +34 -9
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/sentinel.js +7 -1
- package/dist/analyzer/sentinel.js.map +1 -1
- package/dist/analyzer/service.js +6 -2
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/sourceEnumerator.d.ts +3 -1
- package/dist/analyzer/sourceEnumerator.js +30 -11
- package/dist/analyzer/sourceEnumerator.js.map +1 -1
- package/dist/analyzer/sourceFile.js +13 -6
- package/dist/analyzer/sourceFile.js.map +1 -1
- package/dist/analyzer/sourceMapper.d.ts +1 -0
- package/dist/analyzer/sourceMapper.js +10 -4
- package/dist/analyzer/sourceMapper.js.map +1 -1
- package/dist/analyzer/tupleComparison.d.ts +6 -0
- package/dist/analyzer/tupleComparison.js +731 -0
- package/dist/analyzer/tupleComparison.js.map +1 -0
- package/dist/analyzer/tuples.js +52 -10
- package/dist/analyzer/tuples.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +508 -63
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +1 -1
- package/dist/analyzer/typeEvaluatorTypes.js +2 -3
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typeGuards.d.ts +6 -1
- package/dist/analyzer/typeGuards.js +373 -72
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typeStubRenderer.d.ts +6 -1
- package/dist/analyzer/typeStubRenderer.js +19 -12
- package/dist/analyzer/typeStubRenderer.js.map +1 -1
- package/dist/analyzer/typeUtils.js +3 -0
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/typedDicts.d.ts +2 -1
- package/dist/analyzer/typedDicts.js +49 -10
- package/dist/analyzer/typedDicts.js.map +1 -1
- package/dist/analyzer/types.d.ts +14 -0
- package/dist/analyzer/types.js +215 -10
- package/dist/analyzer/types.js.map +1 -1
- package/dist/common/configOptions.d.ts +1 -0
- package/dist/common/configOptions.js +9 -0
- package/dist/common/configOptions.js.map +1 -1
- package/dist/common/processUtils.d.ts +6 -0
- package/dist/common/processUtils.js +56 -1
- package/dist/common/processUtils.js.map +1 -1
- package/dist/common/textEditTracker.js +1 -1
- package/dist/common/textEditTracker.js.map +1 -1
- package/dist/common/windowsProcessTree.d.ts +2 -0
- package/dist/common/windowsProcessTree.js +23 -0
- package/dist/common/windowsProcessTree.js.map +1 -1
- package/dist/common/windowsProcessTree.json +273 -34
- package/dist/languageServerBase.d.ts +3 -0
- package/dist/languageServerBase.js +44 -12
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/callHierarchyProvider.js +6 -6
- package/dist/languageService/callHierarchyProvider.js.map +1 -1
- package/dist/languageService/referencesProvider.js +3 -3
- package/dist/languageService/referencesProvider.js.map +1 -1
- package/dist/languageService/renameProvider.js +1 -1
- package/dist/languageService/renameProvider.js.map +1 -1
- package/dist/languageService/symbolIndexer.js +2 -2
- package/dist/languageService/symbolIndexer.js.map +1 -1
- package/dist/localization/localize.d.ts +2 -0
- package/dist/localization/localize.js +2 -0
- package/dist/localization/localize.js.map +1 -1
- package/dist/localization/package.nls.en-us.json +8 -0
- package/dist/parser/parseTreeTokenReuse.d.ts +34 -0
- package/dist/parser/parseTreeTokenReuse.js +897 -0
- package/dist/parser/parseTreeTokenReuse.js.map +1 -0
- package/dist/parser/tokenizer.d.ts +10 -1
- package/dist/parser/tokenizer.js +184 -130
- package/dist/parser/tokenizer.js.map +1 -1
- package/dist/tests/checker.test.js +58 -0
- package/dist/tests/checker.test.js.map +1 -1
- package/dist/tests/config.test.js +126 -0
- package/dist/tests/config.test.js.map +1 -1
- package/dist/tests/fourSlashParser.test.js +35 -0
- package/dist/tests/fourSlashParser.test.js.map +1 -1
- package/dist/tests/fourslash/hover.typedDict.get.fourslash.js +11 -0
- package/dist/tests/fourslash/hover.typedDict.get.fourslash.js.map +1 -1
- package/dist/tests/harness/fourslash/fourSlashParser.js +14 -4
- package/dist/tests/harness/fourslash/fourSlashParser.js.map +1 -1
- package/dist/tests/languageServer.test.js +15 -0
- package/dist/tests/languageServer.test.js.map +1 -1
- package/dist/tests/lsp/languageServer.js +6 -6
- package/dist/tests/lsp/languageServer.js.map +1 -1
- package/dist/tests/mypyPrimerAnalysis.test.js +133 -0
- package/dist/tests/mypyPrimerAnalysis.test.js.map +1 -1
- package/dist/tests/overloadResultController.test.js +379 -1
- package/dist/tests/overloadResultController.test.js.map +1 -1
- package/dist/tests/signatureHelp.test.js +34 -0
- package/dist/tests/signatureHelp.test.js.map +1 -1
- package/dist/tests/sourceEnumeratorSymlink.test.js +98 -13
- package/dist/tests/sourceEnumeratorSymlink.test.js.map +1 -1
- package/dist/tests/sourceMapperUtils.test.js +143 -0
- package/dist/tests/sourceMapperUtils.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +22 -3
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +54 -1
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +10 -3
- package/dist/tests/typeEvaluator4.test.js.map +1 -1
- package/dist/tests/typeEvaluator5.test.js +1 -1
- package/dist/tests/typeEvaluator6.test.js +55 -0
- package/dist/tests/typeEvaluator6.test.js.map +1 -1
- package/dist/tests/typeEvaluator7.test.js +30 -0
- package/dist/tests/typeEvaluator7.test.js.map +1 -1
- package/dist/tests/typeEvaluator8.test.js +1293 -2
- package/dist/tests/typeEvaluator8.test.js.map +1 -1
- package/dist/tests/types.test.js +55 -0
- package/dist/tests/types.test.js.map +1 -1
- package/dist/typeServer/programWrapper.js +8 -2
- package/dist/typeServer/programWrapper.js.map +1 -1
- package/dist/typeServer/server.d.ts +12 -2
- package/dist/typeServer/server.js +97 -0
- package/dist/typeServer/server.js.map +1 -1
- package/package.json +3 -3
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"{",
|
|
10
10
|
" private const uint QueryAccess = 0x1000 | 0x100000;",
|
|
11
11
|
" private const uint ControlAccess = QueryAccess | 0x0001 | 0x0800;",
|
|
12
|
+
" private const int ProcessIsTerminating = unchecked((int)0xC000010A);",
|
|
12
13
|
" private IntPtr handle;",
|
|
13
14
|
" private bool controlled;",
|
|
14
15
|
" private bool suspended;",
|
|
@@ -51,6 +52,18 @@
|
|
|
51
52
|
" public long CreationTimeUtcTicks;",
|
|
52
53
|
" }",
|
|
53
54
|
"",
|
|
55
|
+
" public sealed class CandidateOpenException : Win32Exception",
|
|
56
|
+
" {",
|
|
57
|
+
" public readonly int ProcessId;",
|
|
58
|
+
"",
|
|
59
|
+
" public CandidateOpenException(int error, int processId)",
|
|
60
|
+
" : base(error, \"Cannot pin candidate process \" + processId + \" (Win32 error \" + error + \": \" + new Win32Exception(error).Message + \")\")",
|
|
61
|
+
" {",
|
|
62
|
+
" ProcessId = processId;",
|
|
63
|
+
" if (error == 87 && processId > 0) Data[\"PylanceAbsentProcessId\"] = processId;",
|
|
64
|
+
" }",
|
|
65
|
+
" }",
|
|
66
|
+
"",
|
|
54
67
|
" [DllImport(\"kernel32.dll\", SetLastError = true)]",
|
|
55
68
|
" private static extern IntPtr OpenProcess(uint access, bool inherit, int pid);",
|
|
56
69
|
" [DllImport(\"kernel32.dll\", SetLastError = true)]",
|
|
@@ -99,7 +112,7 @@
|
|
|
99
112
|
" if (value == IntPtr.Zero)",
|
|
100
113
|
" {",
|
|
101
114
|
" int error = Marshal.GetLastWin32Error();",
|
|
102
|
-
" throw new
|
|
115
|
+
" throw new CandidateOpenException(error, pid);",
|
|
103
116
|
" }",
|
|
104
117
|
" return new PylanceOwnedWindowsProcess(value);",
|
|
105
118
|
" }",
|
|
@@ -141,18 +154,28 @@
|
|
|
141
154
|
" finally { if (value != IntPtr.Zero) CloseHandle(value); }",
|
|
142
155
|
" }",
|
|
143
156
|
"",
|
|
144
|
-
" public
|
|
157
|
+
" public enum SuspendResult { AlreadyExited, Suspended, ExitedDuringSuspend }",
|
|
158
|
+
"",
|
|
159
|
+
" public SuspendResult Suspend(int terminatingWaitMilliseconds)",
|
|
145
160
|
" {",
|
|
146
|
-
" if (HasExited) return;",
|
|
161
|
+
" if (HasExited) return SuspendResult.AlreadyExited;",
|
|
147
162
|
" AcquireControl();",
|
|
148
|
-
"
|
|
163
|
+
" int status = NtSuspendProcess(handle);",
|
|
164
|
+
" if (status == ProcessIsTerminating)",
|
|
165
|
+
" {",
|
|
166
|
+
" if (!WaitForExit(terminatingWaitMilliseconds))",
|
|
167
|
+
" throw new InvalidOperationException(\"Owned process \" + Id + \" is terminating but has not exited; cleanup is incomplete.\");",
|
|
168
|
+
" return SuspendResult.ExitedDuringSuspend;",
|
|
169
|
+
" }",
|
|
170
|
+
" CheckStatus(status, \"suspend owned process \" + Id);",
|
|
149
171
|
" suspended = true;",
|
|
172
|
+
" return SuspendResult.Suspended;",
|
|
150
173
|
" }",
|
|
151
174
|
"",
|
|
152
175
|
" public void Resume()",
|
|
153
176
|
" {",
|
|
154
177
|
" if (!suspended) return;",
|
|
155
|
-
" if (!HasExited)
|
|
178
|
+
" if (!HasExited) CheckControlStatus(NtResumeProcess(handle), \"resume owned process \" + Id);",
|
|
156
179
|
" suspended = false;",
|
|
157
180
|
" }",
|
|
158
181
|
"",
|
|
@@ -218,6 +241,14 @@
|
|
|
218
241
|
" }",
|
|
219
242
|
" }",
|
|
220
243
|
"",
|
|
244
|
+
" private static bool CheckControlStatus(int status, string operation)",
|
|
245
|
+
" {",
|
|
246
|
+
" // Exit can start after HasExited; the tree must still wait for the retained handle to signal.",
|
|
247
|
+
" if (status == ProcessIsTerminating) return false;",
|
|
248
|
+
" CheckStatus(status, operation);",
|
|
249
|
+
" return true;",
|
|
250
|
+
" }",
|
|
251
|
+
"",
|
|
221
252
|
" private static void CheckStatus(int status, string operation)",
|
|
222
253
|
" {",
|
|
223
254
|
" if (status < 0) throw new InvalidOperationException(\"Cannot \" + operation + \" (NTSTATUS 0x\" + status.ToString(\"X8\") + \").\");",
|
|
@@ -230,6 +261,99 @@
|
|
|
230
261
|
"}"
|
|
231
262
|
],
|
|
232
263
|
"functions": [
|
|
264
|
+
"function New-OwnedWindowsProcessLineageDiagnostics {",
|
|
265
|
+
" param(",
|
|
266
|
+
" [Parameter(Mandatory = $true)] [hashtable] $Known,",
|
|
267
|
+
" [Parameter(Mandatory = $true)] [object[]] $Hints,",
|
|
268
|
+
" [Parameter(Mandatory = $true)] $Parent,",
|
|
269
|
+
" [Parameter(Mandatory = $true)] [int] $Round,",
|
|
270
|
+
" [Parameter(Mandatory = $true)] [int] $HintIndex,",
|
|
271
|
+
" [Parameter(Mandatory = $true)] [int] $HintId,",
|
|
272
|
+
" [Parameter(Mandatory = $true)] [int] $HintParentId,",
|
|
273
|
+
" [Parameter(Mandatory = $true)] [long] $HintBirth,",
|
|
274
|
+
" [Parameter(Mandatory = $true)] [string] $Identity",
|
|
275
|
+
" )",
|
|
276
|
+
" $parentMatches = [System.Collections.Generic.List[object]]::new()",
|
|
277
|
+
" $parentMatchesTruncated = $false",
|
|
278
|
+
" for ($index = 0; $index -lt $Hints.Count; $index++) {",
|
|
279
|
+
" $entry = $Hints[$index]",
|
|
280
|
+
" if ([int]$entry.Id -ne $HintParentId) { continue }",
|
|
281
|
+
" if ($parentMatches.Count -ge 4) { $parentMatchesTruncated = $true; continue }",
|
|
282
|
+
" $parentMatches.Add([ordered]@{",
|
|
283
|
+
" snapshotIndex = $index",
|
|
284
|
+
" processId = [string][int]$entry.Id",
|
|
285
|
+
" parentProcessId = [string][int]$entry.ParentId",
|
|
286
|
+
" creationTimeUtcTicks = [string][long]$entry.CreationTimeUtcTicks",
|
|
287
|
+
" })",
|
|
288
|
+
" }",
|
|
289
|
+
" $chain = [System.Collections.Generic.List[object]]::new()",
|
|
290
|
+
" $cursor = $Parent",
|
|
291
|
+
" for ($depth = 0; $null -ne $cursor -and $depth -lt 16; $depth++) {",
|
|
292
|
+
" $chain.Add([ordered]@{",
|
|
293
|
+
" processId = [string][int]$cursor.Id",
|
|
294
|
+
" parentProcessId = [string][int]$cursor.ParentId",
|
|
295
|
+
" creationTimeUtcTicks = [string][long]$cursor.CreationTimeUtcTicks",
|
|
296
|
+
" acceptedSnapshotGeneration = [int]$cursor.SnapshotGeneration",
|
|
297
|
+
" acceptedSnapshotIndex = [int]$cursor.SnapshotIndex",
|
|
298
|
+
" nativeOpenOutcome = [string]$cursor.OpenOutcome",
|
|
299
|
+
" })",
|
|
300
|
+
" if (!$Known.ContainsKey([int]$cursor.ParentId)) { $cursor = $null; break }",
|
|
301
|
+
" $cursor = $Known[[int]$cursor.ParentId]",
|
|
302
|
+
" }",
|
|
303
|
+
" $chainTruncated = $null -ne $cursor",
|
|
304
|
+
" $root = @($Known.Values | Where-Object { $_.Depth -eq 0 })[0]",
|
|
305
|
+
" $generationMatches = $Parent.SnapshotGeneration -eq $Round",
|
|
306
|
+
" $frozenChildIdentityPresent = $Parent.AllowedChildren.ContainsKey($Identity)",
|
|
307
|
+
" $exactParentIdentityPresent = $false",
|
|
308
|
+
" foreach ($match in $parentMatches) {",
|
|
309
|
+
" if ($match.creationTimeUtcTicks -eq [string][long]$Parent.CreationTimeUtcTicks) {",
|
|
310
|
+
" $exactParentIdentityPresent = $true",
|
|
311
|
+
" break",
|
|
312
|
+
" }",
|
|
313
|
+
" }",
|
|
314
|
+
" $diagnostics = [ordered]@{",
|
|
315
|
+
" version = 1",
|
|
316
|
+
" root = [ordered]@{",
|
|
317
|
+
" processId = [string][int]$root.Id",
|
|
318
|
+
" creationTimeUtcTicks = [string][long]$root.CreationTimeUtcTicks",
|
|
319
|
+
" }",
|
|
320
|
+
" rejectedHint = [ordered]@{",
|
|
321
|
+
" processId = [string]$HintId",
|
|
322
|
+
" parentProcessId = [string]$HintParentId",
|
|
323
|
+
" creationTimeUtcTicks = [string]$HintBirth",
|
|
324
|
+
" snapshotGeneration = $Round",
|
|
325
|
+
" snapshotIndex = $HintIndex",
|
|
326
|
+
" nativeOpenOutcome = 'not-attempted-lineage-guard'",
|
|
327
|
+
" }",
|
|
328
|
+
" vanishedParent = [ordered]@{",
|
|
329
|
+
" processId = [string][int]$Parent.Id",
|
|
330
|
+
" parentProcessId = [string][int]$Parent.ParentId",
|
|
331
|
+
" creationTimeUtcTicks = [string][long]$Parent.CreationTimeUtcTicks",
|
|
332
|
+
" acceptedSnapshotGeneration = [int]$Parent.SnapshotGeneration",
|
|
333
|
+
" acceptedSnapshotIndex = [int]$Parent.SnapshotIndex",
|
|
334
|
+
" nativeOpenOutcome = [string]$Parent.OpenOutcome",
|
|
335
|
+
" }",
|
|
336
|
+
" currentSnapshot = [ordered]@{",
|
|
337
|
+
" generation = $Round",
|
|
338
|
+
" entryCount = $Hints.Count",
|
|
339
|
+
" exactVanishedParentIdentityPresent = $exactParentIdentityPresent",
|
|
340
|
+
" vanishedParentPidMatches = @($parentMatches.ToArray())",
|
|
341
|
+
" vanishedParentPidMatchesTruncated = $parentMatchesTruncated",
|
|
342
|
+
" }",
|
|
343
|
+
" failedOwnershipPredicate = [ordered]@{",
|
|
344
|
+
" expression = 'parentSnapshotGenerationMatches && frozenChildIdentityPresent'",
|
|
345
|
+
" parentSnapshotGenerationMatches = $generationMatches",
|
|
346
|
+
" frozenChildIdentityPresent = $frozenChildIdentityPresent",
|
|
347
|
+
" rejectedIdentity = $Identity",
|
|
348
|
+
" }",
|
|
349
|
+
" parentChainOrder = 'vanished-parent-to-root'",
|
|
350
|
+
" parentChain = @($chain.ToArray())",
|
|
351
|
+
" parentChainTruncated = $chainTruncated",
|
|
352
|
+
" }",
|
|
353
|
+
" $json = ConvertTo-Json -InputObject $diagnostics -Compress -Depth 6",
|
|
354
|
+
" return $json",
|
|
355
|
+
"}",
|
|
356
|
+
"",
|
|
233
357
|
"function Stop-OwnedWindowsProcessTree {",
|
|
234
358
|
" param(",
|
|
235
359
|
" [Parameter(Mandatory = $true)] $Root,",
|
|
@@ -240,48 +364,163 @@
|
|
|
240
364
|
" $watch = [System.Diagnostics.Stopwatch]::StartNew()",
|
|
241
365
|
" $held = [System.Collections.Generic.List[object]]::new()",
|
|
242
366
|
" $known = @{}",
|
|
367
|
+
" $missing = @{}",
|
|
243
368
|
" $failure = $null",
|
|
244
369
|
" $cleanupErrors = [System.Collections.Generic.List[string]]::new()",
|
|
245
370
|
" try {",
|
|
246
371
|
" if ($Root.Id -eq $PID) { throw 'Refusing to terminate the cleanup process.' }",
|
|
247
372
|
" $retainedRoot = $Root.Retain()",
|
|
248
|
-
" $rootEntry = [PSCustomObject]@{
|
|
373
|
+
" $rootEntry = [PSCustomObject]@{",
|
|
374
|
+
" Process = $retainedRoot",
|
|
375
|
+
" Id = [int]$retainedRoot.Id",
|
|
376
|
+
" CreationTimeUtcTicks = [long]$retainedRoot.CreationTimeUtcTicks",
|
|
377
|
+
" Depth = 0",
|
|
378
|
+
" ParentId = [int]$retainedRoot.ParentId",
|
|
379
|
+
" SnapshotGeneration = -1",
|
|
380
|
+
" SnapshotIndex = -1",
|
|
381
|
+
" OpenOutcome = 'retained-root'",
|
|
382
|
+
" AllowedChildren = $null",
|
|
383
|
+
" }",
|
|
249
384
|
" $held.Add($rootEntry)",
|
|
250
385
|
" $known[[int]$retainedRoot.Id] = $rootEntry",
|
|
251
|
-
" $
|
|
386
|
+
" $remaining = [Math]::Max(1, $TimeoutMilliseconds - [int]$watch.ElapsedMilliseconds)",
|
|
387
|
+
" $null = $retainedRoot.Suspend($remaining)",
|
|
252
388
|
" for ($round = 0; ; $round++) {",
|
|
253
|
-
" if ($round -ge 64 -or $
|
|
389
|
+
" if ($round -ge 64 -or $known.Count -gt 4096 -or $watch.ElapsedMilliseconds -ge $TimeoutMilliseconds) {",
|
|
254
390
|
" throw 'Owned process-tree discovery exceeded its bounded budget; cleanup is incomplete.'",
|
|
255
391
|
" }",
|
|
392
|
+
" $hints = @(& $Snapshot)",
|
|
256
393
|
" $found = $false",
|
|
257
|
-
"
|
|
258
|
-
"
|
|
259
|
-
"
|
|
260
|
-
" $
|
|
261
|
-
"
|
|
262
|
-
"
|
|
263
|
-
"
|
|
264
|
-
"
|
|
265
|
-
"
|
|
266
|
-
"
|
|
267
|
-
"
|
|
268
|
-
"
|
|
269
|
-
"
|
|
270
|
-
"
|
|
271
|
-
"
|
|
394
|
+
" $madeProgress = $true",
|
|
395
|
+
" while ($madeProgress) {",
|
|
396
|
+
" $madeProgress = $false",
|
|
397
|
+
" $hintIndex = 0",
|
|
398
|
+
" foreach ($hint in $hints) {",
|
|
399
|
+
" $currentHintIndex = $hintIndex",
|
|
400
|
+
" $hintIndex++",
|
|
401
|
+
" $hintId = [int]$hint.Id",
|
|
402
|
+
" $hintParentId = [int]$hint.ParentId",
|
|
403
|
+
" $hintBirth = [long]$hint.CreationTimeUtcTicks",
|
|
404
|
+
" if ($known.ContainsKey($hintId)) {",
|
|
405
|
+
" $existing = $known[$hintId]",
|
|
406
|
+
" if ($null -eq $existing.Process -and $hintBirth -gt 0 -and $hintBirth -ne $existing.CreationTimeUtcTicks) {",
|
|
407
|
+
" throw \"Vanished process $hintId was reused during discovery; cleanup is incomplete.\"",
|
|
408
|
+
" }",
|
|
409
|
+
" continue",
|
|
410
|
+
" }",
|
|
411
|
+
" if (!$known.ContainsKey($hintParentId)) { continue }",
|
|
412
|
+
" if ($watch.ElapsedMilliseconds -ge $TimeoutMilliseconds) { throw 'Owned process-tree discovery timed out; cleanup is incomplete.' }",
|
|
413
|
+
" $parent = $known[$hintParentId]",
|
|
414
|
+
" if ($null -eq $parent.Process) {",
|
|
415
|
+
" $identity = \"$hintId`:$hintBirth\"",
|
|
416
|
+
" if ($parent.SnapshotGeneration -ne $round -or !$parent.AllowedChildren.ContainsKey($identity)) {",
|
|
417
|
+
" $lineageMessage = \"Cannot prove ownership of process $hintId through vanished parent $hintParentId; cleanup is incomplete.\"",
|
|
418
|
+
" try {",
|
|
419
|
+
" $lineageDiagnostics = New-OwnedWindowsProcessLineageDiagnostics -Known $known -Hints $hints -Parent $parent -Round $round -HintIndex $currentHintIndex -HintId $hintId -HintParentId $hintParentId -HintBirth $hintBirth -Identity $identity",
|
|
420
|
+
" [Console]::Error.WriteLine(\"OWNED_PROCESS_LINEAGE_DIAGNOSTICS $lineageDiagnostics\")",
|
|
421
|
+
" $lineageMessage += \" Ownership diagnostics: $lineageDiagnostics\"",
|
|
422
|
+
" } catch {",
|
|
423
|
+
" $lineageMessage += \" Ownership diagnostic capture failed: $($_.Exception.Message)\"",
|
|
424
|
+
" }",
|
|
425
|
+
" throw $lineageMessage",
|
|
426
|
+
" }",
|
|
272
427
|
" }",
|
|
273
|
-
"
|
|
274
|
-
" if ($
|
|
275
|
-
" if ($candidate.Id -eq $PID) { throw 'Refusing to include the cleanup process in the owned tree.' }",
|
|
276
|
-
" # Freeze each accepted parent before its next child snapshot, not an entire discovered tree.",
|
|
277
|
-
" $entry = [PSCustomObject]@{ Process = $candidate; Depth = $parent.Depth + 1 }",
|
|
278
|
-
" $held.Add($entry)",
|
|
279
|
-
" $known[[int]$candidate.Id] = $entry",
|
|
428
|
+
" # Exclude historical PID reuse before opening potentially inaccessible processes.",
|
|
429
|
+
" if ($hintBirth -gt 0 -and $hintBirth -lt $parent.CreationTimeUtcTicks) { continue }",
|
|
280
430
|
" $candidate = $null",
|
|
281
|
-
"
|
|
282
|
-
"
|
|
283
|
-
"
|
|
284
|
-
"
|
|
431
|
+
" try {",
|
|
432
|
+
" try { $candidate = & $OpenProcess $hintId }",
|
|
433
|
+
" catch {",
|
|
434
|
+
" $openFailure = $_.Exception",
|
|
435
|
+
" while ($openFailure.InnerException) { $openFailure = $openFailure.InnerException }",
|
|
436
|
+
" $typedAbsent = $openFailure -is [PylanceOwnedWindowsProcess+CandidateOpenException] -and",
|
|
437
|
+
" $openFailure.NativeErrorCode -eq 87 -and $openFailure.ProcessId -eq $hintId",
|
|
438
|
+
" $taggedAbsent = $openFailure -is [System.ComponentModel.Win32Exception] -and",
|
|
439
|
+
" $openFailure.NativeErrorCode -eq 87 -and",
|
|
440
|
+
" $openFailure.Data['PylanceAbsentProcessId'] -eq $hintId",
|
|
441
|
+
" if (!$typedAbsent -and !$taggedAbsent) {",
|
|
442
|
+
" throw",
|
|
443
|
+
" }",
|
|
444
|
+
" if ($hintId -le 0 -or $hintBirth -le 0) {",
|
|
445
|
+
" throw \"Cannot prove the identity of vanished process $hintId; cleanup is incomplete.\"",
|
|
446
|
+
" }",
|
|
447
|
+
" if ($hintBirth -lt $parent.CreationTimeUtcTicks) { continue }",
|
|
448
|
+
" if ($hintBirth -eq $parent.CreationTimeUtcTicks) {",
|
|
449
|
+
" throw \"Ambiguous parent/child birth ordering for $hintId; cleanup is incomplete.\"",
|
|
450
|
+
" }",
|
|
451
|
+
" if ($null -ne $parent.Process) {",
|
|
452
|
+
" $parentExit = $parent.Process.ExitTimeUtcTicks",
|
|
453
|
+
" if ($parentExit -ne 0 -and $hintBirth -gt $parentExit) { continue }",
|
|
454
|
+
" }",
|
|
455
|
+
" if ($hintId -eq $PID) { throw 'Refusing to include the cleanup process in the owned tree.' }",
|
|
456
|
+
" $allowedChildren = @{}",
|
|
457
|
+
" foreach ($childHint in $hints) {",
|
|
458
|
+
" $childId = [int]$childHint.Id",
|
|
459
|
+
" $childBirth = [long]$childHint.CreationTimeUtcTicks",
|
|
460
|
+
" if ([int]$childHint.ParentId -eq $hintId -and $childBirth -gt $hintBirth) {",
|
|
461
|
+
" $allowedChildren[\"$childId`:$childBirth\"] = $true",
|
|
462
|
+
" }",
|
|
463
|
+
" }",
|
|
464
|
+
" $entry = [PSCustomObject]@{",
|
|
465
|
+
" Process = $null",
|
|
466
|
+
" Id = $hintId",
|
|
467
|
+
" CreationTimeUtcTicks = $hintBirth",
|
|
468
|
+
" Depth = $parent.Depth + 1",
|
|
469
|
+
" ParentId = $hintParentId",
|
|
470
|
+
" SnapshotGeneration = $round",
|
|
471
|
+
" SnapshotIndex = $currentHintIndex",
|
|
472
|
+
" OpenOutcome = 'candidate-open-error-87'",
|
|
473
|
+
" AllowedChildren = $allowedChildren",
|
|
474
|
+
" }",
|
|
475
|
+
" $known[$hintId] = $entry",
|
|
476
|
+
" $found = $true",
|
|
477
|
+
" $madeProgress = $true",
|
|
478
|
+
" continue",
|
|
479
|
+
" }",
|
|
480
|
+
" if ($null -eq $candidate) { throw \"Cannot pin candidate process $hintId; cleanup is incomplete.\" }",
|
|
481
|
+
" if ($candidate.Id -ne $hintId) { throw 'Pinned candidate identity does not match the snapshot.' }",
|
|
482
|
+
" # A pinned identity must match the exact native snapshot generation.",
|
|
483
|
+
" if ($hintBirth -gt 0 -and $candidate.CreationTimeUtcTicks -ne $hintBirth) {",
|
|
484
|
+
" throw \"Pinned candidate birth does not match the snapshot for $hintId; cleanup is incomplete.\"",
|
|
485
|
+
" }",
|
|
486
|
+
" if ($candidate.ParentId -ne $parent.Id) { continue }",
|
|
487
|
+
" if ($candidate.CreationTimeUtcTicks -lt $parent.CreationTimeUtcTicks) { continue }",
|
|
488
|
+
" if ($candidate.CreationTimeUtcTicks -eq $parent.CreationTimeUtcTicks) {",
|
|
489
|
+
" throw \"Ambiguous parent/child birth ordering for $($candidate.Id); cleanup is incomplete.\"",
|
|
490
|
+
" }",
|
|
491
|
+
" if ($null -ne $parent.Process) {",
|
|
492
|
+
" $parentExit = $parent.Process.ExitTimeUtcTicks",
|
|
493
|
+
" if ($parentExit -ne 0 -and $candidate.CreationTimeUtcTicks -gt $parentExit) { continue }",
|
|
494
|
+
" }",
|
|
495
|
+
" if ($candidate.Id -eq $PID) { throw 'Refusing to include the cleanup process in the owned tree.' }",
|
|
496
|
+
" # Freeze each accepted parent before its next child snapshot, not an entire discovered tree.",
|
|
497
|
+
" $entry = [PSCustomObject]@{",
|
|
498
|
+
" Process = $candidate",
|
|
499
|
+
" Id = [int]$candidate.Id",
|
|
500
|
+
" CreationTimeUtcTicks = [long]$candidate.CreationTimeUtcTicks",
|
|
501
|
+
" Depth = $parent.Depth + 1",
|
|
502
|
+
" ParentId = [int]$candidate.ParentId",
|
|
503
|
+
" SnapshotGeneration = -1",
|
|
504
|
+
" SnapshotIndex = $currentHintIndex",
|
|
505
|
+
" OpenOutcome = 'pinned'",
|
|
506
|
+
" AllowedChildren = $null",
|
|
507
|
+
" }",
|
|
508
|
+
" $held.Add($entry)",
|
|
509
|
+
" $known[$hintId] = $entry",
|
|
510
|
+
" $candidate = $null",
|
|
511
|
+
" $remaining = [Math]::Max(1, $TimeoutMilliseconds - [int]$watch.ElapsedMilliseconds)",
|
|
512
|
+
" $null = $entry.Process.Suspend($remaining)",
|
|
513
|
+
" $found = $true",
|
|
514
|
+
" $madeProgress = $true",
|
|
515
|
+
" } finally {",
|
|
516
|
+
" if ($null -ne $candidate) { $candidate.Dispose() }",
|
|
517
|
+
" }",
|
|
518
|
+
" }",
|
|
519
|
+
" }",
|
|
520
|
+
" # Missing candidates require another snapshot, not an assumed empty descendant branch.",
|
|
521
|
+
" foreach ($hint in $hints) {",
|
|
522
|
+
" if ($missing.ContainsKey([int]$hint.ParentId)) {",
|
|
523
|
+
" throw \"Cannot establish descendant ownership after candidate $($hint.ParentId) disappeared; cleanup is incomplete.\"",
|
|
285
524
|
" }",
|
|
286
525
|
" }",
|
|
287
526
|
" if (!$found) { break }",
|
|
@@ -43,6 +43,7 @@ export declare abstract class LanguageServerBase implements LanguageServerInterf
|
|
|
43
43
|
private _workspaceDiagnosticsReporter;
|
|
44
44
|
private _workspaceDiagnosticsProgressReporter;
|
|
45
45
|
private _workspaceDiagnosticsResolve;
|
|
46
|
+
private _workspaceDiagnosticsCancellationDisposable;
|
|
46
47
|
protected isDisposed: boolean;
|
|
47
48
|
protected client: ClientCapabilities;
|
|
48
49
|
protected defaultClientConfig: any;
|
|
@@ -134,9 +135,11 @@ export declare abstract class LanguageServerBase implements LanguageServerInterf
|
|
|
134
135
|
reporter: WorkDoneProgressReporter;
|
|
135
136
|
source: AbstractCancellationTokenSource;
|
|
136
137
|
}>;
|
|
138
|
+
protected getWorkspaceDiagnosticVersion(version: number | undefined): number | null;
|
|
137
139
|
protected sendDiagnostics(params: PublishDiagnosticsParams[]): void;
|
|
138
140
|
protected convertLspUriStringToUri(uri: string): Uri;
|
|
139
141
|
protected addDynamicFeature(feature: DynamicFeature): void;
|
|
142
|
+
private _completeWorkspaceDiagnostics;
|
|
140
143
|
private _getCompatibleMarkupKind;
|
|
141
144
|
private _convertDiagnostics;
|
|
142
145
|
}
|
|
@@ -233,9 +233,8 @@ class LanguageServerBase {
|
|
|
233
233
|
this.console.level = serverSettings.logLevel ?? console_1.LogLevel.Info;
|
|
234
234
|
this.dynamicFeatures.update(serverSettings);
|
|
235
235
|
// If the workspace mode has changed, we may need to resolve the workspace diagnostics promise.
|
|
236
|
-
if (serverSettings.openFilesOnly
|
|
237
|
-
this.
|
|
238
|
-
this._workspaceDiagnosticsResolve = undefined;
|
|
236
|
+
if (serverSettings.openFilesOnly) {
|
|
237
|
+
this._completeWorkspaceDiagnostics();
|
|
239
238
|
}
|
|
240
239
|
// Then use the updated settings to restart the service.
|
|
241
240
|
this.updateOptionsAndRestartService(workspace, serverSettings);
|
|
@@ -774,9 +773,11 @@ class LanguageServerBase {
|
|
|
774
773
|
return result;
|
|
775
774
|
}
|
|
776
775
|
async onWorkspaceDiagnostics(params, token, workDoneProgress, resultReporter) {
|
|
776
|
+
if (token.isCancellationRequested) {
|
|
777
|
+
return { items: [] };
|
|
778
|
+
}
|
|
777
779
|
// Resolve any pending workspace diagnostics. We only allow one at a time.
|
|
778
|
-
this.
|
|
779
|
-
this._workspaceDiagnosticsResolve = undefined;
|
|
780
|
+
this._completeWorkspaceDiagnostics();
|
|
780
781
|
// Save the progress reporters and force a refresh of analysis.
|
|
781
782
|
this._workspaceDiagnosticsProgressReporter = !(0, lspUtils_1.isNullProgressReporter)(workDoneProgress)
|
|
782
783
|
? wrapProgressReporter(workDoneProgress)
|
|
@@ -785,12 +786,21 @@ class LanguageServerBase {
|
|
|
785
786
|
this.workspaceFactory.getNonDefaultWorkspaces().forEach((workspace) => {
|
|
786
787
|
workspace.service.invalidateAndScheduleReanalysis(backgroundAnalysisProgram_1.InvalidatedReason.Reanalyzed);
|
|
787
788
|
});
|
|
788
|
-
return new Promise((resolve
|
|
789
|
-
//
|
|
790
|
-
// should cause a new workspace diagnostic to be generated.
|
|
791
|
-
// Save the resolve callback to be used during shutdown so that tests don't crash
|
|
792
|
-
// on the unresolved promise for the workspace diagnostics.
|
|
789
|
+
return new Promise((resolve) => {
|
|
790
|
+
// Keep the request active until cancellation, replacement, configuration change, or shutdown.
|
|
793
791
|
this._workspaceDiagnosticsResolve = resolve;
|
|
792
|
+
const cancellationDisposable = token.onCancellationRequested(() => {
|
|
793
|
+
this._completeWorkspaceDiagnostics(resolve);
|
|
794
|
+
});
|
|
795
|
+
if (this._workspaceDiagnosticsResolve === resolve) {
|
|
796
|
+
this._workspaceDiagnosticsCancellationDisposable = cancellationDisposable;
|
|
797
|
+
if (token.isCancellationRequested) {
|
|
798
|
+
this._completeWorkspaceDiagnostics(resolve);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
else {
|
|
802
|
+
cancellationDisposable.dispose();
|
|
803
|
+
}
|
|
794
804
|
});
|
|
795
805
|
}
|
|
796
806
|
onDidChangeWatchedFiles(params) {
|
|
@@ -849,7 +859,7 @@ class LanguageServerBase {
|
|
|
849
859
|
}
|
|
850
860
|
onShutdown(token) {
|
|
851
861
|
// Shutdown remaining workspaces.
|
|
852
|
-
this.
|
|
862
|
+
this._completeWorkspaceDiagnostics();
|
|
853
863
|
this.workspaceFactory.clear();
|
|
854
864
|
// Stop tracking all open files.
|
|
855
865
|
this.openFileMap.clear();
|
|
@@ -990,6 +1000,9 @@ class LanguageServerBase {
|
|
|
990
1000
|
source: (0, cancellationUtils_1.CancelAfter)(this.serviceProvider.cancellationProvider(), token, serverInitiatedReporter.token),
|
|
991
1001
|
};
|
|
992
1002
|
}
|
|
1003
|
+
getWorkspaceDiagnosticVersion(version) {
|
|
1004
|
+
return version || null;
|
|
1005
|
+
}
|
|
993
1006
|
sendDiagnostics(params) {
|
|
994
1007
|
for (const param of params) {
|
|
995
1008
|
if (param.diagnostics.length === 0) {
|
|
@@ -1002,7 +1015,14 @@ class LanguageServerBase {
|
|
|
1002
1015
|
if (this._workspaceDiagnosticsReporter) {
|
|
1003
1016
|
// Skip storing previous result ids, just send new results every time.
|
|
1004
1017
|
this._workspaceDiagnosticsReporter.report({
|
|
1005
|
-
items: [
|
|
1018
|
+
items: [
|
|
1019
|
+
{
|
|
1020
|
+
...param,
|
|
1021
|
+
kind: 'full',
|
|
1022
|
+
version: this.getWorkspaceDiagnosticVersion(param.version),
|
|
1023
|
+
items: param.diagnostics,
|
|
1024
|
+
},
|
|
1025
|
+
],
|
|
1006
1026
|
});
|
|
1007
1027
|
}
|
|
1008
1028
|
else {
|
|
@@ -1017,6 +1037,18 @@ class LanguageServerBase {
|
|
|
1017
1037
|
addDynamicFeature(feature) {
|
|
1018
1038
|
this.dynamicFeatures.add(feature);
|
|
1019
1039
|
}
|
|
1040
|
+
_completeWorkspaceDiagnostics(expectedResolve = this._workspaceDiagnosticsResolve) {
|
|
1041
|
+
if (!expectedResolve || this._workspaceDiagnosticsResolve !== expectedResolve) {
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
this._workspaceDiagnosticsResolve = undefined;
|
|
1045
|
+
this._workspaceDiagnosticsCancellationDisposable?.dispose();
|
|
1046
|
+
this._workspaceDiagnosticsCancellationDisposable = undefined;
|
|
1047
|
+
this._workspaceDiagnosticsReporter = undefined;
|
|
1048
|
+
this._workspaceDiagnosticsProgressReporter?.end();
|
|
1049
|
+
this._workspaceDiagnosticsProgressReporter = undefined;
|
|
1050
|
+
expectedResolve({ items: [] });
|
|
1051
|
+
}
|
|
1020
1052
|
_getCompatibleMarkupKind(clientSupportedFormats) {
|
|
1021
1053
|
const serverSupportedFormats = [vscode_languageserver_1.MarkupKind.PlainText, vscode_languageserver_1.MarkupKind.Markdown];
|
|
1022
1054
|
for (const format of clientSupportedFormats ?? []) {
|