public override Task <CodeLensContainer> Handle(CodeLensParams request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            CodeLens[] codeLensResults = ProvideCodeLenses(scriptFile);
            return(Task.FromResult(new CodeLensContainer(codeLensResults)));
        }
        public Task <DocumentHighlightContainer> Handle(
            DocumentHighlightParams request,
            CancellationToken cancellationToken)
        {
            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            IReadOnlyList <SymbolReference> symbolOccurrences = _symbolsService.FindOccurrencesInFile(
                scriptFile,
                (int)request.Position.Line + 1,
                (int)request.Position.Character + 1);

            if (symbolOccurrences == null)
            {
                return(Task.FromResult(s_emptyHighlightContainer));
            }

            var highlights = new DocumentHighlight[symbolOccurrences.Count];

            for (int i = 0; i < symbolOccurrences.Count; i++)
            {
                highlights[i] = new DocumentHighlight
                {
                    Kind  = DocumentHighlightKind.Write, // TODO: Which symbol types are writable?
                    Range = symbolOccurrences[i].ScriptRegion.ToRange()
                };
            }

            return(Task.FromResult(new DocumentHighlightContainer(highlights)));
        }
        public async Task <LocationOrLocationLinks> Handle(DefinitionParams request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile =
                _workspaceService.GetFile(
                    request.TextDocument.Uri.ToString());

            SymbolReference foundSymbol =
                _symbolsService.FindSymbolAtLocation(
                    scriptFile,
                    (int)request.Position.Line + 1,
                    (int)request.Position.Character + 1);

            List <LocationOrLocationLink> definitionLocations = new List <LocationOrLocationLink>();

            if (foundSymbol != null)
            {
                SymbolReference foundDefinition = await _symbolsService.GetDefinitionOfSymbolAsync(
                    scriptFile,
                    foundSymbol);

                if (foundDefinition != null)
                {
                    definitionLocations.Add(
                        new LocationOrLocationLink(
                            new Location
                    {
                        Uri   = PathUtils.ToUri(foundDefinition.FilePath),
                        Range = GetRangeFromScriptRegion(foundDefinition.ScriptRegion)
                    }));
                }
            }

            return(new LocationOrLocationLinks(definitionLocations));
        }
예제 #4
0
        public async Task <Hover> Handle(HoverParams request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile =
                _workspaceService.GetFile(
                    request.TextDocument.Uri.ToString());

            SymbolDetails symbolDetails =
                await _symbolsService.FindSymbolDetailsAtLocationAsync(
                    scriptFile,
                    (int)request.Position.Line + 1,
                    (int)request.Position.Character + 1);

            List <MarkedString> symbolInfo = new List <MarkedString>();
            Range symbolRange = null;

            if (symbolDetails != null)
            {
                symbolInfo.Add(new MarkedString("PowerShell", symbolDetails.DisplayString));

                if (!string.IsNullOrEmpty(symbolDetails.Documentation))
                {
                    symbolInfo.Add(new MarkedString("markdown", symbolDetails.Documentation));
                }

                symbolRange = GetRangeFromScriptRegion(symbolDetails.SymbolReference.ScriptRegion);
            }

            return(new Hover
            {
                Contents = new MarkedStringsOrMarkupContent(symbolInfo),
                Range = symbolRange
            });
        }
        public async Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken)
        {
            int cursorLine   = (int)request.Position.Line + 1;
            int cursorColumn = (int)request.Position.Character + 1;

            ScriptFile scriptFile =
                _workspaceService.GetFile(
                    request.TextDocument.Uri.ToString());

            CompletionResults completionResults =
                await GetCompletionsInFileAsync(
                    scriptFile,
                    cursorLine,
                    cursorColumn);

            CompletionItem[] completionItems = s_emptyCompletionResult;

            if (completionResults != null)
            {
                completionItems = new CompletionItem[completionResults.Completions.Length];
                for (int i = 0; i < completionItems.Length; i++)
                {
                    completionItems[i] = CreateCompletionItem(completionResults.Completions[i], completionResults.ReplacedRange, i + 1);
                }
            }

            return(new CompletionList(completionItems));
        }
        public override async Task <LocationOrLocationLinks> Handle(DefinitionParams request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            SymbolReference foundSymbol =
                SymbolsService.FindSymbolAtLocation(
                    scriptFile,
                    request.Position.Line + 1,
                    request.Position.Character + 1);

            List <LocationOrLocationLink> definitionLocations = new List <LocationOrLocationLink>();

            if (foundSymbol != null)
            {
                SymbolReference foundDefinition = await _symbolsService.GetDefinitionOfSymbolAsync(
                    scriptFile,
                    foundSymbol).ConfigureAwait(false);

                if (foundDefinition != null)
                {
                    definitionLocations.Add(
                        new LocationOrLocationLink(
                            new Location
                    {
                        Uri   = DocumentUri.From(foundDefinition.FilePath),
                        Range = GetRangeFromScriptRegion(foundDefinition.ScriptRegion)
                    }));
                }
            }

            return(new LocationOrLocationLinks(definitionLocations));
        }
