protected override AbstractIndenter GetIndenter(
     ISyntaxFactsService syntaxFacts, SyntaxTree syntaxTree, TextLine lineToBeIndented, IEnumerable<IFormattingRule> formattingRules, OptionSet optionSet, CancellationToken cancellationToken)
 {
     return new Indenter(
         syntaxFacts, syntaxTree, formattingRules,
         optionSet, lineToBeIndented, cancellationToken);
 }
 public GenerateTypeOptionsResult GetGenerateTypeOptions(
     string className,
     GenerateTypeDialogOptions generateTypeDialogOptions,
     Document document,
     INotificationService notificationService,
     IProjectManagementService projectManagementService,
     ISyntaxFactsService syntaxFactsService)
 {
     // Storing the actual values
     ClassName = className;
     GenerateTypeDialogOptions = generateTypeDialogOptions;
     if (DefaultNamespace == null)
     {
         DefaultNamespace = projectManagementService.GetDefaultNamespace(Project, Project?.Solution.Workspace);
     }
     return new GenerateTypeOptionsResult(
         accessibility: Accessibility,
         typeKind: TypeKind,
         typeName: TypeName,
         project: Project,
         isNewFile: IsNewFile,
         newFileName: NewFileName,
         folders: Folders,
         fullFilePath: FullFilePath,
         existingDocument: ExistingDocument,
         areFoldersValidIdentifiers: AreFoldersValidIdentifiers,
         defaultNamespace: DefaultNamespace,
         isCancelled: IsCancelled);
 }
        public override SignatureHelpState GetCurrentArgumentState(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken)
        {
            if (GetOuterMostTupleExpressionInSpan(root, position, syntaxFacts, currentSpan, cancellationToken, out var expression))
            {
                return CommonSignatureHelpUtilities.GetSignatureHelpState(expression, position,
                   getOpenToken: s_getOpenToken,
                   getCloseToken: s_getCloseToken,
                   getArgumentsWithSeparators: s_getArgumentsWithSeparators,
                   getArgumentNames: s_getArgumentNames);
            }

            if (GetOuterMostParenthesizedExpressionInSpan(root, position, syntaxFacts, currentSpan, cancellationToken, out var parenthesizedExpression))
            {
                if (currentSpan.Start == parenthesizedExpression.SpanStart)
                {
                    return new SignatureHelpState(
                        argumentIndex: 0,
                        argumentCount: 0,
                        argumentName: string.Empty,
                        argumentNames: null);
                }
            }

            return null;
        }
 protected static bool TryGetNameWithoutAttributeSuffix(
     string name,
     ISyntaxFactsService syntaxFacts,
     out string result)
 {
     return name.TryGetWithoutAttributeSuffix(syntaxFacts.IsCaseSensitive, out result);
 }
            public AbstractIndenter(
                ISyntaxFactsService syntaxFacts,
                SyntaxTree syntaxTree,
                IEnumerable<IFormattingRule> rules,
                OptionSet optionSet,
                TextLine lineToBeIndented,
                CancellationToken cancellationToken)
            {
                var syntaxRoot = syntaxTree.GetRoot(cancellationToken);

                this._syntaxFacts = syntaxFacts;
                this.OptionSet = optionSet;
                this.Tree = syntaxTree;
                this.LineToBeIndented = lineToBeIndented;
                this.TabSize = this.OptionSet.GetOption(FormattingOptions.TabSize, syntaxRoot.Language);
                this.CancellationToken = cancellationToken;

                this.Rules = rules;
                this.Finder = new BottomUpBaseIndentationFinder(
                         new ChainedFormattingRules(this.Rules, OptionSet),
                         this.TabSize,
                         this.OptionSet.GetOption(FormattingOptions.IndentationSize, syntaxRoot.Language),
                         tokenStream: null,
                         lastToken: default(SyntaxToken));
            }
        private bool TryGetConstructorInitializer(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, SignatureHelpTriggerReason triggerReason, CancellationToken cancellationToken, out ConstructorInitializerSyntax expression)
        {
            if (!CommonSignatureHelpUtilities.TryGetSyntax(root, position, syntaxFacts, triggerReason, IsTriggerToken, IsArgumentListToken, cancellationToken, out expression))
            {
                return false;
            }

            return expression.ArgumentList != null;
        }
 protected AbstractTokenBraceCompletionSession(
     ISyntaxFactsService syntaxFactsService,
     int openingTokenKind,
     int closingTokenKind)
 {
     _syntaxFactsService = syntaxFactsService;
     this.OpeningTokenKind = openingTokenKind;
     this.ClosingTokenKind = closingTokenKind;
 }
        private bool TryGetAttributeExpression(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, SignatureHelpTriggerReason triggerReason, CancellationToken cancellationToken, out AttributeSyntax attribute)
        {
            if (!CommonSignatureHelpUtilities.TryGetSyntax(root, position, syntaxFacts, triggerReason, IsTriggerToken, IsArgumentListToken, cancellationToken, out attribute))
            {
                return false;
            }

            return attribute.ArgumentList != null;
        }
示例#9
0
 /// <summary>
 /// Returns the identifier, keyword, contextual keyword or preprocessor keyword touching this
 /// position, or a token of Kind = None if the caret is not touching either.
 /// </summary>
 public static Task<SyntaxToken> GetTouchingWordAsync(
     this SyntaxTree syntaxTree,
     int position,
     ISyntaxFactsService syntaxFacts,
     CancellationToken cancellationToken,
     bool findInsideTrivia = false)
 {
     return GetTouchingTokenAsync(syntaxTree, position, syntaxFacts.IsWord, cancellationToken, findInsideTrivia);
 }
 private SymbolMapBuilder(
     ISyntaxFactsService service,
     SemanticModel semanticModel,
     TextSpan span,
     CancellationToken cancellationToken)
     : base(SyntaxWalkerDepth.Token)
 {
     _semanticModel = semanticModel;
     _service = service;
     _span = span;
     _symbolMap = new Dictionary<ISymbol, List<SyntaxToken>>();
     _cancellationToken = cancellationToken;
 }
            public GenerateTypeOptionsResult GetGenerateTypeOptions(
                string typeName,
                GenerateTypeDialogOptions generateTypeDialogOptions,
                Document document,
                INotificationService notificationService,
                IProjectManagementService projectManagementService,
                ISyntaxFactsService syntaxFactsService)
            {
                var viewModel = new GenerateTypeDialogViewModel(
                    document,
                    notificationService,
                    projectManagementService,
                    syntaxFactsService,
                    _generatedCodeService,
                    generateTypeDialogOptions,
                    typeName,
                    document.Project.Language == LanguageNames.CSharp ? ".cs" : ".vb",
                    _isNewFile,
                    _accessSelectString,
                    _typeKindSelectString);

                var dialog = new GenerateTypeDialog(viewModel);
                var result = dialog.ShowModal();

                if (result.HasValue && result.Value)
                {
                    // Retain choice
                    _isNewFile = viewModel.IsNewFile;
                    _accessSelectString = viewModel.SelectedAccessibilityString;
                    _typeKindSelectString = viewModel.SelectedTypeKindString;

                    var defaultNamespace = projectManagementService.GetDefaultNamespace(viewModel.SelectedProject, viewModel.SelectedProject?.Solution.Workspace);

                    return new GenerateTypeOptionsResult(
                        accessibility: viewModel.SelectedAccessibility,
                        typeKind: viewModel.SelectedTypeKind,
                        typeName: viewModel.TypeName,
                        project: viewModel.SelectedProject,
                        isNewFile: viewModel.IsNewFile,
                        newFileName: viewModel.FileName.Trim(),
                        folders: viewModel.Folders,
                        fullFilePath: viewModel.FullFilePath,
                        existingDocument: viewModel.SelectedDocument,
                        defaultNamespace: defaultNamespace,
                        areFoldersValidIdentifiers: viewModel.AreFoldersValidIdentifiers);
                }
                else
                {
                    return GenerateTypeOptionsResult.Cancelled;
                }
            }
