-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathSetTypeCache.ps1
More file actions
122 lines (104 loc) · 4.79 KB
/
SetTypeCache.ps1
File metadata and controls
122 lines (104 loc) · 4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
using namespace System
using namespace System.Collections.Generic
using namespace System.Management.Automation
using namespace System.Reflection
<#
SYNOPSIS
Forcefully repopulates type tab completion cache. Useful when loading
assemblies that cause Assembly.GetTypes() to throw in PowerShell 5.1.
#>
function global:Set-TypeCompletionCache {
param()
end {
Import-Module PSLambda
$types = [type[]] (& {
Find-Type -Force TypeCompletionMapping
Find-Type -Force TypeCompletion
Find-Type -Force TypeAccelerators
Find-Type -Force TypeCompletionBase
Find-Type -Force TypeCompletionInStringFormat
Find-Type -Force ClrFacade
Find-Type -Force TypeResolver -Namespace System.Management.Automation.Language
})
Invoke-PSLambda -EnablePrivateBinding -ResolvablePrivateTypes $types {
$entries = [Dictionary[string,TypeCompletionMapping]]::new([StringComparer]::OrdinalIgnoreCase)
foreach ($type in [TypeAccelerators]::Get) {
$entry = default([TypeCompletionMapping])
$instance = [TypeCompletion]::new()
$instance.Type = $type.Value
if ($entries.TryGetValue($type.Key, $entry)) {
$acceleratorType = $type.Value
$alreadyIncluded = $entry.Completions.Any{ $item => {
return $item -is [TypeCompletion] -and ([TypeCompletion]$item).Type -eq $acceleratorType
}}
if ($alreadyIncluded) {
continue
}
$entry.Completions.Add($instance)
} else {
$entry = [TypeCompletionMapping]::new()
$entry.Key = $type.Key
$entry.Completions = [List[TypeCompletionBase]]::new()
$entry.Completions.Add($instance)
$entries.Add($type.Key, $entry)
}
$fullTypeName = $type.Value.FullName
if ($entries.ContainsKey($fullTypeName)) {
continue
}
$mapping = [TypeCompletionMapping]::new()
$mapping.Key = $fullTypeName
$mapping.Completions = [List[TypeCompletionBase]]::new()
$mapping.Completions.Add($instance)
$entries.Add($fullTypeName, $mapping)
$shortTypeName = $type.Value.Name
if ($type.Key.Equals($shortTypeName, [StringComparison]::OrdinalIgnoreCase)) {
continue
}
if (-not $entries.TryGetValue($shortTypeName, $entry)) {
$entry = [TypeCompletionMapping]::new()
$entry.Key = $shortTypeName
$entries.Add($shortTypeName, $entry)
}
$entry.Completions.Add($instance)
}
$availableTypes = [List[type]]::new()
foreach ($assembly in [AppDomain]::CurrentDomain.GetAssemblies()) {
$types = [type]::EmptyTypes
try {
$types = $assembly.GetTypes()
} catch {
continue
}
$availableTypes.AddRange($types)
}
foreach ($type in $availableTypes) {
try {
if (-not [TypeResolver]::IsPublic($type)) {
continue
}
[CompletionCompleters]::HandleNamespace($entries, $type.Namespace)
[CompletionCompleters]::HandleType($entries, $type.FullName, $type.Name, $type)
} catch {
continue
}
}
$grouping = ([TypeCompletionMapping[]]$entries.Values).
GroupBy{ $t => $t.Key.ToCharArray().Count{ $c => ($c -eq '.'[0]) }}.
OrderBy{ $g => $g.Key }.
ToArray()
$localTypeCache = [TypeCompletionMapping[][]]::new($grouping.Last().Key + 1)
foreach ($group in $grouping) {
$localTypeCache.SetValue([TypeCompletionMapping[]]$group, $group.Key)
}
$cacheField = default([FieldInfo])
$bindingFlags = [BindingFlags]'NonPublic, Static'
if (([Version]$PSVersionTable['PSVersion']).Major -gt 5) {
$cacheField = [CompletionCompleters].GetField('s_typeCache', $bindingFlags)
} else {
$cacheField = [CompletionCompleters].GetField('typeCache', $bindingFlags)
}
$cacheField.SetValue($null, $localTypeCache)
}
}
}