Esempio n. 1
0
 public static IList<SyntaxToken> GetTokens(SyntaxNode node)
 {
     if (node.Language == LanguageNames.CSharp)
     {
         return node.DescendantTokens().Where(t => !SkipCSharpToken(t)).ToList();
     }
     else
     {
         return node.DescendantTokens().Where(t => !SkipVisualBasicToken(t)).ToList();
     }
 }
 private static IEnumerable<SyntaxToken> GetAsyncOrAwaitTokens(SyntaxNode node)
 {
     return node.DescendantTokens()
         .Where(token =>
             token.IsKind(SyntaxKind.IdentifierToken) &&
             AsyncOrAwait.Contains(token.ToString()));
 }
 private static IEnumerable<SyntaxToken> GetAsyncOrAwaitTokens(SyntaxNode node)
 {
     return from token in node.DescendantTokens()
            where token.IsKind(SyntaxKind.IdentifierToken) &&
            AsyncOrAwait.Contains(token.ToString())
            select token;
 }
Esempio n. 4
0
        private bool TryGetVariable(SyntaxNode node, out PatternVariable variable)
        {
            variable = null;

            var tokens = node.DescendantTokens().Take(2).ToImmutableArray();
            if (tokens.Length != 1)
                return false;

            var token = tokens[0];
            return TryGetVariable(token, out variable);
        }
        /// <summary>
        /// Fix the new lines around open brace tokens.  An open brace should be followed by content, not a blank
        /// line.  Remove those here.  
        /// </summary>
        private static SyntaxNode FixOpenBraces(SyntaxNode syntaxNode)
        {
            // Look for the open brace tokens that are followed by empty blank lines.  The new lines will
            // be attached to the next nodes, not the open brace token.
            var tokensToReplace = syntaxNode.DescendantTokens().Where((token) =>
                {
                    var nextToken = token.GetNextToken();
                    if (token.Kind() != SyntaxKind.OpenBraceToken || !nextToken.HasLeadingTrivia)
                    {
                        return false;
                    }

                    return IsSimpleNewLine(nextToken.LeadingTrivia, 0);
                }).Select(x => x.GetNextToken());

            return syntaxNode.ReplaceTokens(tokensToReplace, (_, y) => FixOpenBraceNextToken(y));
        }
        SyntaxNode ISyntaxRule.Process(SyntaxNode root)
        {
            var braceTokenNeighbors = root.DescendantTokens()
                .Where(t =>
                    t.IsKind(SyntaxKind.OpenBraceToken)
                    || (t.IsKind(SyntaxKind.CloseBraceToken) && t.GetPreviousToken().IsKind(SyntaxKind.OpenBraceToken))
                )
                .ToDictionary(
                    t => t.IsKind(SyntaxKind.OpenBraceToken) ? t.GetNextToken() : t.GetPreviousToken(),
                    t => t.Kind()
                );

            var processed = root.ReplaceTokens(
                braceTokenNeighbors.Keys,
                (orig, t) => braceTokenNeighbors[orig] == SyntaxKind.OpenBraceToken
                    ? ProcessTokenAfterOpenBrace(t)
                    : ProcessTokenBeforeCloseBrace(t)
            );
            return processed;
        }