示例#12
0
        public static IEnumerable<SyntaxToken> GetIdentifierOrGlobalNamespaceTokensWithText(
            ISyntaxFactsService syntaxFacts, Document document, VersionStamp version, SemanticModel model, SyntaxNode root, SourceText sourceText,
            string text, CancellationToken cancellationToken)
        {
            var normalized = syntaxFacts.IsCaseSensitive ? text : text.ToLowerInvariant();

            var entry = GetCachedEntry(model);
            if (entry == null)
            {
                return GetIdentifierOrGlobalNamespaceTokensWithText(syntaxFacts, document, version, root, sourceText, normalized, cancellationToken);
            }

            return entry.IdentifierCache.GetOrAdd(normalized, key => GetIdentifierOrGlobalNamespaceTokensWithText(syntaxFacts, document, version, root, sourceText, key, cancellationToken));
        }
        public override SignatureHelpState GetCurrentArgumentState(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken)
        {
            if (TryGetObjectCreationExpression(
                    root,
                    position,
                    syntaxFacts,
                    SignatureHelpTriggerReason.InvokeSignatureHelpCommand,
                    cancellationToken,
                    out var expression) &&
                currentSpan.Start == SignatureHelpUtilities.GetSignatureHelpSpan(expression.ArgumentList).Start)
            {
                return SignatureHelpUtilities.GetSignatureHelpState(expression.ArgumentList, position);
            }

            return null;
        }
                public static Dictionary<ISymbol, List<SyntaxToken>> Build(
                    ISyntaxFactsService service,
                    SemanticModel semanticModel,
                    SyntaxNode root,
                    TextSpan span,
                    CancellationToken cancellationToken)
                {
                    Contract.ThrowIfNull(semanticModel);
                    Contract.ThrowIfNull(service);
                    Contract.ThrowIfNull(root);

                    var builder = new SymbolMapBuilder(service, semanticModel, span, cancellationToken);
                    builder.Visit(root);

                    return builder._symbolMap;
                }
 public ExtractInterfaceOptionsResult GetExtractInterfaceOptions(ISyntaxFactsService syntaxFactsService,
     INotificationService notificationService, List<ISymbol> extractableMembers, string defaultInterfaceName,
     List<string> conflictingTypeNames, string defaultNamespace, string generatedNameTypeParameterSuffix, string languageName)
 {
     var viewModel = new ExtractInterfaceDialogViewModel(syntaxFactsService, defaultInterfaceName, extractableMembers, conflictingTypeNames, defaultNamespace, generatedNameTypeParameterSuffix, languageName, languageName == LanguageNames.CSharp ? ".cs" : ".vb");
     var dialog = new ExtractInterfaceDialog(viewModel);
     dialog.SetOwnerToActive();
     var options = dialog.ShowDialog() == true
         ? new ExtractInterfaceOptionsResult(
             isCancelled: false,
             includedMembers: viewModel.MemberContainers.Where(c => c.IsChecked).Select(c => c.MemberSymbol),
             interfaceName: viewModel.InterfaceName.Trim(),
             fileName: viewModel.FileName.Trim())
         : ExtractInterfaceOptionsResult.Cancelled;
     return options;
 }
示例#16
0
        private static ImmutableArray<SyntaxToken> GetIdentifierOrGlobalNamespaceTokensWithText(
            ISyntaxFactsService syntaxFacts, Document document, VersionStamp version, SyntaxNode root, SourceText sourceText,
            string text, CancellationToken cancellationToken)
        {
            Func<SyntaxToken, bool> candidate = t =>
                syntaxFacts.IsGlobalNamespaceKeyword(t) || (syntaxFacts.IsIdentifier(t) && syntaxFacts.TextMatch(t.ValueText, text));

            // identifier is not escaped
            if (sourceText != null)
            {
                return GetTokensFromText(syntaxFacts, document, version, root, sourceText, text, candidate, cancellationToken);
            }

            // identifier is escaped
            return root.DescendantTokens(descendIntoTrivia: true).Where(candidate).ToImmutableArray();
        }
        private bool GetOuterMostParenthesizedExpressionInSpan(SyntaxNode root, int position,
         ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken, out ParenthesizedExpressionSyntax result)
        {
            result = null;
            while (TryGetParenthesizedExpression(SignatureHelpTriggerReason.InvokeSignatureHelpCommand,
                root, position, syntaxFacts, cancellationToken, out var expression))
            {
                if (!currentSpan.Contains(expression.Span))
                {
                    break;
                }

                result = expression;
                position = expression.SpanStart;
            }

            return result != null;
        }
        protected virtual bool TryGetGenericIdentifier(
            SyntaxNode root, int position,
            ISyntaxFactsService syntaxFacts,
            SignatureHelpTriggerReason triggerReason,
            CancellationToken cancellationToken,
            out SyntaxToken genericIdentifier, out SyntaxToken lessThanToken)
        {
            if (CommonSignatureHelpUtilities.TryGetSyntax(root, position, syntaxFacts, triggerReason, IsTriggerToken, IsArgumentListToken, cancellationToken, out GenericNameSyntax name))
            {
                genericIdentifier = name.Identifier;
                lessThanToken = name.TypeArgumentList.LessThanToken;
                return true;
            }

            genericIdentifier = default(SyntaxToken);
            lessThanToken = default(SyntaxToken);
            return false;
        }