예제 #7
0
        public override Task <LocationContainer> Handle(ReferenceParams request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            SymbolReference foundSymbol =
                _symbolsService.FindSymbolAtLocation(
                    scriptFile,
                    request.Position.Line + 1,
                    request.Position.Character + 1);

            List <SymbolReference> referencesResult =
                _symbolsService.FindReferencesOfSymbol(
                    foundSymbol,
                    _workspaceService.ExpandScriptReferences(scriptFile),
                    _workspaceService);

            var locations = new List <Location>();

            if (referencesResult != null)
            {
                foreach (SymbolReference foundReference in referencesResult)
                {
                    locations.Add(new Location
                    {
                        Uri   = DocumentUri.From(foundReference.FilePath),
                        Range = GetRangeFromScriptRegion(foundReference.ScriptRegion)
                    });
                }
            }

            return(Task.FromResult(new LocationContainer(locations)));
        }
        public Task <Unit> Handle(DidChangeTextDocumentParams notification, CancellationToken token)
        {
            ScriptFile changedFile = _workspaceService.GetFile(notification.TextDocument.Uri.ToString());

            // A text change notification can batch multiple change requests
            foreach (TextDocumentContentChangeEvent textChange in notification.ContentChanges)
            {
                changedFile.ApplyChange(
                    GetFileChangeDetails(
                        textChange.Range,
                        textChange.Text));
            }

            // TODO: Get all recently edited files in the workspace
            _analysisService.RunScriptDiagnosticsAsync(new ScriptFile[] { changedFile });
            return(Unit.Task);
        }