Esempio n. 7
0
 public int CalculateLinesOfCode(SyntaxNode node)
 {
     var totalLines = node.SyntaxTree.GetLineSpan(node.FullSpan).EndLinePosition.Line -
                      node.SyntaxTree.GetLineSpan(node.FullSpan).StartLinePosition.Line;
     var amountOfSingleLineCommentsAndEmptyLines = CountSingleLineCommentsAndEmptyLines(node.DescendantTokens());
     var amountOfMultiLineCommentLines = CountMultiLineCommentLines(node.DescendantTokens());
     var amountOfSingleLineBraces = CountSingleLineBraces(node);
     var amountOfDocumentationComments = CountDocumentationComments(node.DescendantTokens());
     var linesOfCode = totalLines
         - amountOfSingleLineCommentsAndEmptyLines 
         - amountOfMultiLineCommentLines 
         - amountOfSingleLineBraces
         - amountOfDocumentationComments;
     return linesOfCode; 
 }
        /// <returns>
        /// If <paramref name="node"/> is a method, accessor, operator, destructor, or constructor without an initializer,
        /// tokens of its block body, or tokens of the expression body if applicable.
        /// 
        /// If <paramref name="node"/> is an indexer declaration the tokens of its expression body.
        /// 
        /// If <paramref name="node"/> is a property declaration the tokens of its expression body or initializer.
        ///   
        /// If <paramref name="node"/> is a constructor with an initializer, 
        /// tokens of the initializer concatenated with tokens of the constructor body.
        /// 
        /// If <paramref name="node"/> is a variable declarator of a field with an initializer,
        /// tokens of the field initializer.
        /// 
        /// Null reference otherwise.
        /// </returns>
        internal override IEnumerable<SyntaxToken> TryGetActiveTokens(SyntaxNode node)
        {
            if (node.IsKind(SyntaxKind.VariableDeclarator))
            {
                // TODO: The logic is similar to BreakpointSpans.TryCreateSpanForVariableDeclaration. Can we abstract it?

                var declarator = node;
                var fieldDeclaration = (BaseFieldDeclarationSyntax)declarator.Parent.Parent;
                var variableDeclaration = fieldDeclaration.Declaration;

                if (fieldDeclaration.Modifiers.Any(SyntaxKind.ConstKeyword))
                {
                    return null;
                }

                if (variableDeclaration.Variables.Count == 1)
                {
                    if (variableDeclaration.Variables[0].Initializer == null)
                    {
                        return null;
                    }

                    return fieldDeclaration.Modifiers.Concat(variableDeclaration.DescendantTokens()).Concat(fieldDeclaration.SemicolonToken);
                }

                if (declarator == variableDeclaration.Variables[0])
                {
                    return fieldDeclaration.Modifiers.Concat(variableDeclaration.Type.DescendantTokens()).Concat(node.DescendantTokens());
                }

                return declarator.DescendantTokens();
            }

            if (node.IsKind(SyntaxKind.ConstructorDeclaration))
            {
                var ctor = (ConstructorDeclarationSyntax)node;
                if (ctor.Initializer != null)
                {
                    return ctor.Initializer.DescendantTokens().Concat(ctor.Body.DescendantTokens());
                }

                return ctor.Body.DescendantTokens();
            }

            return SyntaxUtilities.TryGetMethodDeclarationBody(node)?.DescendantTokens();
        }