示例#19
0
        public static IEnumerable<SyntaxToken> GetConstructorInitializerTokens(
            ISyntaxFactsService syntaxFacts, SemanticModel model, SyntaxNode root, CancellationToken cancellationToken)
        {
            // this one will only get called when we know given document contains constructor initializer.
            // no reason to use text to check whether it exist first.
            var entry = GetCachedEntry(model);
            if (entry == null)
            {
                return GetConstructorInitializerTokens(syntaxFacts, root, cancellationToken);
            }

            if (entry.ConstructorInitializerCache == null)
            {
                var initializers = GetConstructorInitializerTokens(syntaxFacts, root, cancellationToken);
                Interlocked.CompareExchange(ref entry.ConstructorInitializerCache, initializers, null);
            }

            return entry.ConstructorInitializerCache;
        }
        public ExtractInterfaceOptionsResult GetExtractInterfaceOptions(
            ISyntaxFactsService syntaxFactsService,
            INotificationService notificationService,
            List<ISymbol> extractableMembers,
            string defaultInterfaceName,
            List<string> allTypeNames,
            string defaultNamespace,
            string generatedNameTypeParameterSuffix,
            string languageName)
        {
            var viewModel = new ExtractInterfaceDialogViewModel(
                syntaxFactsService,
                _glyphService,
                notificationService,
                defaultInterfaceName,
                extractableMembers,
                allTypeNames,
                defaultNamespace,
                generatedNameTypeParameterSuffix,
                languageName,
                languageName == LanguageNames.CSharp ? ".cs" : ".vb");

            var dialog = new ExtractInterfaceDialog(viewModel);
            var result = dialog.ShowModal();

            if (result.HasValue && result.Value)
            {
                return new ExtractInterfaceOptionsResult(
                    isCancelled: false,
                    includedMembers: viewModel.MemberContainers.Where(c => c.IsChecked).Select(c => c.MemberSymbol),
                    interfaceName: viewModel.InterfaceName.Trim(),
                    fileName: viewModel.FileName.Trim());
            }
            else
            {
                return ExtractInterfaceOptionsResult.Cancelled;
            }
        }
        public ExtractInterfaceOptionsResult GetExtractInterfaceOptions(
            ISyntaxFactsService syntaxFactsService,
            INotificationService notificationService,
            List<ISymbol> extractableMembers,
            string defaultInterfaceName,
            List<string> conflictingTypeNames,
            string defaultNamespace,
            string generatedNameTypeParameterSuffix,
            string languageName)
        {
            this.AllExtractableMembers = extractableMembers;
            this.DefaultInterfaceName = defaultInterfaceName;
            this.ConflictingTypeNames = conflictingTypeNames;
            this.DefaultNamespace = defaultNamespace;
            this.GeneratedNameTypeParameterSuffix = generatedNameTypeParameterSuffix;

            return IsCancelled
                ? ExtractInterfaceOptionsResult.Cancelled
                : new ExtractInterfaceOptionsResult(
                    isCancelled: false,
                    includedMembers: ChosenMembers ?? AllExtractableMembers,
                    interfaceName: ChosenInterfaceName ?? defaultInterfaceName,
                    fileName: ChosenFileName ?? defaultInterfaceName);
        }
        internal ExtractInterfaceDialogViewModel(
            ISyntaxFactsService syntaxFactsService,
            IGlyphService glyphService,
            INotificationService notificationService,
            string defaultInterfaceName,
            List<ISymbol> extractableMembers,
            List<string> conflictingTypeNames,
            string defaultNamespace,
            string generatedNameTypeParameterSuffix,
            string languageName,
            string fileExtension)
        {
            _syntaxFactsService = syntaxFactsService;
            _notificationService = notificationService;
            _interfaceName = defaultInterfaceName;
            _conflictingTypeNames = conflictingTypeNames;
            _fileExtension = fileExtension;
            _fileName = string.Format("{0}{1}", defaultInterfaceName, fileExtension);
            _defaultNamespace = defaultNamespace;
            _generatedNameTypeParameterSuffix = generatedNameTypeParameterSuffix;
            _languageName = languageName;

            MemberContainers = extractableMembers.Select(m => new MemberSymbolViewModel(m, glyphService)).OrderBy(s => s.MemberName).ToList();
        }
        private static void CalculateContext(SyntaxNode node, ISyntaxFactsService syntaxFacts, out string name, out int arity, out bool inAttributeContext, out bool hasIncompleteParentMember)
        {
            // Has to be a simple identifier or generic name.
            syntaxFacts.GetNameAndArityOfSimpleName(node, out name, out arity);

            inAttributeContext = syntaxFacts.IsAttributeName(node);
            hasIncompleteParentMember = syntaxFacts.HasIncompleteParentMember(node);
        }
 internal abstract bool IsViableField(IFieldSymbol field, SyntaxNode expression, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken);
 internal abstract bool IsViableProperty(IPropertySymbol property, SyntaxNode expression, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken);
        private static async Task <bool> CanBeMergedAsync(
            Document document,
            ISyntaxFactsService syntaxFacts,
            IIfLikeStatementGenerator ifGenerator,
            SyntaxNode outerIfOrElseIf,
            SyntaxNode innerIfStatement,
            CancellationToken cancellationToken)
        {
            // We can only merge this with the outer if statement if any inner else-if and else clauses are equal
            // to else-if and else clauses following the outer if statement because we'll be removing the inner ones.
            // Example of what we can merge:
            //    if (a)
            //    {
            //        if (b)
            //            Console.WriteLine();
            //        else
            //            Foo();
            //    }
            //    else
            //    {
            //        Foo();
            //    }
            if (!System.Linq.ImmutableArrayExtensions.SequenceEqual(
                    ifGenerator.GetElseIfAndElseClauses(outerIfOrElseIf),
                    ifGenerator.GetElseIfAndElseClauses(innerIfStatement),
                    (a, b) => IsElseIfOrElseClauseEquivalent(syntaxFacts, ifGenerator, a, b)))
            {
                return(false);
            }

            var statements = syntaxFacts.GetStatementContainerStatements(innerIfStatement.Parent);

            if (statements.Count == 1)
            {
                // There are no other statements below the inner if statement. Merging is OK.
                return(true);
            }
            else
            {
                // There are statements below the inner if statement. We can merge if
                // 1. there are equivalent statements below the outer 'if', and
                // 2. control flow can't reach the end of these statements (otherwise, it would continue
                //    below the outer 'if' and run the same statements twice).
                // This will typically look like a single return, break, continue or a throw statement.
                // The opposite refactoring (SplitIntoNestedIfStatements) never generates this but we support it anyway.

                // Example:
                //    if (a)
                //    {
                //        if (b)
                //            Console.WriteLine();
                //        return;
                //    }
                //    return;

                // If we have an else-if, get the topmost if statement.
                var outerIfStatement = ifGenerator.GetRootIfStatement(outerIfOrElseIf);

                // A statement should always be in a statement container, but we'll do a defensive check anyway so that
                // we don't crash if the helper is missing some cases or there's a new language feature it didn't account for.
                Debug.Assert(syntaxFacts.GetStatementContainer(outerIfStatement) is object);
                if (syntaxFacts.GetStatementContainer(outerIfStatement) is not {
                } container)
                {
                    return(false);
                }

                var outerStatements       = syntaxFacts.GetStatementContainerStatements(container);
                var outerIfStatementIndex = outerStatements.IndexOf(outerIfStatement);

                var remainingStatements      = statements.Skip(1);
                var remainingOuterStatements = outerStatements.Skip(outerIfStatementIndex + 1);

                if (!remainingStatements.SequenceEqual(remainingOuterStatements.Take(statements.Count - 1), syntaxFacts.AreEquivalent))
                {
                    return(false);
                }

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

                var controlFlow = semanticModel.AnalyzeControlFlow(statements[0], statements[statements.Count - 1]);

                return(!controlFlow.EndPointIsReachable);
            }
        }
示例#27
0
 protected static bool ParentIsSkippedTokensTriviaOrNull(ISyntaxFactsService syntaxFactsService, SyntaxToken token)
 => token.Parent == null || syntaxFactsService.IsSkippedTokensTrivia(token.Parent);