예제 #9
0
        public async Task <TextEditContainer> Handle(DocumentFormattingParams request, CancellationToken cancellationToken)
        {
            var scriptFile   = _workspaceService.GetFile(request.TextDocument.Uri);
            var pssaSettings = _configurationService.CurrentSettings.CodeFormatting.GetPSSASettingsHashtable(
                (int)request.Options.TabSize,
                request.Options.InsertSpaces,
                _logger);


            // TODO raise an error event in case format returns null
            string formattedScript;
            Range  editRange;
            var    extent = scriptFile.ScriptAst.Extent;

            // todo create an extension for converting range to script extent
            editRange = new Range
            {
                Start = new Position
                {
                    Line      = extent.StartLineNumber - 1,
                    Character = extent.StartColumnNumber - 1
                },
                End = new Position
                {
                    Line      = extent.EndLineNumber - 1,
                    Character = extent.EndColumnNumber - 1
                }
            };

            formattedScript = await _analysisService.FormatAsync(
                scriptFile.Contents,
                pssaSettings,
                null).ConfigureAwait(false);

            formattedScript = formattedScript ?? scriptFile.Contents;

            return(new TextEditContainer(new TextEdit
            {
                NewText = formattedScript,
                Range = editRange
            }));
        }
        protected override Task Tokenize(SemanticTokensBuilder builder, ITextDocumentIdentifierParams identifier,
                                         CancellationToken cancellationToken)
        {
            ScriptFile file = _workspaceService.GetFile(identifier.TextDocument.Uri);

            foreach (Token token in file.ScriptTokens)
            {
                PushToken(token, builder);
            }
            return(Task.CompletedTask);
        }
        public Task <Unit> Handle(DidChangeTextDocumentParams notification, CancellationToken token)
        {
            ScriptFile changedFile = _workspaceService.GetFile(notification.TextDocument.Uri);

            // A text change notification can batch multiple change requests
            foreach (TextDocumentContentChangeEvent textChange in notification.ContentChanges)
            {
                changedFile.ApplyChange(
                    GetFileChangeDetails(
                        textChange.Range,
                        textChange.Text));
            }

#pragma warning disable CS4014
            // Kick off script diagnostics without blocking the response
            // TODO: Get all recently edited files in the workspace
            _analysisService.RunScriptDiagnosticsAsync(new ScriptFile[] { changedFile });
#pragma warning restore CS4014
            return(Unit.Task);
        }
        private async Task LaunchScriptAsync(string scriptToLaunch)
        {
            // Is this an untitled script?
            if (ScriptFile.IsUntitledPath(scriptToLaunch))
            {
                ScriptFile untitledScript = _workspaceService.GetFile(scriptToLaunch);

                if (BreakpointApiUtils.SupportsBreakpointApis)
                {
                    // Parse untitled files with their `Untitled:` URI as the file name which will cache the URI & contents within the PowerShell parser.
                    // By doing this, we light up the ability to debug Untitled files with breakpoints.
                    // This is only possible via the direct usage of the breakpoint APIs in PowerShell because
                    // Set-PSBreakpoint validates that paths are actually on the filesystem.
                    ScriptBlockAst ast = Parser.ParseInput(untitledScript.Contents, untitledScript.DocumentUri, out Token[] tokens, out ParseError[] errors);
        public override async Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken)
        {
            int cursorLine   = request.Position.Line + 1;
            int cursorColumn = request.Position.Character + 1;

            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);
            IEnumerable <CompletionItem> completionResults = await GetCompletionsInFileAsync(
                scriptFile,
                cursorLine,
                cursorColumn,
                cancellationToken).ConfigureAwait(false);

            return(new CompletionList(completionResults));
        }
        public async Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken)
        {
            int cursorLine   = request.Position.Line + 1;
            int cursorColumn = request.Position.Character + 1;

            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            try
            {
                await _completionLock.WaitAsync(cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                _logger.LogDebug("Completion request canceled for file: {0}", request.TextDocument.Uri);
                return(Array.Empty <CompletionItem>());
            }

            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    _logger.LogDebug("Completion request canceled for file: {0}", request.TextDocument.Uri);
                    return(Array.Empty <CompletionItem>());
                }

                CompletionResults completionResults =
                    await GetCompletionsInFileAsync(
                        scriptFile,
                        cursorLine,
                        cursorColumn).ConfigureAwait(false);

                if (completionResults == null)
                {
                    return(Array.Empty <CompletionItem>());
                }

                CompletionItem[] completionItems = new CompletionItem[completionResults.Completions.Length];
                for (int i = 0; i < completionItems.Length; i++)
                {
                    completionItems[i] = CreateCompletionItem(completionResults.Completions[i], completionResults.ReplacedRange, i + 1);
                }

                return(completionItems);
            }
            finally
            {
                _completionLock.Release();
            }
        }