Esempio n. 9
0
 private void ClassifyNode(SyntaxNode node)
 {
     foreach (var token in node.DescendantTokens(span: _textSpan, descendIntoTrivia: false))
     {
         _cancellationToken.ThrowIfCancellationRequested();
         ClassifyToken(token);
     }
 }
        private static bool LocateExcludedSpans(SyntaxNode root, out ImmutableArray<TextSpan> excludedSpans)
        {
            ImmutableArray<TextSpan>.Builder builder = ImmutableArray.CreateBuilder<TextSpan>();

            // Locate disabled text
            foreach (var trivia in root.DescendantTrivia(descendIntoTrivia: true))
            {
                if (trivia.IsKind(SyntaxKind.DisabledTextTrivia))
                {
                    builder.Add(trivia.Span);
                }
                else if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia))
                {
                    if (trivia.ToString().StartsWith("////"))
                    {
                        // Exclude comments starting with //// because they could contain commented code which contains
                        // string or character literals, and we don't want to change the contents of those strings.
                        builder.Add(trivia.Span);
                    }
                }
            }

            // Locate string literals
            foreach (var token in root.DescendantTokens(descendIntoTrivia: true))
            {
                switch (token.Kind())
                {
                case SyntaxKind.XmlTextLiteralToken:
                    if (token.Parent.IsKind(SyntaxKind.XmlCDataSection))
                    {
                        builder.Add(token.Span);
                    }

                    break;

                case SyntaxKind.CharacterLiteralToken:
                case SyntaxKind.StringLiteralToken:
                case SyntaxKind.InterpolatedStringTextToken:
                    builder.Add(token.Span);
                    break;

                default:
                    break;
                }
            }

            // Sort the results
            builder.Sort();

            // Combine adjacent and overlapping spans
            ReduceTextSpans(builder);

            excludedSpans = builder.ToImmutable();
            return true;
        }
 public void Process(SyntaxNode node)
 {
     var indentLevel = 0;
     SyntaxToken previous = default(SyntaxToken);
     foreach (var token in node.DescendantTokens())
     {
         switch (token.Kind())
         {
             case SyntaxKind.AbstractKeyword:
             case SyntaxKind.AddKeyword:
             case SyntaxKind.AliasKeyword:
             case SyntaxKind.ArgListKeyword:
             case SyntaxKind.AscendingKeyword:
             case SyntaxKind.AsKeyword:
             case SyntaxKind.AssemblyKeyword:
             case SyntaxKind.AsyncKeyword:
             case SyntaxKind.AwaitKeyword:
             case SyntaxKind.BaseKeyword:
             case SyntaxKind.BoolKeyword:
             case SyntaxKind.BreakKeyword:
             case SyntaxKind.ByKeyword:
             case SyntaxKind.TildeToken:
                 this.ProcessUnaryOperator(token);
                 break;
             case SyntaxKind.ExclamationToken:
                 this.ProcessUnaryOperator(token);
                 break;
             case SyntaxKind.DollarToken:
                 throw new NotSupportedException(token.Kind().ToString());
             case SyntaxKind.PercentToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.CaretToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.AmpersandToken:
                 switch (token.Parent.Kind())
                 {
                     case SyntaxKind.BitwiseAndExpression:
                         this.ProcessBinaryOperator(token);
                         break;
                     case SyntaxKind.AddressOfExpression:
                         this.ProcessUnaryOperator(token);
                         break;
                     default:
                         throw new InvalidOperationException("Unexpected parent kind " + token.Parent.Kind() + " for token " + token.Kind());
                 }
                 break;
             case SyntaxKind.AsteriskToken:
                 switch (token.Parent.Kind())
                 {
                     case SyntaxKind.MultiplyExpression:
                         this.ProcessBinaryOperator(token);
                         break;
                     default:
                         throw new NotSupportedException("Parent kind of asterisk was " + token.Parent.Kind());
                 }
                 break;
             case SyntaxKind.OpenParenToken:
                 this.EnterGroup(token);
                 break;
             case SyntaxKind.CloseParenToken:
                 this.ExitGroup(token);
                 break;
             case SyntaxKind.MinusToken:
                 switch (token.Parent.Kind())
                 {
                     case SyntaxKind.SubtractExpression:
                         this.ProcessBinaryOperator(token);
                         break;
                     case SyntaxKind.UnaryMinusExpression:
                         this.ProcessUnaryOperator(token);
                         break;
                     default:
                         throw new InvalidOperationException("Unexpected parent kind " + token.Parent.Kind() + " for " + token.Kind());
                 }
                 break;
             case SyntaxKind.PlusToken:
                 switch (token.Parent.Kind())
                 {
                     case SyntaxKind.AddExpression:
                         this.ProcessBinaryOperator(token);
                         break;
                     case SyntaxKind.UnaryPlusExpression:
                         this.ProcessUnaryOperator(token);
                         break;
                     default:
                         throw new InvalidOperationException("Unexpected parent kind " + token.Parent.Kind() + " for " + token.Kind());
                 }
                 break;
             case SyntaxKind.EqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.OpenBraceToken:
                 this.EnterGroup(token);
                 break;
             case SyntaxKind.CloseBraceToken:
                 this.ExitGroup(token);
                 break;
             case SyntaxKind.OpenBracketToken:
                 this.EnterGroup(token);
                 break;
             case SyntaxKind.CloseBracketToken:
                 this.ExitGroup(token);
                 break;
             case SyntaxKind.BarToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.BackslashToken:
                 throw new NotSupportedException(token.Kind().ToString());
             case SyntaxKind.ColonToken:
                 switch (token.Parent.Kind())
                 {
                     case SyntaxKind.ConditionalExpression:
                         this.ProcessBinaryOperator(token);
                         break;
                     default:
                         throw new NotSupportedException("Parent kind " + token.Parent.Kind() + " for " + token.Kind());
                 }
                 break;
             case SyntaxKind.SemicolonToken:
                 this.ProcessSemicolon(token);
                 break;
             case SyntaxKind.DoubleQuoteToken:
             case SyntaxKind.SingleQuoteToken:
                 throw new NotSupportedException("XML");
             case SyntaxKind.LessThanToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.CommaToken:
                 this.ProcessComma(token);
                 break;
             case SyntaxKind.GreaterThanToken:
                 this.ProcessBinaryOperator(token); break;
                 break;
             case SyntaxKind.DotToken:
                 this.ProcessAccessor(token);
                 break;
             case SyntaxKind.QuestionToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.HashToken:
                 throw new NotSupportedException("TRIVIA");
             case SyntaxKind.SlashToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.SlashGreaterThanToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.LessThanSlashToken:
             case SyntaxKind.XmlCommentStartToken:
             case SyntaxKind.XmlCommentEndToken:
             case SyntaxKind.XmlCDataStartToken:
             case SyntaxKind.XmlCDataEndToken:
             case SyntaxKind.XmlProcessingInstructionStartToken:
             case SyntaxKind.XmlProcessingInstructionEndToken:
                 throw new NotSupportedException("XML");
             case SyntaxKind.BarBarToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.AmpersandAmpersandToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.MinusMinusToken:
                 this.ProcessUnaryOperator(token);
                 break;
             case SyntaxKind.PlusPlusToken:
                 this.ProcessUnaryOperator(token);
                 break;
             case SyntaxKind.ColonColonToken:
                 throw new NotSupportedException(token.Kind().ToString());
             case SyntaxKind.QuestionQuestionToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.MinusGreaterThanToken:
                 this.ProcessAccessor(token);
                 break;
             case SyntaxKind.ExclamationEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.EqualsEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.EqualsGreaterThanToken:
                 this.ProcessLambdaOperator(token);
                 break;
             case SyntaxKind.LessThanEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.LessThanLessThanToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.LessThanLessThanEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.GreaterThanEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.GreaterThanGreaterThanToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.GreaterThanGreaterThanEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.SlashEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.AsteriskEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.BarEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.AmpersandEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.PlusEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.MinusEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.CaretEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.PercentEqualsToken:
                 this.ProcessBinaryOperator(token);
                 break;
             case SyntaxKind.InterpolatedStringStartToken:
             case SyntaxKind.InterpolatedStringEndToken:
             case SyntaxKind.InterpolatedVerbatimStringStartToken:
                 throw new NotSupportedException("C#6");
             case SyntaxKind.OmittedTypeArgumentToken:
             case SyntaxKind.OmittedArraySizeExpressionToken:
                 break; // no-op
             case SyntaxKind.EndOfDirectiveToken:
             case SyntaxKind.EndOfDocumentationCommentToken:
                 throw new InvalidOperationException("TRIVIA");
             case SyntaxKind.EndOfFileToken:
                 break;
             case SyntaxKind.BadToken:
                 throw new NotSupportedException("BAD");
             case SyntaxKind.IdentifierToken:
             case SyntaxKind.NumericLiteralToken:
             case SyntaxKind.CharacterLiteralToken:
             case SyntaxKind.StringLiteralToken:
                 this.ProcessIdentifierOrLiteral(token);
                 break;
             case SyntaxKind.XmlEntityLiteralToken:
             case SyntaxKind.XmlTextLiteralToken:
             case SyntaxKind.XmlTextLiteralNewLineToken:
                 throw new InvalidOperationException("XML");
             case SyntaxKind.InterpolatedStringToken:
             case SyntaxKind.InterpolatedStringTextToken:
                 throw new NotSupportedException("C#6");
             case SyntaxKind.SkippedTokensTrivia:
                 throw new NotSupportedException("Skipped");
             default:
                 throw new InvalidOperationException("Unexpected kind " + token.Kind());
         }
     }
 }
 private static IEnumerable<SyntaxToken> GetDescendantCloseBraceTokens(SyntaxNode node)
 {
     return node.DescendantTokens().Where(token => token.IsKind(SyntaxKind.CloseBraceToken));
 }
        private static Dictionary<string, List<int>> CreateIdentifierLocations(Document document, SyntaxNode root, CancellationToken cancellationToken)
        {
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            var identifierMap = SharedPools.StringIgnoreCaseDictionary<List<int>>().AllocateAndClear();
            foreach (var token in root.DescendantTokens(descendIntoTrivia: true))
            {
                if (token.IsMissing || token.Span.Length == 0)
                {
                    continue;
                }

                if (syntaxFacts.IsIdentifier(token) || syntaxFacts.IsGlobalNamespaceKeyword(token))
                {
                    var valueText = token.ValueText;
                    identifierMap.GetOrAdd(valueText, _ => SharedPools.BigDefault<List<int>>().AllocateAndClear()).Add(token.Span.Start);
                }
            }

            return identifierMap;
        }
        /// <summary>
        /// Close braces should never have a newline between the last line of content and the 
        /// closing brace.  Also want to remove consecutive new lines before any comments or
        /// #pragma that preceeds the close brace.
        /// </summary>
        private static SyntaxNode FixCloseBraces(SyntaxNode syntaxNode)
        {
            var tokensToReplace = syntaxNode.DescendantTokens().Where((token) =>
                {
                    return
                        token.Kind() == SyntaxKind.CloseBraceToken &&
                        token.HasLeadingTrivia &&
                        (IsSimpleNewLine(token.LeadingTrivia, 0) || IsSimpleNewLine(token.LeadingTrivia, token.LeadingTrivia.Count - 1));
                });

            return syntaxNode.ReplaceTokens(tokensToReplace, (_, y) => FixCloseBraceLeadingTrivia(y));
        }