示例#28
0
 private IEnumerable <IGrouping <SyntaxNode, Diagnostic> > GetDiagnosticsGroupedByMember(
     ImmutableArray <Diagnostic> diagnostics,
     ISyntaxFactsService syntaxFacts,
     SyntaxNode root)
 => diagnostics.GroupBy(d => syntaxFacts.GetContainingMemberDeclaration(root, d.Location.SourceSpan.Start));
 protected AbstractDocumentationCommentService(ISyntaxFactsService syntaxFacts)
 {
     _syntaxFacts = syntaxFacts;
 }
示例#30
0
        protected override bool CanAddImportForMethod(Diagnostic diagnostic, ISyntaxFactsService syntaxFacts, ref SyntaxNode node)
        {
            switch (diagnostic.Id)
            {
            case CS1061:
                if (node.IsKind(SyntaxKind.ConditionalAccessExpression))
                {
                    node = (node as ConditionalAccessExpressionSyntax).WhenNotNull;
                }
                else if (node.IsKind(SyntaxKind.MemberBindingExpression))
                {
                    node = (node as MemberBindingExpressionSyntax).Name;
                }
                else if (node.Parent.IsKind(SyntaxKind.CollectionInitializerExpression))
                {
                    return(true);
                }

                break;

            case CS0122:
            case CS1501:
                if (node is SimpleNameSyntax)
                {
                    break;
                }
                else if (node is MemberBindingExpressionSyntax)
                {
                    node = (node as MemberBindingExpressionSyntax).Name;
                }
                break;

            case CS1929:
                var memberAccessName      = (node.Parent as MemberAccessExpressionSyntax)?.Name;
                var conditionalAccessName = (((node.Parent as ConditionalAccessExpressionSyntax)?.WhenNotNull as InvocationExpressionSyntax)?.Expression as MemberBindingExpressionSyntax)?.Name;
                if (memberAccessName == null && conditionalAccessName == null)
                {
                    return(false);
                }

                node = memberAccessName ?? conditionalAccessName;
                break;

            case CS1503:
                //// look up its corresponding method name
                var parent = node.GetAncestor <InvocationExpressionSyntax>();
                if (parent == null)
                {
                    return(false);
                }

                var method = parent.Expression as MemberAccessExpressionSyntax;
                if (method != null)
                {
                    node = method.Name;
                }

                break;

            default:
                return(false);
            }

            var simpleName = node as SimpleNameSyntax;

            if (!simpleName.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) &&
                !simpleName.IsParentKind(SyntaxKind.MemberBindingExpression))
            {
                return(false);
            }

            var memberAccess  = simpleName.Parent as MemberAccessExpressionSyntax;
            var memberBinding = simpleName.Parent as MemberBindingExpressionSyntax;

            if (memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) ||
                memberAccess.IsParentKind(SyntaxKind.ElementAccessExpression) ||
                memberBinding.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) ||
                memberBinding.IsParentKind(SyntaxKind.ElementAccessExpression))
            {
                return(false);
            }

            if (!syntaxFacts.IsMemberAccessExpressionName(node))
            {
                return(false);
            }

            return(true);
        }
 /// <summary>
 /// Try to get a new node to replace given node, which is a reference to a top-level type declared inside the
 /// namespce to be changed. If this reference is the right side of a qualified name, the new node returned would
 /// be the entire qualified name. Depends on whether <paramref name="newNamespaceParts"/> is provided, the name
 /// in the new node might be qualified with this new namespace instead.
 /// </summary>
 /// <param name="reference">A reference to a type declared inside the namespce to be changed, which is calculated
 /// based on results from `SymbolFinder.FindReferencesAsync`.</param>
 /// <param name="newNamespaceParts">If specified, the namespace of original reference will be replaced with given
 /// namespace in the replacement node.</param>
 /// <param name="old">The node to be replaced. This might be an ancestor of original </param>
 /// <param name="new">The replacement node.</param>
 public abstract bool TryGetReplacementReferenceSyntax(SyntaxNode reference, ImmutableArray <string> newNamespaceParts, ISyntaxFactsService syntaxFacts, out SyntaxNode old, out SyntaxNode @new);
        private static void MoveCaretToSemicolonPosition(
            TypeCharCommandArgs args,
            Document document,
            SyntaxNode root,
            SnapshotPoint caret,
            ISyntaxFactsService syntaxFacts,
            SyntaxNode currentNode,
            bool isInsideDelimiters,
            CancellationToken cancellationToken)
        {
            if (currentNode == null ||
                IsInAStringOrCharacter(currentNode, caret))
            {
                // Don't complete statement.  Return without moving the caret.
                return;
            }

            if (currentNode.IsKind(SyntaxKind.ArgumentList, SyntaxKind.ArrayRankSpecifier, SyntaxKind.BracketedArgumentList, SyntaxKind.ParenthesizedExpression, SyntaxKind.ParameterList))
            {
                // make sure the closing delimiter exists
                if (RequiredDelimiterIsMissing(currentNode))
                {
                    return;
                }

                // set caret to just outside the delimited span and analyze again
                // if caret was already in that position, return to avoid infinite loop
                var newCaretPosition = currentNode.Span.End;
                if (newCaretPosition == caret.Position)
                {
                    return;
                }

                var newCaret = args.SubjectBuffer.CurrentSnapshot.GetPoint(newCaretPosition);
                if (!TryGetStartingNode(root, newCaret, out currentNode, cancellationToken))
                {
                    return;
                }

                MoveCaretToSemicolonPosition(args, document, root, newCaret, syntaxFacts, currentNode,
                                             isInsideDelimiters: true, cancellationToken);
            }
            else if (currentNode.IsKind(SyntaxKind.DoStatement))
            {
                if (IsInConditionOfDoStatement(currentNode, caret))
                {
                    MoveCaretToFinalPositionInStatement(currentNode, args, caret, true);
                }
                return;
            }
            else if (syntaxFacts.IsStatement(currentNode) || currentNode.IsKind(SyntaxKind.FieldDeclaration, SyntaxKind.DelegateDeclaration))
            {
                MoveCaretToFinalPositionInStatement(currentNode, args, caret, isInsideDelimiters);
                return;
            }
            else
            {
                // keep caret the same, but continue analyzing with the parent of the current node
                currentNode = currentNode.Parent;
                MoveCaretToSemicolonPosition(args, document, root, caret, syntaxFacts, currentNode,
                                             isInsideDelimiters, cancellationToken);
                return;
            }
        }
示例#33
0
 public CharLiteralCompletionSession(ISyntaxFactsService syntaxFactsService)
     : base(syntaxFactsService, (int)SyntaxKind.CharacterLiteralToken, (int)SyntaxKind.CharacterLiteralToken,
            Braces.SingleQuote.OpenCharacter, Braces.SingleQuote.CloseCharacter)
 {
 }