예제 #15
0
        public async Task <SignatureHelp> Handle(SignatureHelpParams request, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                _logger.LogDebug("SignatureHelp request canceled for file: {0}", request.TextDocument.Uri);
                return(new SignatureHelp());
            }

            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            ParameterSetSignatures parameterSets =
                await _symbolsService.FindParameterSetsInFileAsync(
                    scriptFile,
                    (int)request.Position.Line + 1,
                    (int)request.Position.Character + 1,
                    _powerShellContextService).ConfigureAwait(false);

            if (parameterSets == null)
            {
                return(new SignatureHelp());
            }

            var signatures = new SignatureInformation[parameterSets.Signatures.Length];

            for (int i = 0; i < signatures.Length; i++)
            {
                var parameters = new List <ParameterInformation>();
                foreach (ParameterInfo param in parameterSets.Signatures[i].Parameters)
                {
                    parameters.Add(CreateParameterInfo(param));
                }

                signatures[i] = new SignatureInformation
                {
                    Label         = parameterSets.CommandName + " " + parameterSets.Signatures[i].SignatureText,
                    Documentation = null,
                    Parameters    = parameters,
                };
            }

            return(new SignatureHelp
            {
                Signatures = signatures,
                ActiveParameter = null,
                ActiveSignature = 0
            });
        }
        private async Task LaunchScriptAsync(string scriptToLaunch)
        {
            // Is this an untitled script?
            if (ScriptFile.IsUntitledPath(scriptToLaunch))
            {
                ScriptFile untitledScript = _workspaceService.GetFile(scriptToLaunch);

                await _powerShellContextService
                .ExecuteScriptStringAsync(untitledScript.Contents, true, true);
            }
            else
            {
                await _powerShellContextService
                .ExecuteScriptWithArgsAsync(scriptToLaunch, _debugStateService.Arguments, writeInputToHost : true);
            }

            _jsonRpcServer.SendNotification(EventNames.Terminated);
        }
        public async Task <SignatureHelp> Handle(SignatureHelpParams request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile =
                _workspaceService.GetFile(
                    request.TextDocument.Uri.ToString());

            ParameterSetSignatures parameterSets =
                await _symbolsService.FindParameterSetsInFileAsync(
                    scriptFile,
                    (int)request.Position.Line + 1,
                    (int)request.Position.Character + 1,
                    _powerShellContextService);

            SignatureInformation[] signatures = s_emptySignatureResult;

            if (parameterSets != null)
            {
                signatures = new SignatureInformation[parameterSets.Signatures.Length];
                for (int i = 0; i < signatures.Length; i++)
                {
                    var parameters = new ParameterInformation[parameterSets.Signatures[i].Parameters.Count()];
                    int j          = 0;
                    foreach (ParameterInfo param in parameterSets.Signatures[i].Parameters)
                    {
                        parameters[j] = CreateParameterInfo(param);
                        j++;
                    }

                    signatures[i] = new SignatureInformation
                    {
                        Label         = parameterSets.CommandName + " " + parameterSets.Signatures[i].SignatureText,
                        Documentation = null,
                        Parameters    = parameters,
                    };
                }
            }

            return(new SignatureHelp
            {
                Signatures = signatures,
                ActiveParameter = null,
                ActiveSignature = 0
            });
        }
        public Task <SymbolInformationOrDocumentSymbolContainer> Handle(DocumentSymbolParams request, CancellationToken cancellationToken)
        {
            ScriptFile scriptFile =
                _workspaceService.GetFile(
                    request.TextDocument.Uri.ToString());

            IEnumerable <SymbolReference> foundSymbols =
                this.ProvideDocumentSymbols(scriptFile);

            SymbolInformationOrDocumentSymbol[] symbols = null;

            string containerName = Path.GetFileNameWithoutExtension(scriptFile.FilePath);

            if (foundSymbols != null)
            {
                symbols =
                    foundSymbols
                    .Select(r =>
                {
                    return(new SymbolInformationOrDocumentSymbol(new SymbolInformation
                    {
                        ContainerName = containerName,
                        Kind = GetSymbolKind(r.SymbolType),
                        Location = new Location
                        {
                            Uri = PathUtils.ToUri(r.FilePath),
                            Range = GetRangeFromScriptRegion(r.ScriptRegion)
                        },
                        Name = GetDecoratedSymbolName(r)
                    }));
                })
                    .ToArray();
            }
            else
            {
                symbols = new SymbolInformationOrDocumentSymbol[0];
            }


            return(Task.FromResult(new SymbolInformationOrDocumentSymbolContainer(symbols)));
        }
        public override async Task <Hover> Handle(HoverParams request, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                _logger.LogDebug("Hover request canceled for file: {0}", request.TextDocument.Uri);
                return(null);
            }

            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            SymbolDetails symbolDetails =
                await _symbolsService.FindSymbolDetailsAtLocationAsync(
                    scriptFile,
                    request.Position.Line + 1,
                    request.Position.Character + 1).ConfigureAwait(false);

            if (symbolDetails == null)
            {
                return(null);
            }

            List <MarkedString> symbolInfo = new List <MarkedString>();

            symbolInfo.Add(new MarkedString("PowerShell", symbolDetails.DisplayString));

            if (!string.IsNullOrEmpty(symbolDetails.Documentation))
            {
                symbolInfo.Add(new MarkedString("markdown", symbolDetails.Documentation));
            }

            Range symbolRange = GetRangeFromScriptRegion(symbolDetails.SymbolReference.ScriptRegion);

            return(new Hover
            {
                Contents = new MarkedStringsOrMarkupContent(symbolInfo),
                Range = symbolRange
            });
        }
