55
66using System ;
77using System . Collections . Generic ;
8+ using System . Diagnostics ;
89using System . Linq ;
10+ using System . Management . Automation ;
911using 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 ;
1017
1118namespace Microsoft . PowerShell . EditorServices . Symbols
1219{
@@ -17,11 +24,11 @@ internal static class AstOperations
1724 {
1825 // TODO: When netstandard is upgraded to 2.0, see if
1926 // 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 ) ;
2330
24- // private static readonly SemaphoreSlim s_completionHandle = AsyncUtils.CreateSimpleLockingSemaphore();
31+ private static readonly SemaphoreSlim s_completionHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
2532
2633 // TODO: BRING THIS BACK
2734 /// <summary>
@@ -48,89 +55,88 @@ internal static class AstOperations
4855 /// A CommandCompletion instance that contains completions for the
4956 /// symbol at the given offset.
5057 /// </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+ }
134140
135141 /// <summary>
136142 /// Finds the symbol at a given file location
0 commit comments