示例#34
0
        private void RemoveAwaitFromCallerIfPresent(
            SyntaxEditor editor, ISyntaxFactsService syntaxFacts,
            SyntaxNode root, ReferenceLocation referenceLocation,
            CancellationToken cancellationToken)
        {
            if (referenceLocation.IsImplicit)
            {
                return;
            }

            var location = referenceLocation.Location;
            var token    = location.FindToken(cancellationToken);

            var nameNode = token.Parent;

            if (nameNode == null)
            {
                return;
            }

            // Look for the following forms:
            //  await M(...)
            //  await <expr>.M(...)
            //  await M(...).ConfigureAwait(...)
            //  await <expr>.M(...).ConfigureAwait(...)

            var expressionNode = nameNode;

            if (syntaxFacts.IsNameOfMemberAccessExpression(nameNode))
            {
                expressionNode = nameNode.Parent;
            }

            if (!syntaxFacts.IsExpressionOfInvocationExpression(expressionNode))
            {
                return;
            }

            // We now either have M(...) or <expr>.M(...)

            var invocationExpression = expressionNode.Parent;

            Debug.Assert(syntaxFacts.IsInvocationExpression(invocationExpression));

            if (syntaxFacts.IsExpressionOfAwaitExpression(invocationExpression))
            {
                // Handle the case where we're directly awaited.
                var awaitExpression = invocationExpression.Parent;
                editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) =>
                                   syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression)
                                   .WithTriviaFrom(currentAwaitExpression));
            }
            else if (syntaxFacts.IsExpressionOfMemberAccessExpression(invocationExpression))
            {
                // Check for the .ConfigureAwait case.
                var parentMemberAccessExpression         = invocationExpression.Parent;
                var parentMemberAccessExpressionNameNode = syntaxFacts.GetNameOfMemberAccessExpression(
                    parentMemberAccessExpression);

                var parentMemberAccessExpressionName = syntaxFacts.GetIdentifierOfSimpleName(parentMemberAccessExpressionNameNode).ValueText;
                if (parentMemberAccessExpressionName == nameof(Task.ConfigureAwait))
                {
                    var parentExpression = parentMemberAccessExpression.Parent;
                    if (syntaxFacts.IsExpressionOfAwaitExpression(parentExpression))
                    {
                        var awaitExpression = parentExpression.Parent;
                        editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) =>
                        {
                            var currentConfigureAwaitInvocation = syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression);
                            var currentMemberAccess             = syntaxFacts.GetExpressionOfInvocationExpression(currentConfigureAwaitInvocation);
                            var currentInvocationExpression     = syntaxFacts.GetExpressionOfMemberAccessExpression(currentMemberAccess);
                            return(currentInvocationExpression.WithTriviaFrom(currentAwaitExpression));
                        });
                    }
                }
            }
        }
        public override SignatureHelpState GetCurrentArgumentState(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken)
        {
            if (TryGetObjectCreationExpression(
                    root,
                    position,
                    syntaxFacts,
                    SignatureHelpTriggerReason.InvokeSignatureHelpCommand,
                    cancellationToken,
                    out var expression) &&
                currentSpan.Start == SignatureHelpUtilities.GetSignatureHelpSpan(expression.ArgumentList).Start)
            {
                return(SignatureHelpUtilities.GetSignatureHelpState(expression.ArgumentList, position));
            }

            return(null);
        }
示例#36
0
 public abstract SignatureHelpState GetCurrentArgumentState(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken);
 private bool IsTrackableCharacter(ISyntaxFactsService syntaxFactsService, char c)
 {
     // Allow identifier part characters at the beginning of strings (even if they are
     // not identifier start characters). If an intermediate name is not valid, the smart
     // tag will not be shown due to later checks. Also allow escape chars anywhere as
     // they might be in the middle of a complex edit.
     return syntaxFactsService.IsIdentifierPartCharacter(c) || syntaxFactsService.IsIdentifierEscapeCharacter(c);
 }
示例#38
0
 public static void GetPartsOfAssignmentStatement(
     this ISyntaxFactsService syntaxFacts, SyntaxNode statement,
     out SyntaxNode left, out SyntaxNode right)
 {
     syntaxFacts.GetPartsOfAssignmentStatement(statement, out left, out _, out right);
 }
示例#39
0
 internal override bool IsViableProperty(IPropertySymbol property, SyntaxNode expression, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken)
 {
     return(IsViablePropertyOrField(property, expression, semanticModel, syntaxFacts, cancellationToken));
 }
示例#40
0
 public static bool IsAnyMemberAccessExpression(
     this ISyntaxFactsService syntaxFacts, SyntaxNode node)
 {
     return(syntaxFacts.IsSimpleMemberAccessExpression(node) || syntaxFacts.IsPointerMemberAccessExpression(node));
 }
示例#41
0
 public static bool IsWhitespaceOrEndOfLineTrivia(this ISyntaxFactsService syntaxFacts, SyntaxTrivia trivia)
 {
     return(syntaxFacts.IsWhitespaceTrivia(trivia) || syntaxFacts.IsEndOfLineTrivia(trivia));
 }
示例#42
0
        private bool IsViablePropertyOrField(ISymbol propertyOrField, SyntaxNode expression, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken)
        {
            if (!propertyOrField.IsStatic)
            {
                return(false);
            }

            var leftName = (expression as MemberAccessExpressionSyntax)?.Expression as SimpleNameSyntax;

            if (leftName == null)
            {
                return(false);
            }

            return(StringComparer.Ordinal.Compare(propertyOrField.ContainingType.Name, leftName.Identifier.Text) == 0);
        }
示例#43
0
 public static bool IsRegularOrDocumentationComment(this ISyntaxFactsService syntaxFacts, SyntaxTrivia trivia)
 => syntaxFacts.IsRegularComment(trivia) || syntaxFacts.IsDocumentationComment(trivia);
示例#44
0
        private static SyntaxNode GetContainer(SemanticModel semanticModel, SyntaxNode parameterNode, ISyntaxFactsService syntaxFactsService)
        {
            for (var current = parameterNode; current != null; current = current.Parent)
            {
                var declaredSymbol = semanticModel.GetDeclaredSymbol(current);

                if (declaredSymbol is IMethodSymbol method && method.MethodKind != MethodKind.AnonymousFunction)
                {
                    return(current);
                }
            }

            return(syntaxFactsService.GetContainingVariableDeclaratorOfFieldDeclaration(parameterNode));
        }
 /// <summary>
 /// Try to get a new node to replace given node, which is a reference to a top-level type declared inside the
 /// namespace to be changed. If this reference is the right side of a qualified name, the new node returned would
 /// be the entire qualified name. Depends on whether <paramref name="newNamespaceParts"/> is provided, the name
 /// in the new node might be qualified with this new namespace instead.
 /// </summary>
 /// <param name="reference">A reference to a type declared inside the namespace to be changed, which is calculated
 /// based on results from `SymbolFinder.FindReferencesAsync`.</param>
 /// <param name="newNamespaceParts">If specified, the namespace of original reference will be replaced with given
 /// namespace in the replacement node.</param>
 /// <param name="old">The node to be replaced. This might be an ancestor of original </param>
 /// <param name="new">The replacement node.</param>
 public abstract bool TryGetReplacementReferenceSyntax(SyntaxNode reference, ImmutableArray <string> newNamespaceParts, ISyntaxFactsService syntaxFacts, [NotNullWhen(returnValue: true)] out SyntaxNode?old, [NotNullWhen(returnValue: true)] out SyntaxNode? @new);
        private string TryGetText(SyntaxToken token, SemanticModel semanticModel, Document document, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken)
        {
            if (TryGetTextForSpecialCharacters(token, out var text) ||
                TryGetTextForContextualKeyword(token, out text) ||
                TryGetTextForCombinationKeyword(token, syntaxFacts, out text) ||
                TryGetTextForKeyword(token, syntaxFacts, out text) ||
                TryGetTextForPreProcessor(token, syntaxFacts, out text) ||
                TryGetTextForOperator(token, document, out text) ||
                TryGetTextForSymbol(token, semanticModel, document, cancellationToken, out text))
            {
                return(text);
            }

            return(string.Empty);
        }
 public CurlyBraceCompletionSession(ISyntaxFactsService syntaxFactsService, ISmartIndentationService smartIndentationService, ITextBufferUndoManagerProvider undoManager)
     : base(syntaxFactsService, (int)SyntaxKind.OpenBraceToken, (int)SyntaxKind.CloseBraceToken)
 {
     _smartIndentationService = smartIndentationService;
     _undoManager             = undoManager;
 }