예제 #20
0
        public async Task <CommandOrCodeActionContainer> Handle(CodeActionParams request, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Array.Empty <CommandOrCodeAction>());
            }

            // On Windows, VSCode still gives us file URIs like "file:///c%3a/...", so we need to escape them
            IReadOnlyDictionary <string, MarkerCorrection> corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync(
                _workspaceService.GetFile(request.TextDocument.Uri)).ConfigureAwait(false);

            if (corrections == null)
            {
                return(Array.Empty <CommandOrCodeAction>());
            }

            var codeActions = new List <CommandOrCodeAction>();

            // If there are any code fixes, send these commands first so they appear at top of "Code Fix" menu in the client UI.
            foreach (Diagnostic diagnostic in request.Context.Diagnostics)
            {
                if (string.IsNullOrEmpty(diagnostic.Code.String))
                {
                    _logger.LogWarning(
                        $"textDocument/codeAction skipping diagnostic with empty Code field: {diagnostic.Source} {diagnostic.Message}");

                    continue;
                }

                string diagnosticId = AnalysisService.GetUniqueIdFromDiagnostic(diagnostic);
                if (corrections.TryGetValue(diagnosticId, out MarkerCorrection correction))
                {
                    codeActions.Add(new CodeAction
                    {
                        Title = correction.Name,
                        Kind  = CodeActionKind.QuickFix,
                        Edit  = new WorkspaceEdit
                        {
                            DocumentChanges = new Container <WorkspaceEditDocumentChange>(
                                new WorkspaceEditDocumentChange(
                                    new TextDocumentEdit
                            {
                                TextDocument = new VersionedTextDocumentIdentifier
                                {
                                    Uri = request.TextDocument.Uri
                                },
                                Edits = new TextEditContainer(correction.Edits.Select(ScriptRegion.ToTextEdit))
                            }))
                        }
                    });
                }
            }

            // Add "show documentation" commands last so they appear at the bottom of the client UI.
            // These commands do not require code fixes. Sometimes we get a batch of diagnostics
            // to create commands for. No need to create multiple show doc commands for the same rule.
            var ruleNamesProcessed = new HashSet <string>();

            foreach (Diagnostic diagnostic in request.Context.Diagnostics)
            {
                if (!diagnostic.Code.IsString || string.IsNullOrEmpty(diagnostic.Code.String))
                {
                    continue;
                }

                if (string.Equals(diagnostic.Source, "PSScriptAnalyzer", StringComparison.OrdinalIgnoreCase) &&
                    !ruleNamesProcessed.Contains(diagnostic.Code.String))
                {
                    ruleNamesProcessed.Add(diagnostic.Code.String);
                    var title = $"Show documentation for: {diagnostic.Code.String}";
                    codeActions.Add(new CodeAction
                    {
                        Title = title,
                        // This doesn't fix anything, but I'm adding it here so that it shows up in VS Code's
                        // Quick fix UI. The VS Code team is working on a way to support documentation CodeAction's better
                        // but this is good for now until that's ready.
                        Kind    = CodeActionKind.QuickFix,
                        Command = new Command
                        {
                            Title     = title,
                            Name      = "PowerShell.ShowCodeActionDocumentation",
                            Arguments = JArray.FromObject(new[] { diagnostic.Code.String })
                        }
                    });
                }
            }

            return(codeActions);
        }
 private ScriptFile GetScriptFile(ScriptRegion scriptRegion) => workspace.GetFile(TestUtilities.GetSharedPath(scriptRegion.File));