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)); } }
public Document GetDocument(ITextSnapshot snapshot, CancellationToken cancellationToken) { _threadingContext.ThrowIfNotOnBackgroundThread(); return(snapshot.AsText().GetDocumentWithFrozenPartialSemantics(cancellationToken)); }