示例#48
0
 private static bool MatchesPattern(ISyntaxFactsService syntaxFacts, SyntaxNode node1, SyntaxNode node2)
 => syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(node1)) &&
 !syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(node2));
 protected override bool CanAddImportForGetAwaiter(string diagnosticId, ISyntaxFactsService syntaxFactsService, SyntaxNode node)
 => (diagnosticId == CS1061 ||     // Regular cases
     diagnosticId == CS4036 ||     // WinRT async interfaces
     diagnosticId == CS1929) &&    // An extension `GetAwaiter()` is in scope, but for another type
 AncestorOrSelfIsAwaitExpression(syntaxFactsService, node);
示例#50
0
 public MoveToNamespaceOptionsResult GetChangeNamespaceOptions(string defaultNamespace, ImmutableArray <string> availableNamespaces, ISyntaxFactsService syntaxFactsService)
 => _optionsResult;
        private async Task<IEnumerable<IMethodSymbol>> GetAddMethodsAsync(
            Project project,
            Diagnostic diagnostic,
            SyntaxNode node,
            SemanticModel semanticModel,
            ISet<INamespaceSymbol> namespacesInScope,
            ISyntaxFactsService syntaxFacts,
            SyntaxNode expression,
            CancellationToken cancellationToken)
        {
            string name;
            int arity;
            syntaxFacts.GetNameAndArityOfSimpleName(node, out name, out arity);
            if (name != null)
            {
                return SpecializedCollections.EmptyEnumerable<IMethodSymbol>();
            }

            if (IsAddMethodContext(node, semanticModel))
            {
                var symbols = await SymbolFinder.FindDeclarationsAsync(project, "Add", this.IgnoreCase, SymbolFilter.Member, cancellationToken).ConfigureAwait(false);
                return symbols
                    .OfType<IMethodSymbol>()
                    .Where(method => method.IsExtensionMethod &&
                                     method.ContainingType?.IsAccessibleWithin(semanticModel.Compilation.Assembly) == true &&
                                     IsViableExtensionMethod(method, expression, semanticModel, syntaxFacts, cancellationToken));
            }

            return SpecializedCollections.EmptyEnumerable<IMethodSymbol>();
        }
示例#52
0
            static SyntaxNode TryGetAcceptedNodeOrExtracted(SyntaxNode node, Predicate <SyntaxNode> predicate, Func <SyntaxNode, ISyntaxFactsService, SyntaxNode> extractNode, ISyntaxFactsService syntaxFacts)
            {
                if (node == null)
                {
                    return(null);
                }

                if (predicate(node))
                {
                    return(node);
                }

                var extractedNode = extractNode(node, syntaxFacts);

                return((extractedNode != null && predicate(extractedNode))
                    ? extractedNode
                    : null);
            }
        private IEnumerable<INamespaceSymbol> FilterForExtensionMethods(SemanticModel semanticModel, ISet<INamespaceSymbol> namespacesInScope, ISyntaxFactsService syntaxFacts, SyntaxNode expression, IEnumerable<ISymbol> symbols, CancellationToken cancellationToken)
        {
            var extensionMethodSymbols = symbols
                .OfType<IMethodSymbol>()
                .Where(method => method.IsExtensionMethod &&
                                 method.ContainingType?.IsAccessibleWithin(semanticModel.Compilation.Assembly) == true &&
                                 IsViableExtensionMethod(method, expression, semanticModel, syntaxFacts, cancellationToken))
                .ToList();

            return GetProposedNamespaces(
                extensionMethodSymbols.Select(s => s.ContainingNamespace),
                semanticModel,
                namespacesInScope);
        }
 protected abstract Func <SyntaxToken, bool> GetTokensMatchFunction(ISyntaxFactsService syntaxFacts, string name);
示例#55
0
 /// <summary>
 /// Gets the replacement node for a compound assignment expression whose
 /// assigned value is redundant.
 /// For example, "x += MethodCall()", where assignment to 'x' is redundant
 /// is replaced with "_ = MethodCall()" or "var unused = MethodCall()"
 /// </summary>
 protected abstract SyntaxNode GetReplacementNodeForCompoundAssignment(
     SyntaxNode originalCompoundAssignment,
     SyntaxNode newAssignmentTarget,
     SyntaxEditor editor,
     ISyntaxFactsService syntaxFacts);
