5
5
6
6
using System ;
7
7
using System . Collections . Generic ;
8
+ using System . Diagnostics ;
8
9
using System . Linq ;
10
+ using System . Management . Automation ;
9
11
using System . Management . Automation . Language ;
12
+ using System . Reflection ;
13
+ using System . Threading ;
14
+ using System . Threading . Tasks ;
15
+ using Microsoft . Extensions . Logging ;
16
+ using Microsoft . PowerShell . EditorServices . Utility ;
10
17
11
18
namespace Microsoft . PowerShell . EditorServices . Symbols
12
19
{
@@ -17,11 +24,11 @@ internal static class AstOperations
17
24
{
18
25
// TODO: When netstandard is upgraded to 2.0, see if
19
26
// Delegate.CreateDelegate can be used here instead
20
- // private static readonly MethodInfo s_extentCloneWithNewOffset = typeof(PSObject).GetTypeInfo().Assembly
21
- // .GetType("System.Management.Automation.Language.InternalScriptPosition")
22
- // .GetMethod("CloneWithNewOffset", BindingFlags.Instance | BindingFlags.NonPublic);
27
+ private static readonly MethodInfo s_extentCloneWithNewOffset = typeof ( PSObject ) . GetTypeInfo ( ) . Assembly
28
+ . GetType ( "System.Management.Automation.Language.InternalScriptPosition" )
29
+ . GetMethod ( "CloneWithNewOffset" , BindingFlags . Instance | BindingFlags . NonPublic ) ;
23
30
24
- // private static readonly SemaphoreSlim s_completionHandle = AsyncUtils.CreateSimpleLockingSemaphore();
31
+ private static readonly SemaphoreSlim s_completionHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
25
32
26
33
// TODO: BRING THIS BACK
27
34
/// <summary>
@@ -48,89 +55,88 @@ internal static class AstOperations
48
55
/// A CommandCompletion instance that contains completions for the
49
56
/// symbol at the given offset.
50
57
/// </returns>
51
- // static public async Task<CommandCompletion> GetCompletionsAsync(
52
- // Ast scriptAst,
53
- // Token[] currentTokens,
54
- // int fileOffset,
55
- // PowerShellContext powerShellContext,
56
- // ILogger logger,
57
- // CancellationToken cancellationToken)
58
- // {
59
- // if (!s_completionHandle.Wait(0))
60
- // {
61
- // return null;
62
- // }
63
-
64
- // try
65
- // {
66
- // IScriptPosition cursorPosition = (IScriptPosition)s_extentCloneWithNewOffset.Invoke(
67
- // scriptAst.Extent.StartScriptPosition,
68
- // new object[] { fileOffset });
69
-
70
- // logger.Write(
71
- // LogLevel.Verbose,
72
- // string.Format(
73
- // "Getting completions at offset {0} (line: {1}, column: {2})",
74
- // fileOffset,
75
- // cursorPosition.LineNumber,
76
- // cursorPosition.ColumnNumber));
77
-
78
- // if (!powerShellContext.IsAvailable)
79
- // {
80
- // return null;
81
- // }
82
-
83
- // var stopwatch = new Stopwatch();
84
-
85
- // // If the current runspace is out of process we can use
86
- // // CommandCompletion.CompleteInput because PSReadLine won't be taking up the
87
- // // main runspace.
88
- // if (powerShellContext.IsCurrentRunspaceOutOfProcess())
89
- // {
90
- // using (RunspaceHandle runspaceHandle = await powerShellContext.GetRunspaceHandleAsync(cancellationToken))
91
- // using (PowerShell powerShell = PowerShell.Create())
92
- // {
93
- // powerShell.Runspace = runspaceHandle.Runspace;
94
- // stopwatch.Start();
95
- // try
96
- // {
97
- // return CommandCompletion.CompleteInput(
98
- // scriptAst,
99
- // currentTokens,
100
- // cursorPosition,
101
- // options: null,
102
- // powershell: powerShell);
103
- // }
104
- // finally
105
- // {
106
- // stopwatch.Stop();
107
- // logger.Write(LogLevel.Verbose, $"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");
108
- // }
109
- // }
110
- // }
111
-
112
- // CommandCompletion commandCompletion = null;
113
- // await powerShellContext.InvokeOnPipelineThreadAsync(
114
- // pwsh =>
115
- // {
116
- // stopwatch.Start();
117
- // commandCompletion = CommandCompletion.CompleteInput(
118
- // scriptAst,
119
- // currentTokens,
120
- // cursorPosition,
121
- // options: null,
122
- // powershell: pwsh);
123
- // });
124
- // stopwatch.Stop();
125
- // logger.Write(LogLevel.Verbose, $"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");
126
-
127
- // return commandCompletion;
128
- // }
129
- // finally
130
- // {
131
- // s_completionHandle.Release();
132
- // }
133
- // }
58
+ static public async Task < CommandCompletion > GetCompletionsAsync (
59
+ Ast scriptAst ,
60
+ Token [ ] currentTokens ,
61
+ int fileOffset ,
62
+ PowerShellContextService powerShellContext ,
63
+ ILogger logger ,
64
+ CancellationToken cancellationToken )
65
+ {
66
+ if ( ! s_completionHandle . Wait ( 0 ) )
67
+ {
68
+ return null ;
69
+ }
70
+
71
+ try
72
+ {
73
+ IScriptPosition cursorPosition = ( IScriptPosition ) s_extentCloneWithNewOffset . Invoke (
74
+ scriptAst . Extent . StartScriptPosition ,
75
+ new object [ ] { fileOffset } ) ;
76
+
77
+ logger . LogTrace (
78
+ string . Format (
79
+ "Getting completions at offset {0} (line: {1}, column: {2})" ,
80
+ fileOffset ,
81
+ cursorPosition . LineNumber ,
82
+ cursorPosition . ColumnNumber ) ) ;
83
+
84
+ if ( ! powerShellContext . IsAvailable )
85
+ {
86
+ return null ;
87
+ }
88
+
89
+ var stopwatch = new Stopwatch ( ) ;
90
+
91
+ // If the current runspace is out of process we can use
92
+ // CommandCompletion.CompleteInput because PSReadLine won't be taking up the
93
+ // main runspace.
94
+ if ( powerShellContext . IsCurrentRunspaceOutOfProcess ( ) )
95
+ {
96
+ using ( RunspaceHandle runspaceHandle = await powerShellContext . GetRunspaceHandleAsync ( cancellationToken ) )
97
+ using ( System . Management . Automation . PowerShell powerShell = System . Management . Automation . PowerShell . Create ( ) )
98
+ {
99
+ powerShell . Runspace = runspaceHandle . Runspace ;
100
+ stopwatch . Start ( ) ;
101
+ try
102
+ {
103
+ return CommandCompletion . CompleteInput (
104
+ scriptAst ,
105
+ currentTokens ,
106
+ cursorPosition ,
107
+ options : null ,
108
+ powershell : powerShell ) ;
109
+ }
110
+ finally
111
+ {
112
+ stopwatch . Stop ( ) ;
113
+ logger . LogTrace ( $ "IntelliSense completed in { stopwatch . ElapsedMilliseconds } ms.") ;
114
+ }
115
+ }
116
+ }
117
+
118
+ CommandCompletion commandCompletion = null ;
119
+ await powerShellContext . InvokeOnPipelineThreadAsync (
120
+ pwsh =>
121
+ {
122
+ stopwatch . Start ( ) ;
123
+ commandCompletion = CommandCompletion . CompleteInput (
124
+ scriptAst ,
125
+ currentTokens ,
126
+ cursorPosition ,
127
+ options : null ,
128
+ powershell : pwsh ) ;
129
+ } ) ;
130
+ stopwatch . Stop ( ) ;
131
+ logger . LogTrace ( $ "IntelliSense completed in { stopwatch . ElapsedMilliseconds } ms.") ;
132
+
133
+ return commandCompletion ;
134
+ }
135
+ finally
136
+ {
137
+ s_completionHandle . Release ( ) ;
138
+ }
139
+ }
134
140
135
141
/// <summary>
136
142
/// Finds the symbol at a given file location
0 commit comments