Esempio n. 15
0
        private int CountSingleLineBraces(SyntaxNode root)
        {
            var braces = root.DescendantTokens().Where(t => t.RawKind == OpenBraceToken 
                                                         || t.RawKind == CloseBraceToken);

            return braces.Select(brace => root.SyntaxTree.GetLineSpan(brace.Span).StartLinePosition.Line)
                .Select(lineNumber => root.SyntaxTree.GetText().Lines[lineNumber])
                .Count(line => line.ToString().Trim().Length == 1);
        }
Esempio n. 16
0
        private SelectionInfo CheckErrorCasesAndAppendDescriptions(SelectionInfo selectionInfo, SyntaxNode root, CancellationToken cancellationToken)
        {
            if (selectionInfo.Status.FailedWithNoBestEffortSuggestion())
            {
                return selectionInfo;
            }

            if (selectionInfo.FirstTokenInFinalSpan.IsMissing || selectionInfo.LastTokenInFinalSpan.IsMissing)
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.ContainsInvalidSelection));
            }

            // get the node that covers the selection
            var commonNode = selectionInfo.FirstTokenInFinalSpan.GetCommonRoot(selectionInfo.LastTokenInFinalSpan);

            if ((selectionInfo.SelectionInExpression || selectionInfo.SelectionInSingleStatement) && commonNode.HasDiagnostics())
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.TheSelectionContainsSyntacticErrors));
            }

            var tokens = root.DescendantTokens(selectionInfo.FinalSpan);
            if (tokens.ContainPreprocessorCrossOver(selectionInfo.FinalSpan))
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.BestEffort, CSharpFeaturesResources.SelectionCanNotCrossOverPreprocessorDirectives));
            }

            // TODO : check whether this can be handled by control flow analysis engine
            if (tokens.Any(t => t.Kind() == SyntaxKind.YieldKeyword))
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.BestEffort, CSharpFeaturesResources.SelectionCanNotContainAYieldStatement));
            }

            // TODO : check behavior of control flow analysis engine around exception and exception handling.
            if (tokens.ContainArgumentlessThrowWithoutEnclosingCatch(selectionInfo.FinalSpan))
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.BestEffort, CSharpFeaturesResources.SelectionCanNotContainThrowStatement));
            }

            if (selectionInfo.SelectionInExpression && commonNode.PartOfConstantInitializerExpression())
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.SelectionCanNotBePartOfConstInitializerExpr));
            }

            if (commonNode.IsUnsafeContext())
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(s.Flag, CSharpFeaturesResources.TheSelectedCodeIsInsideAnUnsafeContext));
            }

            var selectionChanged = selectionInfo.FirstTokenInOriginalSpan != selectionInfo.FirstTokenInFinalSpan || selectionInfo.LastTokenInOriginalSpan != selectionInfo.LastTokenInFinalSpan;
            if (selectionChanged)
            {
                selectionInfo = selectionInfo.WithStatus(s => s.MarkSuggestion());
            }

            return selectionInfo;
        }
        private SelectionInfo CheckErrorCasesAndAppendDescriptions(SelectionInfo selectionInfo, SyntaxNode root, CancellationToken cancellationToken)
        {
            if (selectionInfo.Status.FailedWithNoBestEffortSuggestion())
            {
                return selectionInfo;
            }

            if (selectionInfo.FirstTokenInFinalSpan.IsMissing || selectionInfo.LastTokenInFinalSpan.IsMissing)
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.Contains_invalid_selection));
            }

            // get the node that covers the selection
            var commonNode = selectionInfo.FirstTokenInFinalSpan.GetCommonRoot(selectionInfo.LastTokenInFinalSpan);

            if ((selectionInfo.SelectionInExpression || selectionInfo.SelectionInSingleStatement) && commonNode.HasDiagnostics())
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.The_selection_contains_syntactic_errors));
            }

            var tokens = root.DescendantTokens(selectionInfo.FinalSpan);
            if (tokens.ContainPreprocessorCrossOver(selectionInfo.FinalSpan))
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.BestEffort, CSharpFeaturesResources.Selection_can_not_cross_over_preprocessor_directives));
            }

            // TODO : check whether this can be handled by control flow analysis engine
            if (tokens.Any(t => t.Kind() == SyntaxKind.YieldKeyword))
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.BestEffort, CSharpFeaturesResources.Selection_can_not_contain_a_yield_statement));
            }

            // TODO : check behavior of control flow analysis engine around exception and exception handling.
            if (tokens.ContainArgumentlessThrowWithoutEnclosingCatch(selectionInfo.FinalSpan))
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.BestEffort, CSharpFeaturesResources.Selection_can_not_contain_throw_statement));
            }

            if (selectionInfo.SelectionInExpression && commonNode.PartOfConstantInitializerExpression())
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.Selection_can_not_be_part_of_constant_initializer_expression));
            }

            if (commonNode.IsUnsafeContext())
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(s.Flag, CSharpFeaturesResources.The_selected_code_is_inside_an_unsafe_context));
            }

            // For now patterns are being blanket disabled for extract method.  This issue covers designing extractions for them
            // and re-enabling this. 
            // https://github.com/dotnet/roslyn/issues/9244
            if (commonNode.Kind() == SyntaxKind.IsPatternExpression)
            {
                selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.Selection_can_not_contain_a_pattern_expression));
            }

            var selectionChanged = selectionInfo.FirstTokenInOriginalSpan != selectionInfo.FirstTokenInFinalSpan || selectionInfo.LastTokenInOriginalSpan != selectionInfo.LastTokenInFinalSpan;
            if (selectionChanged)
            {
                selectionInfo = selectionInfo.WithStatus(s => s.MarkSuggestion());
            }

            return selectionInfo;
        }