示例#56
0
        private async Task FixAllValueAssignedIsUnusedDiagnosticsAsync(
            IOrderedEnumerable <Diagnostic> diagnostics,
            Document document,
            SemanticModel semanticModel,
            SyntaxNode root,
            SyntaxNode containingMemberDeclaration,
            UnusedValuePreference preference,
            bool removeAssignments,
            UniqueVariableNameGenerator nameGenerator,
            SyntaxEditor editor,
            ISyntaxFactsService syntaxFacts,
            CancellationToken cancellationToken)
        {
            // This method applies the code fix for diagnostics reported for unused value assignments to local/parameter.
            // The actual code fix depends on whether or not the right hand side of the assignment has side effects.
            // For example, if the right hand side is a constant or a reference to a local/parameter, then it has no side effects.
            // The lack of side effects is indicated by the "removeAssignments" parameter for this function.

            // If the right hand side has no side effects, then we can replace the assignments with variable declarations that have no initializer
            // or completely remove the statement.
            // If the right hand side does have side effects, we replace the identifier token for unused value assignment with
            // a new identifier token (either discard '_' or new unused local variable name).

            // For both the above cases, if the original diagnostic was reported on a local declaration, i.e. redundant initialization
            // at declaration, then we also add a new variable declaration statement without initializer for this local.

            using var _1 = PooledDictionary <SyntaxNode, SyntaxNode> .GetInstance(out var nodeReplacementMap);

            using var _2 = PooledHashSet <SyntaxNode> .GetInstance(out var nodesToRemove);

            using var _3 = PooledHashSet <(TLocalDeclarationStatementSyntax declarationStatement, SyntaxNode node)> .GetInstance(out var nodesToAdd);

            // Indicates if the node's trivia was processed.
            using var _4 = PooledHashSet <SyntaxNode> .GetInstance(out var processedNodes);

            using var _5 = PooledHashSet <TLocalDeclarationStatementSyntax> .GetInstance(out var candidateDeclarationStatementsForRemoval);

            var hasAnyUnusedLocalAssignment = false;

            foreach (var(node, isUnusedLocalAssignment) in GetNodesToFix())
            {
                hasAnyUnusedLocalAssignment |= isUnusedLocalAssignment;

                var declaredLocal = semanticModel.GetDeclaredSymbol(node, cancellationToken) as ILocalSymbol;
                if (declaredLocal == null && node.Parent is TCatchStatementSyntax)
                {
                    declaredLocal = semanticModel.GetDeclaredSymbol(node.Parent, cancellationToken) as ILocalSymbol;
                }

                string newLocalNameOpt = null;
                if (removeAssignments)
                {
                    // Removable assignment or initialization, such that right hand side has no side effects.
                    if (declaredLocal != null)
                    {
                        // Redundant initialization.
                        // For example, "int a = 0;"
                        var variableDeclarator = node.FirstAncestorOrSelf <TVariableDeclaratorSyntax>();
                        Debug.Assert(variableDeclarator != null);
                        nodesToRemove.Add(variableDeclarator);

                        // Local declaration statement containing the declarator might be a candidate for removal if all its variables get marked for removal.
                        var candidate = GetCandidateLocalDeclarationForRemoval(variableDeclarator);
                        if (candidate != null)
                        {
                            candidateDeclarationStatementsForRemoval.Add(candidate);
                        }
                    }
                    else
                    {
                        // Redundant assignment or increment/decrement.
                        if (syntaxFacts.IsOperandOfIncrementOrDecrementExpression(node))
                        {
                            // For example, C# increment operation "a++;"
                            Debug.Assert(node.Parent.Parent is TExpressionStatementSyntax);
                            nodesToRemove.Add(node.Parent.Parent);
                        }
                        else
                        {
                            Debug.Assert(syntaxFacts.IsLeftSideOfAnyAssignment(node));

                            if (node.Parent is TStatementSyntax)
                            {
                                // For example, VB simple assignment statement "a = 0"
                                nodesToRemove.Add(node.Parent);
                            }
                            else if (node.Parent is TExpressionSyntax && node.Parent.Parent is TExpressionStatementSyntax)
                            {
                                // For example, C# simple assignment statement "a = 0;"
                                nodesToRemove.Add(node.Parent.Parent);
                            }
                            else
                            {
                                // For example, C# nested assignment statement "a = b = 0;", where assignment to 'b' is redundant.
                                // We replace the node with "a = 0;"
                                nodeReplacementMap.Add(node.Parent, syntaxFacts.GetRightHandSideOfAssignment(node.Parent));
                            }
                        }
                    }
                }
                else
                {
                    // Value initialization/assignment where the right hand side may have side effects,
                    // and hence needs to be preserved in fixed code.
                    // For example, "x = MethodCall();" is replaced with "_ = MethodCall();" or "var unused = MethodCall();"

                    // Replace the flagged variable's indentifier token with new named, based on user's preference.
                    var newNameToken = preference == UnusedValuePreference.DiscardVariable
                        ? document.GetRequiredLanguageService <SyntaxGeneratorInternal>().Identifier(AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.DiscardVariableName)
                        : nameGenerator.GenerateUniqueNameAtSpanStart(node);
                    newLocalNameOpt = newNameToken.ValueText;
                    var newNameNode = TryUpdateNameForFlaggedNode(node, newNameToken);
                    if (newNameNode == null)
                    {
                        continue;
                    }

                    // Is this is compound assignment?
                    if (syntaxFacts.IsLeftSideOfAnyAssignment(node) && !syntaxFacts.IsLeftSideOfAssignment(node))
                    {
                        // Compound assignment is changed to simple assignment.
                        // For example, "x += MethodCall();", where assignment to 'x' is redundant
                        // is replaced with "_ = MethodCall();" or "var unused = MethodCall();"
                        nodeReplacementMap.Add(node.Parent, GetReplacementNodeForCompoundAssignment(node.Parent, newNameNode, editor, syntaxFacts));
                    }
                    else
                    {
                        nodeReplacementMap.Add(node, newNameNode);
                    }
                }

                if (declaredLocal != null)
                {
                    // We have a dead initialization for a local declaration.
                    // Introduce a new local declaration statement without an initializer for this local.
                    var declarationStatement = CreateLocalDeclarationStatement(declaredLocal.Type, declaredLocal.Name);
                    if (isUnusedLocalAssignment)
                    {
                        declarationStatement = declarationStatement.WithAdditionalAnnotations(s_unusedLocalDeclarationAnnotation);
                    }

                    nodesToAdd.Add((declarationStatement, node));
                }
                else
                {
                    // We have a dead assignment to a local/parameter, which is not at the declaration site.
                    // Create a new local declaration for the unused local if both following conditions are met:
                    //  1. User prefers unused local variables for unused value assignment AND
                    //  2. Assignment value has side effects and hence cannot be removed.
                    if (preference == UnusedValuePreference.UnusedLocalVariable && !removeAssignments)
                    {
                        var type = semanticModel.GetTypeInfo(node, cancellationToken).Type;
                        Debug.Assert(type != null);
                        Debug.Assert(newLocalNameOpt != null);
                        var declarationStatement = CreateLocalDeclarationStatement(type, newLocalNameOpt);
                        nodesToAdd.Add((declarationStatement, node));
                    }
                }
            }

            // Process candidate declaration statements for removal.
            foreach (var localDeclarationStatement in candidateDeclarationStatementsForRemoval)
            {
                // If all the variable declarators for the local declaration statement are being removed,
                // we can remove the entire local declaration statement.
                if (ShouldRemoveStatement(localDeclarationStatement, out var variables))
                {
                    nodesToRemove.Add(localDeclarationStatement);
                    nodesToRemove.RemoveRange(variables);
                }
            }

            foreach (var(declarationStatement, node) in nodesToAdd)
            {
                InsertLocalDeclarationStatement(declarationStatement, node);
            }

            if (hasAnyUnusedLocalAssignment)
            {
                // Local declaration statements with no initializer, but non-zero references are candidates for removal
                // if the code fix removes all these references.
                // We annotate such declaration statements with no initializer abd non-zero references here
                // and remove them in post process document pass later, if the code fix did remove all these references.
                foreach (var localDeclarationStatement in containingMemberDeclaration.DescendantNodes().OfType <TLocalDeclarationStatementSyntax>())
                {
                    var variables = syntaxFacts.GetVariablesOfLocalDeclarationStatement(localDeclarationStatement);
                    if (variables.Count == 1 &&
                        syntaxFacts.GetInitializerOfVariableDeclarator(variables[0]) == null &&
                        !(await IsLocalDeclarationWithNoReferencesAsync(localDeclarationStatement, document, cancellationToken).ConfigureAwait(false)))
                    {
                        nodeReplacementMap.Add(localDeclarationStatement, localDeclarationStatement.WithAdditionalAnnotations(s_existingLocalDeclarationWithoutInitializerAnnotation));
                    }
                }
            }

            foreach (var node in nodesToRemove)
            {
                var removeOptions = SyntaxGenerator.DefaultRemoveOptions;
                // If the leading trivia was not added to a new node, process it now.
                if (!processedNodes.Contains(node))
                {
                    // Don't keep trivia if the node is part of a multiple declaration statement.
                    // e.g. int x = 0, y = 0, z = 0; any white space left behind can cause problems if the declaration gets split apart.
                    var containingDeclaration = node.GetAncestor <TLocalDeclarationStatementSyntax>();
                    if (containingDeclaration != null && candidateDeclarationStatementsForRemoval.Contains(containingDeclaration))
                    {
                        removeOptions = SyntaxRemoveOptions.KeepNoTrivia;
                    }
                    else
                    {
                        removeOptions |= SyntaxRemoveOptions.KeepLeadingTrivia;
                    }
                }
                editor.RemoveNode(node, removeOptions);
            }

            foreach (var kvp in nodeReplacementMap)
            {
                editor.ReplaceNode(kvp.Key, kvp.Value.WithAdditionalAnnotations(Formatter.Annotation));
            }

            return;

            // Local functions.
            IEnumerable <(SyntaxNode node, bool isUnusedLocalAssignment)> GetNodesToFix()
            {
                foreach (var diagnostic in diagnostics)
                {
                    var node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
                    var isUnusedLocalAssignment = AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.GetIsUnusedLocalDiagnostic(diagnostic);
                    yield return(node, isUnusedLocalAssignment);
                }
            }

            // Mark generated local declaration statement with:
            //  1. "s_newLocalDeclarationAnnotation" for post processing in "MoveNewLocalDeclarationsNearReference" below.
            //  2. Simplifier annotation so that 'var'/explicit type is correctly added based on user options.
            TLocalDeclarationStatementSyntax CreateLocalDeclarationStatement(ITypeSymbol type, string name)
            => (TLocalDeclarationStatementSyntax)editor.Generator.LocalDeclarationStatement(type, name)
            .WithLeadingTrivia(syntaxFacts.ElasticCarriageReturnLineFeed)
            .WithAdditionalAnnotations(s_newLocalDeclarationStatementAnnotation, Simplifier.Annotation);

            void InsertLocalDeclarationStatement(TLocalDeclarationStatementSyntax declarationStatement, SyntaxNode node)
            {
                // Find the correct place to insert the given declaration statement based on the node's ancestors.
                var insertionNode = node.FirstAncestorOrSelf <SyntaxNode, ISyntaxFactsService>((n, syntaxFacts) => n.Parent is TSwitchCaseBlockSyntax ||
                                                                                               syntaxFacts.IsExecutableBlock(n.Parent) &&
                                                                                               !(n is TCatchStatementSyntax) &&
                                                                                               !(n is TCatchBlockSyntax),
                                                                                               syntaxFacts);

                if (insertionNode is TSwitchCaseLabelOrClauseSyntax)
                {
                    InsertAtStartOfSwitchCaseBlockForDeclarationInCaseLabelOrClause(insertionNode.GetAncestor <TSwitchCaseBlockSyntax>(), editor, declarationStatement);
                }
                else if (insertionNode is TStatementSyntax)
                {
                    // If the insertion node is being removed, keep the leading trivia with the new declaration.
                    if (nodesToRemove.Contains(insertionNode) && !processedNodes.Contains(insertionNode))
                    {
                        declarationStatement = declarationStatement.WithLeadingTrivia(insertionNode.GetLeadingTrivia());
                        // Mark the node as processed so that the trivia only gets added once.
                        processedNodes.Add(insertionNode);
                    }
                    editor.InsertBefore(insertionNode, declarationStatement);
                }
            }

            bool ShouldRemoveStatement(TLocalDeclarationStatementSyntax localDeclarationStatement, out SeparatedSyntaxList <SyntaxNode> variables)
            {
                Debug.Assert(removeAssignments);
                Debug.Assert(localDeclarationStatement != null);

                // We should remove the entire local declaration statement if all its variables are marked for removal.
                variables = syntaxFacts.GetVariablesOfLocalDeclarationStatement(localDeclarationStatement);
                foreach (var variable in variables)
                {
                    if (!nodesToRemove.Contains(variable))
                    {
                        return(false);
                    }
                }

                return(true);
            }
        }
            private bool TryGetSyntaxFactsService(out ISyntaxFactsService syntaxFactsService)
            {
                // Can be called on a background thread

                syntaxFactsService = null;
                var document = _buffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
                if (document != null)
                {
                    syntaxFactsService = document.Project.LanguageServices.GetService<ISyntaxFactsService>();
                }

                return syntaxFactsService != null;
            }
