private async Task <TriggerIdentifierKind> DetermineIfRenamableIdentifierAsync(SnapshotSpan snapshotSpan, bool initialCheck)
            {
                _threadingContext.ThrowIfNotOnBackgroundThread();
                var document = snapshotSpan.Snapshot.GetOpenDocumentInCurrentContextWithChanges();

                if (document != null)
                {
                    var syntaxFactsService = document.GetLanguageService <ISyntaxFactsService>();
                    var syntaxTree         = await document.GetSyntaxTreeAsync(_cancellationToken).ConfigureAwait(false);

                    var token = await syntaxTree.GetTouchingWordAsync(snapshotSpan.Start.Position, syntaxFactsService, _cancellationToken).ConfigureAwait(false);

                    // The OriginalName is determined with a simple textual check, so for a
                    // statement such as "Dim [x = 1" the textual check will return a name of "[x".
                    // The token found for "[x" is an identifier token, but only due to error
                    // recovery (the "[x" is actually in the trailing trivia). If the OriginalName
                    // found through the textual check has a different length than the span of the
                    // touching word, then we cannot perform a rename.
                    if (initialCheck && token.Span.Length != this.OriginalName.Length)
                    {
                        return(TriggerIdentifierKind.NotRenamable);
                    }

                    var languageHeuristicsService = document.GetLanguageService <IRenameTrackingLanguageHeuristicsService>();
                    if (syntaxFactsService.IsIdentifier(token) && languageHeuristicsService.IsIdentifierValidForRenameTracking(token.Text))
                    {
                        var semanticModel = await document.ReuseExistingSpeculativeModelAsync(token.Parent, _cancellationToken).ConfigureAwait(false);

                        var semanticFacts = document.GetLanguageService <ISemanticFactsService>();

                        var renameSymbolInfo = RenameUtilities.GetTokenRenameInfo(semanticFacts, semanticModel, token, _cancellationToken);
                        if (!renameSymbolInfo.HasSymbols)
                        {
                            return(TriggerIdentifierKind.NotRenamable);
                        }

                        if (renameSymbolInfo.IsMemberGroup)
                        {
                            // This is a reference from a nameof expression. Allow the rename but set the RenameOverloads option
                            _forceRenameOverloads = true;

                            return(await DetermineIfRenamableSymbolsAsync(renameSymbolInfo.Symbols, document).ConfigureAwait(false));
                        }
                        else
                        {
                            // We do not yet support renaming (inline rename or rename tracking) on
                            // named tuple elements.
                            if (renameSymbolInfo.Symbols.Single().ContainingType?.IsTupleType() == true)
                            {
                                return(TriggerIdentifierKind.NotRenamable);
                            }

                            return(await DetermineIfRenamableSymbolAsync(renameSymbolInfo.Symbols.Single(), document, token).ConfigureAwait(false));
                        }
                    }
                }

                return(TriggerIdentifierKind.NotRenamable);
            }
            private async Task <string> DetermineIfEventHookupAndGetHandlerNameAsync(Document document, int position, CancellationToken cancellationToken)
            {
                _threadingContext.ThrowIfNotOnBackgroundThread();

                // For test purposes only!
                if (TESTSessionHookupMutex != null)
                {
                    TESTSessionHookupMutex.WaitOne();
                    TESTSessionHookupMutex.ReleaseMutex();
                }

                using (Logger.LogBlock(FunctionId.EventHookup_Determine_If_Event_Hookup, cancellationToken))
                {
                    var plusEqualsToken = await GetPlusEqualsTokenInsideAddAssignExpressionAsync(document, position, cancellationToken).ConfigureAwait(false);

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

                    var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                    var eventSymbol = GetEventSymbol(semanticModel, plusEqualsToken.Value, cancellationToken);
                    if (eventSymbol == null)
                    {
                        return(null);
                    }

                    var namingRule = await document.GetApplicableNamingRuleAsync(
                        new SymbolKindOrTypeKind(MethodKind.Ordinary),
                        new DeclarationModifiers(isStatic : plusEqualsToken.Value.Parent.IsInStaticContext()),
                        Accessibility.Private, cancellationToken).ConfigureAwait(false);

                    return(GetEventHandlerName(
                               eventSymbol, plusEqualsToken.Value, semanticModel,
                               document.GetLanguageService <ISyntaxFactsService>(), namingRule));
                }
            }
Пример #3
0
 public Document GetDocument(ITextSnapshot snapshot, CancellationToken cancellationToken)
 {
     _threadingContext.ThrowIfNotOnBackgroundThread();
     return(snapshot.AsText().GetDocumentWithFrozenPartialSemantics(cancellationToken));
 }