示例#58
0
        protected override bool IsViableExtensionMethod(IMethodSymbol method, SyntaxNode expression, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken)
        {
            var leftExpression = syntaxFacts.GetExpressionOfMemberAccessExpression(expression);

            if (leftExpression == null)
            {
                if (expression.IsKind(SyntaxKind.CollectionInitializerExpression))
                {
                    leftExpression = expression.GetAncestor <ObjectCreationExpressionSyntax>();
                }
                else
                {
                    return(false);
                }
            }

            var semanticInfo       = semanticModel.GetTypeInfo(leftExpression, cancellationToken);
            var leftExpressionType = semanticInfo.Type;

            return(leftExpressionType != null && method.ReduceExtensionMethod(leftExpressionType) != null);
        }
            internal bool CanInvokeRename(
                ISyntaxFactsService syntaxFactsService,
                IRenameTrackingLanguageHeuristicsService languageHeuristicsService,
                bool isSmartTagCheck,
                bool waitForResult,
                CancellationToken cancellationToken)
            {
                if (IsRenamableIdentifier(_isRenamableIdentifierTask, waitForResult, cancellationToken))
                {
                    var isRenamingDeclaration = _isRenamableIdentifierTask.Result == TriggerIdentifierKind.RenamableDeclaration;
                    var newName = TrackingSpan.GetText(TrackingSpan.TextBuffer.CurrentSnapshot);
                    var comparison = isRenamingDeclaration || syntaxFactsService.IsCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;

                    if (!string.Equals(OriginalName, newName, comparison) &&
                        syntaxFactsService.IsValidIdentifier(newName) &&
                        languageHeuristicsService.IsIdentifierValidForRenameTracking(newName))
                    {
                        // At this point, we want to allow renaming if the user invoked Ctrl+. explicitly, but we
                        // want to avoid showing a smart tag if we're renaming a reference that binds to an existing
                        // symbol.
                        if (!isSmartTagCheck || isRenamingDeclaration || !NewIdentifierDefinitelyBindsToReference())
                        {
                            return true;
                        }
                    }
                }

                return false;
            }
 public EmbeddedLanguageInfo(int stringLiteralTokenKind, int interpolatedTextTokenKind, ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, IVirtualCharService virtualCharService)
 {
     StringLiteralTokenKind    = stringLiteralTokenKind;
     InterpolatedTextTokenKind = interpolatedTextTokenKind;
     SyntaxFacts        = syntaxFacts;
     SemanticFacts      = semanticFacts;
     VirtualCharService = virtualCharService;
 }