示例#1
0
        public ITriviaSavedResult SaveTriviaAroundSelection(SyntaxNode root, TextSpan textSpan)
        {
            Contract.ThrowIfNull(root);
            Contract.ThrowIfTrue(textSpan.IsEmpty);
            Debug.Assert(Enum.GetNames(typeof(TriviaLocation)).Length == TriviaLocationsCount);

            var tokens = GetTokensAtEdges(root, textSpan);

            // span must contain after and before spans at the both edges
            Contract.ThrowIfFalse(
                textSpan.Contains(tokens[TriviaLocation.AfterBeginningOfSpan].Span) &&
                textSpan.Contains(tokens[TriviaLocation.BeforeEndOfSpan].Span)
                );

            var triviaList = GetTriviaAtEdges(tokens, textSpan);

            var annotations = Enumerable
                              .Range((int)TriviaLocation.BeforeBeginningOfSpan, TriviaLocationsCount)
                              .Cast <TriviaLocation>()
                              .ToDictionary(location => location, _ => new SyntaxAnnotation());

            var map = CreateOldToNewTokensMap(tokens, annotations);
            var rootWithAnnotation = ReplaceTokens(root, map.Keys, (o, n) => map[o]);

            return(CreateResult(rootWithAnnotation, annotations, triviaList));
        }
示例#2
0
        public void TextSpanContains00()
        {
            TextSpan span = new TextSpan(0, 10);

            Assert.True(span.Contains(3));
            Assert.False(span.Contains(30));
            Assert.False(span.Contains(11));
            Assert.False(span.Contains(-1));
        }
示例#3
0
        /// <summary>
        /// Find all regions in a file and get there start and end line
        /// </summary>
        /// <param name="tree">SyntaxTree for the given file</param>
        /// <param name="span">Start and end line in which we search for regions</param>
        /// <returns>Flat list of regions</returns>
        public static List <CodeRegionItem> MapRegions(SyntaxTree tree, TextSpan span, ICodeViewUserControl control)
        {
            var regionList = new List <CodeRegionItem>();

            if (tree == null)
            {
                return(regionList);
            }

            if (SettingsHelper.FilterRules != null)
            {
                var filterRule = SettingsHelper.FilterRules.LastOrDefault(f => f.Kind == CodeItemKindEnum.Region || f.Kind == CodeItemKindEnum.All);

                if (filterRule != null && filterRule.Ignore)
                {
                    return(regionList);
                }
            }

            var root = tree.GetRoot();

            // Find all start points of regions
            foreach (var regionDirective in root.DescendantTrivia()
                     .Where(i => (i.RawKind == (int)SyntaxKind.RegionDirectiveTrivia ||
                                  i.RawKind == (int)VisualBasic.SyntaxKind.RegionDirectiveTrivia) &&
                            span.Contains(i.Span)))
            {
                regionList.Add(MapRegion(regionDirective, control));
            }

            if (!regionList.Any())
            {
                return(regionList);
            }

            // Find all matching end points of regions
            foreach (var endRegionDirective in root.DescendantTrivia()
                     .Where(j => (j.RawKind == (int)SyntaxKind.EndRegionDirectiveTrivia ||
                                  j.RawKind == (int)VisualBasic.SyntaxKind.EndRegionDirectiveTrivia) &&
                            span.Contains(j.Span)))
            {
                var reg = regionList.LastOrDefault(x => x.StartLine < GetStartLine(endRegionDirective) && x.EndLine == 0);
                if (reg != null)
                {
                    reg.EndLine         = GetEndLine(endRegionDirective);
                    reg.EndLinePosition = GetEndLinePosition(endRegionDirective);
                }
            }

            var list = ToHierarchy(regionList, int.MinValue, int.MaxValue);

            return(list.Select(r => r as CodeRegionItem).ToList());
        }
示例#4
0
        public static async Task ComputeRefactoringAsync(RefactoringContext context, ClassDeclarationSyntax classDeclaration)
        {
            SyntaxToken identifier = classDeclaration.Identifier;

            if (identifier.IsMissing)
            {
                return;
            }

            TextSpan span = identifier.Span;

            BaseListSyntax baseList = classDeclaration.BaseList;

            if (baseList != null)
            {
                span = TextSpan.FromBounds(span.Start, baseList.Span.End);
            }

            TypeParameterListSyntax typeParameterList = classDeclaration.TypeParameterList;

            if (typeParameterList != null)
            {
                span = TextSpan.FromBounds(span.Start, typeParameterList.Span.End);
            }

            if (!span.Contains(context.Span))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            INamedTypeSymbol classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration, context.CancellationToken);

            if (classSymbol?.IsErrorType() != false)
            {
                return;
            }

            if (classSymbol.IsStatic)
            {
                return;
            }

            foreach (INamedTypeSymbol interfaceSymbol in classSymbol.AllInterfaces)
            {
                if (interfaceSymbol.HasMetadataName(MetadataNames.System_IEquatable_T) &&
                    interfaceSymbol.TypeArguments.Single().Equals(classSymbol))
                {
                    return;
                }
            }

            INamedTypeSymbol equatableSymbol = semanticModel.GetTypeByMetadataName("System.IEquatable`1").Construct(classSymbol);

            context.RegisterRefactoring(
                GetTitle(equatableSymbol, semanticModel, classDeclaration.SpanStart),
                f => RefactorAsync(context.Document, classDeclaration, classSymbol, equatableSymbol, semanticModel, f),
                RefactoringIdentifiers.ImplementIEquatableOfT);
        }
示例#5
0
        private static bool SpanInvolvesLocalFunction(TextSpan finalSpan, SemanticModel model, SyntaxNode root)
        {
            var nodes = root.DescendantNodes(finalSpan).Where(n => finalSpan.Contains(n.Span));

            foreach (var node in nodes)
            {
                if (node.IsKind(SyntaxKind.LocalFunctionStatement))
                {
                    return(true);
                }

                if (node is IdentifierNameSyntax id)
                {
                    var symbolInfo = model.GetSymbolInfo(id);
                    if (symbolInfo.Symbol is IMethodSymbol method &&
                        method.MethodKind == MethodKind.LocalFunction)
                    {
                        return(true);
                    }
                }

                if (node.HasAncestor <LocalFunctionStatementSyntax>())
                {
                    return(true);
                }
            }
            return(false);
        }
        public static bool IsApplicableSpan(InitializerExpressionSyntax initializer, TextSpan span)
        {
            SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions;

            if (!expressions.Any())
            {
                return(true);
            }

            if (span.IsEmpty)
            {
                if (expressions.Count == expressions.SeparatorCount &&
                    TextSpan.FromBounds(expressions.GetSeparator(expressions.Count - 1).Span.End, initializer.CloseBraceToken.SpanStart).Contains(span))
                {
                    return(true);
                }

                TextSpan span2 = TextSpan.FromBounds(expressions.Last().Span.End, initializer.CloseBraceToken.SpanStart);

                if (span2.Length > 0)
                {
                    span2 = new TextSpan(span2.Start + 1, span2.Length - 1);

                    if (span2.Contains(span))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
示例#7
0
        private bool GetOuterMostTupleExpressionInSpan(
            SyntaxNode root,
            int position,
            ISyntaxFactsService syntaxFacts,
            TextSpan currentSpan,
            CancellationToken cancellationToken,
            [NotNullWhen(true)] out TupleExpressionSyntax?result
            )
        {
            result = null;
            while (
                TryGetTupleExpression(
                    SignatureHelpTriggerReason.InvokeSignatureHelpCommand,
                    root,
                    position,
                    syntaxFacts,
                    cancellationToken,
                    out var expression
                    )
                )
            {
                if (!currentSpan.Contains(expression.Span))
                {
                    break;
                }

                result   = expression;
                position = expression.SpanStart;
            }

            return(result != null);
        }
示例#8
0
        public static bool ContainArgumentlessThrowWithoutEnclosingCatch(
            this IEnumerable <SyntaxToken> tokens,
            TextSpan textSpan
            )
        {
            foreach (var token in tokens)
            {
                if (token.Kind() != SyntaxKind.ThrowKeyword)
                {
                    continue;
                }

                if (
                    !(token.Parent is ThrowStatementSyntax throwStatement) ||
                    throwStatement.Expression != null
                    )
                {
                    continue;
                }

                var catchClause = token.GetAncestor <CatchClauseSyntax>();
                if (catchClause == null || !textSpan.Contains(catchClause.Span))
                {
                    return(true);
                }
            }

            return(false);
        }
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, ParameterSyntax parameter)
        {
            if (!context.IsAnyRefactoringEnabled(
                    RefactoringIdentifiers.AddIdentifierToParameter,
                    RefactoringIdentifiers.RenameParameterAccordingToTypeName))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

            if (parameterSymbol?.Type == null)
            {
                return;
            }

            if (parameter.Identifier.IsMissing)
            {
                if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddIdentifierToParameter))
                {
                    TextSpan span = (parameter.Type != null)
                        ? TextSpan.FromBounds(parameter.Type.Span.End, parameter.Span.End)
                        : parameter.Span;

                    if (span.Contains(context.Span))
                    {
                        string name = NameGenerator.CreateName(parameterSymbol.Type, firstCharToLower: true);

                        if (!string.IsNullOrEmpty(name))
                        {
                            context.RegisterRefactoring(
                                $"Add identifier '{name}'",
                                cancellationToken => AddParameterNameToParameterAsync(context.Document, parameter, name, cancellationToken),
                                RefactoringIdentifiers.AddIdentifierToParameter);
                        }
                    }
                }
            }
            else if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenameParameterAccordingToTypeName) &&
                     parameter.Identifier.Span.Contains(context.Span))
            {
                string oldName = parameter.Identifier.ValueText;

                string newName = NameGenerator.Default.CreateUniqueParameterName(
                    oldName,
                    parameterSymbol,
                    semanticModel,
                    cancellationToken: context.CancellationToken);

                if (newName != null)
                {
                    context.RegisterRefactoring(
                        $"Rename '{oldName}' to '{newName}'",
                        cancellationToken => Renamer.RenameSymbolAsync(context.Solution, parameterSymbol, newName, default(OptionSet), cancellationToken),
                        RefactoringIdentifiers.RenameParameterAccordingToTypeName);
                }
            }
        }
示例#10
0
        private static List <MemberDeclarationSyntax> GetMembersInSpan(
            TextSpan textSpan,
            TypeDeclarationSyntax containingType,
            MemberDeclarationSyntax firstMember)
        {
            List <MemberDeclarationSyntax> selectedMembers = null;

            var members    = containingType.Members;
            var fieldIndex = members.IndexOf(firstMember);

            if (fieldIndex < 0)
            {
                return(null);
            }

            for (var i = fieldIndex; i < members.Count; i++)
            {
                var member = members[i];
                if (textSpan.Contains(member.Span))
                {
                    selectedMembers = selectedMembers ?? new List <MemberDeclarationSyntax>();
                    selectedMembers.Add(member);
                }
                else if (textSpan.OverlapsWith(member.Span))
                {
                    return(null);
                }
                else
                {
                    break;
                }
            }

            return(selectedMembers);
        }
示例#11
0
        private static bool CheckTrivia(ElseClauseSyntax elseClause, IfStatementSyntax ifStatement)
        {
            TextSpan elseSpan = elseClause.Span;
            TextSpan ifSpan   = ifStatement.Span;

            TextSpan span  = TextSpan.FromBounds(elseSpan.Start, ifSpan.Start);
            TextSpan span2 = TextSpan.FromBounds(ifSpan.End, elseSpan.End);

            foreach (SyntaxTrivia trivia in elseClause.DescendantTrivia())
            {
                TextSpan triviaSpan = trivia.Span;

                if (span.Contains(triviaSpan))
                {
                    if (!trivia.IsWhitespaceOrEndOfLineTrivia())
                    {
                        return(false);
                    }
                }
                else if (span2.Contains(triviaSpan))
                {
                    if (!trivia.IsWhitespaceOrEndOfLineTrivia())
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#12
0
        public static IEnumerable <TSyntaxNode> Traverse <TSyntaxNode>(
            this SyntaxNode node, TextSpan searchSpan, Func <SyntaxNode, bool> predicate)
            where TSyntaxNode : SyntaxNode
        {
            Contract.ThrowIfNull(node);

            var nodes = new LinkedList <SyntaxNode>();

            nodes.AddFirst(node);

            while (nodes.Count > 0)
            {
                var currentNode = nodes.First.Value;
                nodes.RemoveFirst();

                if (currentNode != null && searchSpan.Contains(currentNode.FullSpan) && predicate(currentNode))
                {
                    if (currentNode is TSyntaxNode tSyntax)
                    {
                        yield return(tSyntax);
                    }

                    nodes.AddRangeAtHead(currentNode.ChildNodes());
                }
            }
        }
        private ImmutableArray <DiagnosticData> AdjustInitialDiagnostics(
            Solution solution, UpdatedEventArgs args, CancellationToken cancellationToken)
        {
            // we only reach here if there is the document
            var document = solution.GetDocument(args.DocumentId);

            // if there is no source text for this document, we don't populate the initial tags. this behavior is equivalent of existing
            // behavior in OnDiagnosticsUpdated.
            if (!document.TryGetText(out var text))
            {
                return(ImmutableArray <DiagnosticData> .Empty);
            }

            // GetDiagnostics returns whatever cached diagnostics in the service which can be stale ones. for example, build error will be most likely stale
            // diagnostics. so here we make sure we filter out any diagnostics that is not in the text range.
            var builder = ArrayBuilder <DiagnosticData> .GetInstance();

            var fullSpan = new TextSpan(0, text.Length);

            foreach (var diagnostic in diagService.GetDiagnostics(
                         args.Workspace, args.ProjectId, args.DocumentId, args.Id, includeSuppressedDiagnostics: false, cancellationToken: cancellationToken))
            {
                if (fullSpan.Contains(diagnostic.GetExistingOrCalculatedTextSpan(text)))
                {
                    builder.Add(diagnostic);
                }
            }

            return(builder.ToImmutableAndFree());
        }
示例#14
0
        static public (IXor2ComputationNodeReference, AlreadyProcessedSyntaxNodes) FromReturnStatement(ReturnStatementSyntax returnSyntax, MethodBlockAnalysis methodAnalysis, TextSpan span, AlreadyProcessedSyntaxNodes processedNodesOrNull = null)
        {
            Throw.IfNot(methodAnalysis.DataFlowAnalysis.Succeeded);


            var processedNodes = (processedNodesOrNull ?? new AlreadyProcessedSyntaxNodes());

            if (!span.Contains(returnSyntax.Span))
            {
                return(_CreatePair(Xor2ComputationNodeReference.OutOfScope(returnSyntax), processedNodes));
            }

            var rhsSyntax = SyntaxOperations.GetRightHandSideExpression(returnSyntax);

            var previous = _DispatchXor7ExpressionSyntax(rhsSyntax, methodAnalysis, processedNodes ?? new AlreadyProcessedSyntaxNodes(), span);

            var node = ComputationGraphNode.FromReturnStatement(returnSyntax, previous.Item1);


            if (!previous.Item1.IsA)
            {
                return(_CreatePair(node, previous.Item2));
            }


            return(_CreatePair(node, previous.Item2));
        }
示例#15
0
        public static async Task ComputeRefactoringAsync(RefactoringContext context, StructDeclarationSyntax structDeclaration)
        {
            SyntaxToken identifier = structDeclaration.Identifier;

            if (identifier.IsMissing)
            {
                return;
            }

            TextSpan span = identifier.Span;

            BaseListSyntax baseList = structDeclaration.BaseList;

            if (baseList != null)
            {
                span = TextSpan.FromBounds(span.Start, baseList.Span.End);
            }

            TypeParameterListSyntax typeParameterList = structDeclaration.TypeParameterList;

            if (typeParameterList != null)
            {
                span = TextSpan.FromBounds(span.Start, typeParameterList.Span.End);
            }

            if (!span.Contains(context.Span))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            INamedTypeSymbol typeSymbol = semanticModel.GetDeclaredSymbol(structDeclaration, context.CancellationToken);

            if (typeSymbol?.IsErrorType() != false)
            {
                return;
            }

            INamedTypeSymbol equatableSymbol = semanticModel.GetTypeByMetadataName(MetadataNames.System_IEquatable_T);

            if (equatableSymbol == null)
            {
                return;
            }

            equatableSymbol = equatableSymbol.Construct(typeSymbol);

            if (typeSymbol.Implements(equatableSymbol, allInterfaces: true))
            {
                return;
            }

            context.RegisterRefactoring(
                GetTitle(equatableSymbol, semanticModel, structDeclaration.SpanStart),
                f => RefactorAsync(context.Document, structDeclaration, typeSymbol, equatableSymbol, semanticModel, f),
                RefactoringIdentifiers.ImplementIEquatableOfT);
        }
示例#16
0
        /// <summary>
        /// <para>
        /// Determines if a <paramref name="node"/> is underselected given <paramref name="selection"/>.
        /// </para>
        /// <para>
        /// Underselection is defined as omitting whole nodes from either the beginning or the end. It can be used e.g. to detect that
        /// following selection `1 + [|2 + 3|]` is underselecting the whole expression node tree.
        /// </para>
        /// <para>
        /// Returns false if only and precisely one <see cref="SyntaxToken"/> is selected. In that case the <paramref name="selection"/>
        /// is treated more as a caret location.
        /// </para>
        /// <para>
        /// It's intended to be used in conjunction with <see cref="IRefactoringHelpersService.GetRelevantNodesAsync{TSyntaxNode}(Document, TextSpan, CancellationToken)"/>
        /// that, for non-empty selections, returns the smallest encompassing node. A node that can, for certain refactorings, be too large given user-selection even though
        /// it is the smallest that can be retrieved.
        /// </para>
        /// <para>
        /// When <paramref name="selection"/> doesn't intersect the node in any way it's not considered to be underselected.
        /// </para>
        /// <para>
        /// Null node is always considered underselected.
        /// </para>
        /// </summary>
        public static bool IsNodeUnderselected(SyntaxNode?node, TextSpan selection)
        {
            // Selection is null -> it's always underselected
            // REASON: Easier API use -> underselected node, don't work on it further
            if (node == null)
            {
                return(true);
            }

            // Selection or node is empty -> can't be underselected
            if (selection.IsEmpty || node.Span.IsEmpty)
            {
                return(false);
            }

            // Selection is larger than node.Span -> can't be underselecting
            if (selection.Contains(node.Span))
            {
                return(false);
            }

            // Selection doesn't intersect node -> can't be underselecting.
            // RATIONALE: If there's no intersection then we got the node in some other way, e.g.
            // extracting it after user selected `;` at the end of an expression statement
            // `foo()[|;|]` for `foo()` node.
            if (!node.FullSpan.OverlapsWith(selection))
            {
                return(false);
            }

            // Only precisely one token of the node is selected -> treat is as empty selection -> not
            // underselected. The rationale is that if only one Token is selected then the selection
            // wasn't about precisely getting the one node and nothing else & therefore we should treat
            // it as empty selection.
            if (node.FullSpan.Contains(selection.Start))
            {
                var selectionStartToken = node.FindToken(selection.Start);
                if (selection.IsAround(selectionStartToken))
                {
                    return(false);
                }
            }

            var beginningNode = node.FindToken(node.Span.Start).Parent;
            var endNode       = node.FindToken(node.Span.End - 1).Parent;

            RoslynDebug.Assert(beginningNode is object);
            RoslynDebug.Assert(endNode is object);

            // Node is underselected if either the first (lowest) child doesn't contain start of selection
            // of the last child doesn't intersect with the end.

            // Node is underselected if either the first (lowest) child ends before the selection has started
            // or the last child starts after the selection ends (i.e. one of them is completely on the outside of selection).
            // It's a crude heuristic but it allows omitting parts of nodes or trivial tokens from the beginning/end
            // but fires up e.g.: `1 + [|2 + 3|]`.
            return(beginningNode.Span.End <= selection.Start || endNode.Span.Start >= selection.End);
        }
            public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
            {
                if (_textSpan.Contains(trivia.Span))
                {
                    return(SyntaxFactory.Whitespace(trivia.ToString().Replace("\t", "    ")));
                }

                return(base.VisitTrivia(trivia));
            }
示例#18
0
        internal static void ApplyNewTree(TextEditor editor, int startOffset, bool exact, TextSpan span, Microsoft.CodeAnalysis.SyntaxTree syntaxTree, Microsoft.CodeAnalysis.SyntaxTree newTree)
        {
            var caretOffset    = editor.CaretOffset;
            var caretEndOffset = caretOffset;

            using (var undo = editor.OpenUndoGroup()) {
                int delta = 0;
                foreach (var change in newTree.GetChanges(syntaxTree))
                {
                    if (!exact && change.Span.Start >= caretOffset)
                    {
                        continue;
                    }
                    if (exact && !span.Contains(change.Span.Start))
                    {
                        continue;
                    }
                    var newText   = change.NewText;
                    var length    = change.Span.Length;
                    var changeEnd = delta + change.Span.End - 1;
                    if (changeEnd < editor.Length && changeEnd >= 0 && editor.GetCharAt(changeEnd) == '\r')
                    {
                        length--;
                    }
                    var replaceOffset = delta + change.Span.Start;
                    editor.ReplaceText(replaceOffset, length, newText);
                    delta = delta - length + newText.Length;
                    if (change.Span.Start < caretOffset)
                    {
                        if (change.Span.End < caretOffset)
                        {
                            caretEndOffset += newText.Length - length;
                        }
                        else
                        {
                            caretEndOffset = replaceOffset;
                        }
                    }
                }
            }

            if (startOffset < caretOffset)
            {
                if (0 <= caretEndOffset && caretEndOffset < editor.Length)
                {
                    editor.CaretOffset = caretEndOffset;
                }
                if (editor.CaretColumn == 1)
                {
                    if (editor.CaretLine > 1 && editor.GetLine(editor.CaretLine - 1).Length == 0)
                    {
                        editor.CaretLine--;
                    }
                    editor.CaretColumn = editor.GetVirtualIndentationColumn(editor.CaretLine);
                }
            }
        }
示例#19
0
            public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
            {
                if (_textSpan.Contains(trivia.Span))
                {
                    return(SyntaxFactory.Whitespace(string.Empty));
                }

                return(base.VisitTrivia(trivia));
            }
示例#20
0
        private static bool ContainsInterleavedDirective(
            TextSpan textSpan,
            SyntaxTrivia trivia,
            CancellationToken cancellationToken)
        {
            if (trivia.HasStructure)
            {
                var structure  = trivia.GetStructure();
                var parentSpan = structure.Span;
                if (trivia.GetStructure().IsKind(SyntaxKind.RegionDirectiveTrivia,
                                                 SyntaxKind.EndRegionDirectiveTrivia,
                                                 SyntaxKind.IfDirectiveTrivia,
                                                 SyntaxKind.EndIfDirectiveTrivia))
                {
                    var match = ((DirectiveTriviaSyntax)structure).GetMatchingDirective(cancellationToken);
                    if (match != null)
                    {
                        var matchSpan = match.Span;
                        if (!textSpan.Contains(matchSpan.Start))
                        {
                            // The match for this pp directive is outside
                            // this node.
                            return(true);
                        }
                    }
                }
                else if (trivia.GetStructure().IsKind(SyntaxKind.ElseDirectiveTrivia, SyntaxKind.ElifDirectiveTrivia))
                {
                    var directives = ((DirectiveTriviaSyntax)structure).GetMatchingConditionalDirectives(cancellationToken);
                    if (directives != null && directives.Count > 0)
                    {
                        if (!textSpan.Contains(directives[0].SpanStart) ||
                            !textSpan.Contains(directives[directives.Count - 1].SpanStart))
                        {
                            // This else/elif belongs to a pp span that isn't
                            // entirely within this node.
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
示例#21
0
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, ParameterSyntax parameter)
        {
            if (!context.IsAnyRefactoringEnabled(
                    RefactoringIdentifiers.AddParameterNameToParameter,
                    RefactoringIdentifiers.RenameParameterAccordingToTypeName))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

            if (parameterSymbol?.Type == null)
            {
                return;
            }

            if (parameter.Identifier.IsMissing)
            {
                if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddParameterNameToParameter))
                {
                    TextSpan span = (parameter.Type != null)
                        ? TextSpan.FromBounds(parameter.Type.Span.End, parameter.Span.End)
                        : parameter.Span;

                    if (span.Contains(context.Span))
                    {
                        string name = SyntaxUtility.CreateIdentifier(parameterSymbol.Type, firstCharToLower: true);

                        if (!string.IsNullOrEmpty(name))
                        {
                            context.RegisterRefactoring(
                                $"Add parameter name '{name}'",
                                cancellationToken => AddParameterNameToParameterAsync(context.Document, parameter, name, cancellationToken));
                        }
                    }
                }
            }
            else if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenameParameterAccordingToTypeName) &&
                     parameter.Identifier.Span.Contains(context.Span))
            {
                string name    = parameter.Identifier.ValueText;
                string newName = SyntaxUtility.CreateIdentifier(parameterSymbol.Type, firstCharToLower: true);

                if (!string.IsNullOrEmpty(newName) &&
                    !string.Equals(name, newName, StringComparison.Ordinal))
                {
                    ISymbol symbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

                    context.RegisterRefactoring(
                        $"Rename parameter to '{newName}'",
                        cancellationToken => SymbolRenamer.RenameAsync(context.Document, symbol, newName, cancellationToken));
                }
            }
        }
        public static Task <Document> RefactorAsync(
            Document document,
            MemberDeclarationSyntax declaration,
            TextSpan span,
            CancellationToken cancellationToken)
        {
            MemberDeclarationSyntax newDeclaration = declaration;

            ImmutableArray <string> comments;

            SyntaxTriviaList leadingTrivia = declaration.GetLeadingTrivia();

            if (leadingTrivia.Span.Contains(span))
            {
                comments = leadingTrivia
                           .Where(f => span.Contains(f.Span) && f.Kind() == SyntaxKind.SingleLineCommentTrivia)
                           .Select(f => _leadingSlashesRegex.Replace(f.ToString(), ""))
                           .ToImmutableArray();

                TextSpan spanToRemove = TextSpan.FromBounds(span.Start, declaration.SpanStart);

                newDeclaration = declaration.WithLeadingTrivia(leadingTrivia.Where(f => !spanToRemove.Contains(f.Span)));
            }
            else
            {
                SyntaxTrivia trivia = declaration.FindTrivia(span.Start);

                Debug.Assert(trivia != default(SyntaxTrivia));

                SyntaxToken token = trivia.Token;

                SyntaxTriviaList trailingTrivia = token.TrailingTrivia;

                Debug.Assert(trailingTrivia.Contains(trivia));

                for (int i = 0; i < trailingTrivia.Count; i++)
                {
                    if (trailingTrivia[i].Span == span)
                    {
                        comments = ImmutableArray.Create(_leadingSlashesRegex.Replace(trailingTrivia[i].ToString(), ""));

                        SyntaxToken newToken = token.WithTrailingTrivia(trailingTrivia.Skip(i + 1));

                        newDeclaration = newDeclaration.ReplaceToken(token, newToken);
                        break;
                    }
                }
            }

            var settings = new DocumentationCommentGeneratorSettings(comments);

            newDeclaration = newDeclaration.WithNewSingleLineDocumentationComment(settings);

            return(document.ReplaceNodeAsync(declaration, newDeclaration, cancellationToken));
        }
示例#23
0
        public static bool ContainPreprocessorCrossOver(
            this IEnumerable <SyntaxToken> tokens,
            TextSpan textSpan
            )
        {
            var activeRegions = 0;
            var activeIfs     = 0;

            foreach (var trivia in tokens.GetAllTrivia())
            {
                if (!textSpan.Contains(trivia.Span))
                {
                    continue;
                }

                switch (trivia.Kind())
                {
                case SyntaxKind.RegionDirectiveTrivia:
                    activeRegions++;
                    break;

                case SyntaxKind.EndRegionDirectiveTrivia:
                    if (activeRegions <= 0)
                    {
                        return(true);
                    }

                    activeRegions--;
                    break;

                case SyntaxKind.IfDirectiveTrivia:
                    activeIfs++;
                    break;

                case SyntaxKind.EndIfDirectiveTrivia:
                    if (activeIfs <= 0)
                    {
                        return(true);
                    }

                    activeIfs--;
                    break;

                case SyntaxKind.ElseDirectiveTrivia:
                case SyntaxKind.ElifDirectiveTrivia:
                    if (activeIfs <= 0)
                    {
                        return(true);
                    }
                    break;
                }
            }

            return(activeIfs != 0 || activeRegions != 0);
        }
示例#24
0
        /// <summary>
        /// Find all regions in a file and get there start and end line
        /// </summary>
        /// <param name="tree">SyntaxTree for the given file</param>
        /// <param name="span">Start and end line in which we search for regions</param>
        /// <returns>Flat list of regions</returns>
        public static List <CodeRegionItem> MapRegions(SyntaxTree tree, TextSpan span)
        {
            var regionList = new List <CodeRegionItem>();

            if (tree == null)
            {
                return(regionList);
            }

            var root = tree.GetRoot();

            // Find all start points of regions
            foreach (var regionDirective in root.DescendantTrivia()
                     .Where(i => (i.RawKind == (int)SyntaxKind.RegionDirectiveTrivia ||
                                  i.RawKind == (int)VisualBasic.SyntaxKind.RegionDirectiveTrivia) &&
                            span.Contains(i.Span)))
            {
                regionList.Add(MapRegion(regionDirective));
            }

            if (!regionList.Any())
            {
                return(regionList);
            }

            // Find all matching end points of regions
            foreach (var endRegionDirective in root.DescendantTrivia()
                     .Where(j => (j.RawKind == (int)SyntaxKind.EndRegionDirectiveTrivia ||
                                  j.RawKind == (int)VisualBasic.SyntaxKind.EndRegionDirectiveTrivia) &&
                            span.Contains(j.Span)))
            {
                var reg = regionList.LastOrDefault(x => x.StartLine < GetStartLine(endRegionDirective) && x.EndLine == 0);
                if (reg != null)
                {
                    reg.EndLine = GetEndLine(endRegionDirective);
                }
            }

            var list = ToHierarchy(regionList, int.MinValue, int.MaxValue);

            return(list.Select(r => r as CodeRegionItem).ToList());
        }
示例#25
0
 private static bool IsEmptyAndContainedInSpanOrBetweenSpans(this TextSpan span, TextSpan innerSpan, TextSpan outerSpan)
 {
     if (span.IsEmpty)
     {
         return(innerSpan.Contains(span));
     }
     else
     {
         return(span.IsBetweenSpans(innerSpan, outerSpan));
     }
 }
示例#26
0
        public static bool IsContainedInSpanOrBetweenSpans(this TextSpan span, SyntaxNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            TextSpan innerSpan = node.Span;

            return(innerSpan.Contains(span) || span.IsBetweenSpans(innerSpan, node.FullSpan));
        }
        public static void Refactor(
            CodeRefactoringContext context,
            ParameterSyntax parameter,
            SemanticModel semanticModel)
        {
            if (parameter == null)
            {
                throw new ArgumentNullException(nameof(parameter));
            }

            if (semanticModel == null)
            {
                throw new ArgumentNullException(nameof(semanticModel));
            }

            IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

            if (parameterSymbol?.Type == null)
            {
                return;
            }

            if (parameter.Identifier.IsMissing)
            {
                TextSpan span = (parameter.Type != null)
                    ? TextSpan.FromBounds(parameter.Type.Span.End, parameter.Span.End)
                    : parameter.Span;

                if (span.Contains(context.Span))
                {
                    string name = CreateParameterName(parameterSymbol.Type, semanticModel);

                    if (name != null)
                    {
                        context.RegisterRefactoring(
                            $"Add parameter name '{name}'",
                            cancellationToken => AddParameterNameAccordingToTypeNameRefactorAsync(context.Document, parameter, name, cancellationToken));
                    }
                }
            }
            else if (parameter.Identifier.Span.Contains(context.Span))
            {
                string name = CreateParameterName(parameterSymbol.Type, semanticModel);

                if (name != null)
                {
                    ISymbol symbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

                    context.RegisterRefactoring(
                        $"Rename parameter to '{name}'",
                        cancellationToken => symbol.RenameAsync(name, context.Document, cancellationToken));
                }
            }
        }
示例#28
0
 private static IEnumerable <IdentifierNameSyntax> DescendantIdentifierNames(SyntaxNode node, TextSpan excludedSpan)
 {
     foreach (SyntaxNode descendant in node.DescendantNodes(node.Span))
     {
         if (descendant.IsKind(SyntaxKind.IdentifierName) &&
             !excludedSpan.Contains(descendant.Span))
         {
             yield return((IdentifierNameSyntax)descendant);
         }
     }
 }
示例#29
0
        public void TextSpanContains01()
        {
            TextSpan span_05_15 = new TextSpan(5, 10);
            TextSpan span_03_10 = new TextSpan(3, 7);
            TextSpan span_10_11 = new TextSpan(10, 1);
            TextSpan span_00_03 = new TextSpan(0, 3);

            // non-overlapping
            Assert.False(span_05_15.Contains(span_00_03));
            Assert.False(span_00_03.Contains(span_05_15));

            // overlap with slop
            Assert.True(span_05_15.Contains(span_10_11));

            // same span
            Assert.True(span_05_15.Contains(span_05_15));

            // partial overlap
            Assert.False(span_05_15.Contains(span_03_10));
            Assert.False(span_03_10.Contains(span_05_15));
        }
        public ITriviaSavedResult SaveTriviaAroundSelection(SyntaxNode root, TextSpan textSpan)
        {
            Contract.ThrowIfNull(root);
            Contract.ThrowIfTrue(textSpan.IsEmpty);
            Contract.Requires(Enum.GetNames(typeof(TriviaLocation)).Length == TriviaLocationsCount);

            var tokens = GetTokensAtEdges(root, textSpan);

            // span must contain after and before spans at the both edges
            Contract.ThrowIfFalse(textSpan.Contains(tokens[TriviaLocation.AfterBeginningOfSpan].Span) && textSpan.Contains(tokens[TriviaLocation.BeforeEndOfSpan].Span));

            var triviaList = GetTriviaAtEdges(tokens, textSpan);

            var annotations = Enumerable.Range((int)TriviaLocation.BeforeBeginningOfSpan, TriviaLocationsCount)
                                        .Cast<TriviaLocation>()
                                        .ToDictionary(location => location, _ => new SyntaxAnnotation());

            var map = CreateOldToNewTokensMap(tokens, annotations);
            var rootWithAnnotation = ReplaceTokens(root, map.Keys, (o, n) => map[o]);

            return CreateResult(rootWithAnnotation, annotations, triviaList);
        }
示例#31
0
        private static bool ContainsInterleavedDirective(
            TextSpan textSpan,
            SyntaxTrivia trivia,
            ref SimpleIntervalTree <TextSpan> ifEndIfSpans,
            CancellationToken cancellationToken)
        {
            if (trivia.HasStructure)
            {
                var parentSpan = trivia.GetStructure().Span;
                if (trivia.GetStructure().IsKind(SyntaxKind.RegionDirectiveTrivia) ||
                    trivia.GetStructure().IsKind(SyntaxKind.EndRegionDirectiveTrivia) ||
                    trivia.GetStructure().IsKind(SyntaxKind.IfDirectiveTrivia) ||
                    trivia.GetStructure().IsKind(SyntaxKind.EndIfDirectiveTrivia))
                {
                    var match = ((DirectiveTriviaSyntax)trivia.GetStructure()).GetMatchingDirective(cancellationToken);
                    if (match != null)
                    {
                        var matchSpan = match.Span;
                        if (!textSpan.Contains(matchSpan.Start))
                        {
                            // The match for this pp directive is outside
                            // this node.
                            return(true);
                        }

                        if (trivia.GetStructure().IsKind(SyntaxKind.IfDirectiveTrivia) ||
                            trivia.GetStructure().IsKind(SyntaxKind.EndIfDirectiveTrivia))
                        {
                            var ppSpan = TextSpan.FromBounds(
                                Math.Min(parentSpan.Start, matchSpan.Start),
                                Math.Max(parentSpan.End, matchSpan.End));

                            ifEndIfSpans = ifEndIfSpans.AddInterval(ppSpan);
                        }
                    }
                }
                else if (
                    trivia.GetStructure().IsKind(SyntaxKind.ElseDirectiveTrivia) ||
                    trivia.GetStructure().IsKind(SyntaxKind.ElifDirectiveTrivia))
                {
                    if (!ifEndIfSpans.IntersectsWith(parentSpan.Start))
                    {
                        // This else/elif belongs to a pp span that isn't
                        // entirely within this node.
                        return(true);
                    }
                }
            }

            return(false);
        }
        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;
        }
示例#33
0
        private static List<MemberDeclarationSyntax> GetMembersInSpan(
            TextSpan textSpan,
            TypeDeclarationSyntax containingType,
            MemberDeclarationSyntax firstMember)
        {
            List<MemberDeclarationSyntax> selectedMembers = null;

            var members = containingType.Members;
            var fieldIndex = members.IndexOf(firstMember);
            if (fieldIndex < 0)
            {
                return null;
            }

            for (var i = fieldIndex; i < members.Count; i++)
            {
                var member = members[i];
                if (textSpan.Contains(member.Span))
                {
                    selectedMembers = selectedMembers ?? new List<MemberDeclarationSyntax>();
                    selectedMembers.Add(member);
                }
                else if (textSpan.OverlapsWith(member.Span))
                {
                    return null;
                }
                else
                {
                    break;
                }
            }

            return selectedMembers;
        }
示例#34
0
        private void AdjustIndentationForSpan(
            Document document, ITextEdit edit, TextSpan visibleSpan, IFormattingRule baseIndentationRule, OptionSet options)
        {
            var root = document.GetSyntaxRootAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None);

            using (var rulePool = SharedPools.Default<List<IFormattingRule>>().GetPooledObject())
            using (var spanPool = SharedPools.Default<List<TextSpan>>().GetPooledObject())
            {
                var venusFormattingRules = rulePool.Object;
                var visibleSpans = spanPool.Object;

                venusFormattingRules.Add(baseIndentationRule);
                venusFormattingRules.Add(ContainedDocumentPreserveFormattingRule.Instance);

                var formattingRules = venusFormattingRules.Concat(Formatter.GetDefaultFormattingRules(document));

                var workspace = document.Project.Solution.Workspace;
                var changes = Formatter.GetFormattedTextChanges(
                    root, new TextSpan[] { CommonFormattingHelpers.GetFormattingSpan(root, visibleSpan) },
                    workspace, options, formattingRules, CancellationToken.None);

                visibleSpans.Add(visibleSpan);
                var newChanges = FilterTextChanges(document.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None), visibleSpans, changes.ToReadOnlyCollection()).Where(t => visibleSpan.Contains(t.Span));

                foreach (var change in newChanges)
                {
                    edit.Replace(change.Span.ToSpan(), change.NewText);
                }
            }
        }
        /// <summary>
        /// Finds the member in the containing symbol which is inside the given declaration span.
        /// </summary>
        private Symbol GetDeclaredMember(NamespaceOrTypeSymbol container, TextSpan declarationSpan, string name = null)
        {
            if ((object)container == null)
            {
                return null;
            }

            // look for any member with same declaration location
            var collection = name != null ? container.GetMembers(name) : container.GetMembersUnordered();

            Symbol zeroWidthMatch = null;
            foreach (var symbol in collection)
            {
                var namedType = symbol as ImplicitNamedTypeSymbol;
                if ((object)namedType != null && namedType.IsImplicitClass)
                {
                    // look inside wrapper around illegally placed members in namespaces
                    var result = GetDeclaredMember(namedType, declarationSpan, name);
                    if ((object)result != null)
                    {
                        return result;
                    }
                }

                foreach (var loc in symbol.Locations)
                {
                    if (loc.IsInSource && loc.SourceTree == this.SyntaxTree && declarationSpan.Contains(loc.SourceSpan))
                    {
                        if (loc.SourceSpan.IsEmpty && loc.SourceSpan.End == declarationSpan.Start)
                        {
                            // exclude decls created via syntax recovery
                            zeroWidthMatch = symbol;
                        }
                        else
                        {
                            return symbol;
                        }
                    }
                }

                // Handle the case of the implementation of a partial method.
                var partial = symbol.Kind == SymbolKind.Method
                    ? ((MethodSymbol)symbol).PartialImplementationPart
                    : null;
                if ((object)partial != null)
                {
                    var loc = partial.Locations[0];
                    if (loc.IsInSource && loc.SourceTree == this.SyntaxTree && declarationSpan.Contains(loc.SourceSpan))
                    {
                        return partial;
                    }
                }
            }

            // If we didn't find anything better than the symbol that matched because of syntax error recovery, then return that.
            // Otherwise, if there's a name, try again without a name.
            // Otherwise, give up.
            return zeroWidthMatch ??
                (name != null ? GetDeclaredMember(container, declarationSpan) : null);
        }
示例#36
0
 public void TextSpan_ContainsItself()
 {
     var textSpan = new TextSpan(SourceText.From(""), 1, 2);
     Assert.True(textSpan.Contains(textSpan));
 }
示例#37
0
 public void TextSpan_DoesNotContainEnd()
 {
     var textSpan = new TextSpan(SourceText.From(""), 1, 2);
     Assert.False(textSpan.Contains(textSpan.End));
 }
示例#38
0
 public void TextSpan_ContainsStart()
 {
     var textSpan = new TextSpan(null, 1, 2);
     Assert.True(textSpan.Contains(textSpan.Start));
 }
        private async Task<SuppressionTargetInfo> GetSuppressionTargetInfoAsync(Document document, TextSpan span, CancellationToken cancellationToken)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
            if (syntaxTree.GetLineVisibility(span.Start, cancellationToken) == LineVisibility.Hidden)
            {
                return null;
            }

            // Find the start token to attach leading pragma disable warning directive.
            var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
            var lines = syntaxTree.GetText(cancellationToken).Lines;
            var indexOfLine = lines.IndexOf(span.Start);
            var lineAtPos = lines[indexOfLine];
            var startToken = root.FindToken(lineAtPos.Start);
            startToken = GetAdjustedTokenForPragmaDisable(startToken, root, lines, indexOfLine);

            // Find the end token to attach pragma restore warning directive.
            var spanEnd = Math.Max(startToken.Span.End, span.End);
            indexOfLine = lines.IndexOf(spanEnd);
            lineAtPos = lines[indexOfLine];
            var endToken = root.FindToken(lineAtPos.End);
            endToken = GetAdjustedTokenForPragmaRestore(endToken, root, lines, indexOfLine);

            var nodeWithTokens = GetNodeWithTokens(startToken, endToken, root);

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            ISymbol targetSymbol = null;
            var targetMemberNode = syntaxFacts.GetContainingMemberDeclaration(root, startToken.SpanStart);
            if (targetMemberNode != null)
            {
                targetSymbol = semanticModel.GetDeclaredSymbol(targetMemberNode, cancellationToken);

                if (targetSymbol == null)
                {
                    var analyzerDriverService = document.GetLanguageService<IAnalyzerDriverService>();

                    // targetMemberNode could be a declaration node with multiple decls (e.g. field declaration defining multiple variables).
                    // Let us compute all the declarations intersecting the span.
                    var decls = new List<DeclarationInfo>();
                    analyzerDriverService.ComputeDeclarationsInSpan(semanticModel, span, true, decls, cancellationToken);
                    if (decls.Any())
                    {
                        var containedDecls = decls.Where(d => span.Contains(d.DeclaredNode.Span));
                        if (containedDecls.Count() == 1)
                        {
                            // Single containing declaration, use this symbol.
                            var decl = containedDecls.Single();
                            targetSymbol = decl.DeclaredSymbol;
                        }
                        else
                        {
                            // Otherwise, use the most enclosing declaration.
                            TextSpan? minContainingSpan = null;
                            foreach (var decl in decls)
                            {
                                var declSpan = decl.DeclaredNode.Span;
                                if (declSpan.Contains(span) &&
                                    (!minContainingSpan.HasValue || minContainingSpan.Value.Contains(declSpan)))
                                {
                                    minContainingSpan = declSpan;
                                    targetSymbol = decl.DeclaredSymbol;
                                }
                            }
                        }
                    }
                }
            }

            if (targetSymbol == null)
            {
                // Outside of a member declaration, suppress diagnostic for the entire assembly.
                targetSymbol = semanticModel.Compilation.Assembly;
            }

            return new SuppressionTargetInfo() { TargetSymbol = targetSymbol, NodeWithTokens = nodeWithTokens, StartToken = startToken, EndToken = endToken };
        }
示例#40
0
 public void TextSpan_DoesNotContainEnd()
 {
     var textSpan = new TextSpan(null, 1, 2);
     Assert.False(textSpan.Contains(textSpan.End));
 }
        public void TextSpanContains01()
        {
            TextSpan span_05_15 = new TextSpan(5, 10);
            TextSpan span_03_10 = new TextSpan(3, 7);
            TextSpan span_10_11 = new TextSpan(10, 1);
            TextSpan span_00_03 = new TextSpan(0, 3);

            // nonoverlapping
            Assert.False(span_05_15.Contains(span_00_03));
            Assert.False(span_00_03.Contains(span_05_15));

            // overlap with slop
            Assert.True(span_05_15.Contains(span_10_11));

            // same span
            Assert.True(span_05_15.Contains(span_05_15));

            // partial overlap
            Assert.False(span_05_15.Contains(span_03_10));
            Assert.False(span_03_10.Contains(span_05_15));
        }
示例#42
0
        private bool TryGetSubTextChange(
            SourceText originalText, TextSpan visibleSpanInOriginalText,
            string rightText, TextSpan spanInOriginalText, TextSpan spanInRightText, out TextChange textChange)
        {
            textChange = default(TextChange);

            var visibleFirstLineInOriginalText = originalText.Lines.GetLineFromPosition(visibleSpanInOriginalText.Start);
            var visibleLastLineInOriginalText = originalText.Lines.GetLineFromPosition(visibleSpanInOriginalText.End);

            // skip easy case
            // 1. things are out of visible span
            if (!visibleSpanInOriginalText.IntersectsWith(spanInOriginalText))
            {
                return false;
            }

            // 2. there are no intersects
            var snippetInRightText = rightText.Substring(spanInRightText.Start, spanInRightText.Length);
            if (visibleSpanInOriginalText.Contains(spanInOriginalText) && visibleSpanInOriginalText.End != spanInOriginalText.End)
            {
                textChange = new TextChange(spanInOriginalText, snippetInRightText);
                return true;
            }

            // okay, more complex case. things are intersecting boundaries.
            var firstLineOfRightTextSnippet = snippetInRightText.GetFirstLineText();
            var lastLineOfRightTextSnippet = snippetInRightText.GetLastLineText();

            // there are 4 complex cases - these are all heuristic. not sure what better way I have. and the heristic is heavily based on
            // text differ's behavior.

            // 1. it is a single line
            if (visibleFirstLineInOriginalText.LineNumber == visibleLastLineInOriginalText.LineNumber)
            {
                // don't do anything
                return false;
            }

            // 2. replacement contains visible spans
            if (spanInOriginalText.Contains(visibleSpanInOriginalText))
            {
                // header
                // don't do anything

                // body
                textChange = new TextChange(
                    TextSpan.FromBounds(visibleFirstLineInOriginalText.EndIncludingLineBreak, visibleLastLineInOriginalText.Start),
                    snippetInRightText.Substring(firstLineOfRightTextSnippet.Length, snippetInRightText.Length - firstLineOfRightTextSnippet.Length - lastLineOfRightTextSnippet.Length));

                // footer
                // don't do anything

                return true;
            }

            // 3. replacement intersects with start
            if (spanInOriginalText.Start < visibleSpanInOriginalText.Start &&
                visibleSpanInOriginalText.Start <= spanInOriginalText.End &&
                spanInOriginalText.End < visibleSpanInOriginalText.End)
            {
                // header
                // don't do anything

                // body
                if (visibleFirstLineInOriginalText.EndIncludingLineBreak <= spanInOriginalText.End)
                {
                    textChange = new TextChange(
                        TextSpan.FromBounds(visibleFirstLineInOriginalText.EndIncludingLineBreak, spanInOriginalText.End),
                        snippetInRightText.Substring(firstLineOfRightTextSnippet.Length));
                    return true;
                }

                return false;
            }

            // 4. replacement intersects with end
            if (visibleSpanInOriginalText.Start < spanInOriginalText.Start &&
                spanInOriginalText.Start <= visibleSpanInOriginalText.End &&
                visibleSpanInOriginalText.End <= spanInOriginalText.End)
            {
                // body
                if (spanInOriginalText.Start <= visibleLastLineInOriginalText.Start)
                {
                    textChange = new TextChange(
                        TextSpan.FromBounds(spanInOriginalText.Start, visibleLastLineInOriginalText.Start),
                        snippetInRightText.Substring(0, snippetInRightText.Length - lastLineOfRightTextSnippet.Length));
                    return true;
                }

                // footer
                // don't do anything

                return false;
            }

            // if it got hit, then it means there is a missing case
            throw ExceptionUtilities.Unreachable;
        }
示例#43
0
 public void TextSpan_ContainsItself()
 {
     var textSpan = new TextSpan(null, 1, 2);
     Assert.True(textSpan.Contains(textSpan));
 }
示例#44
0
 protected virtual IEnumerable<SyntaxNode> GetNodes(SyntaxNode root, TextSpan span)
 {
     IEnumerable<SyntaxNode> nodes;
     nodes = root.FindToken(span.Start, findInsideTrivia: true).GetAncestors<SyntaxNode>().Where(a => span.Contains(a.Span)).Reverse();
     return nodes;
 }
 public void TextSpanContains00()
 {
     TextSpan span = new TextSpan(0, 10);
     Assert.True(span.Contains(3));
     Assert.False(span.Contains(30));
     Assert.False(span.Contains(11));
     Assert.False(span.Contains(-1));
 }
        public async Task<IEnumerable<CodeFix>> GetSuppressionsAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
        {
            var suppressableDiagnostics = diagnostics.Where(CanBeSuppressed);
            if (suppressableDiagnostics.IsEmpty())
            {
                return null;
            }

            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
            if (syntaxTree.GetLineVisibility(span.Start, cancellationToken) == LineVisibility.Hidden)
            {
                return null;
            }

            // Find the start token to attach leading pragma disable warning directive.
            var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
            SyntaxTrivia containingTrivia = root.FindTrivia(span.Start);
            var lines = syntaxTree.GetText(cancellationToken).Lines;
            int indexOfLine;
            if (containingTrivia == default(SyntaxTrivia))
            {
                indexOfLine = lines.IndexOf(span.Start);
            }
            else
            {
                indexOfLine = lines.IndexOf(containingTrivia.Token.SpanStart);
            }

            var lineAtPos = lines[indexOfLine];
            var startToken = root.FindToken(lineAtPos.Start);
            startToken = GetAdjustedTokenForPragmaDisable(startToken, root, lines, indexOfLine);

            // Find the end token to attach pragma restore warning directive.
            // This should be the last token on the line that contains the start token.
            indexOfLine = lines.IndexOf(startToken.Span.End);
            lineAtPos = lines[indexOfLine];
            var endToken = root.FindToken(lineAtPos.End);
            endToken = GetAdjustedTokenForPragmaRestore(endToken, root, lines, indexOfLine);

            SyntaxNode nodeWithTokens = null;
            if (IsEndOfFileToken(endToken))
            {
                nodeWithTokens = root;
            }
            else
            {
                nodeWithTokens = startToken.GetCommonRoot(endToken);
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            ISymbol targetSymbol = null;
            SyntaxNode targetMemberNode = null;
            var suppressMessageAttribute = semanticModel.Compilation.SuppressMessageAttributeType();
            bool skipSuppressMessage = suppressMessageAttribute == null || !suppressMessageAttribute.IsAttribute();
            if (!skipSuppressMessage)
            {
                targetMemberNode = syntaxFacts.GetContainingMemberDeclaration(root, startToken.SpanStart);
                if (targetMemberNode != null)
                {
                    targetSymbol = semanticModel.GetDeclaredSymbol(targetMemberNode, cancellationToken);

                    if (targetSymbol == null)
                    {
                        var analyzerDriverService = document.GetLanguageService<IAnalyzerDriverService>();

                        // targetMemberNode could be a declaration node with multiple decls (e.g. field declaration defining multiple variables).
                        // Let us compute all the declarations intersecting the span.
                        var decls = analyzerDriverService.GetDeclarationsInSpan(semanticModel, span, true, cancellationToken);
                        if (decls.Any())
                        {
                            var containedDecls = decls.Where(d => span.Contains(d.DeclaredNode.Span));
                            if (containedDecls.Count() == 1)
                            {
                                // Single containing declaration, use this symbol.
                                var decl = containedDecls.Single();
                                targetSymbol = decl.DeclaredSymbol;
                            }
                            else
                            {
                                // Otherwise, use the most enclosing declaration.
                                TextSpan? minContainingSpan = null;
                                foreach (var decl in decls)
                                {
                                    var declSpan = decl.DeclaredNode.Span;
                                    if (declSpan.Contains(span) &&
                                        (!minContainingSpan.HasValue || minContainingSpan.Value.Contains(declSpan)))
                                    {
                                        minContainingSpan = declSpan;
                                        targetSymbol = decl.DeclaredSymbol;
                                    }
                                }
                            }
                        }
                    }
                }

                if (targetSymbol == null)
                {
                    // Outside of a member declaration, suppress diagnostic for the entire assembly.
                    targetSymbol = semanticModel.Compilation.Assembly;
                }
            }

            var result = new List<CodeFix>();
            foreach (var diagnostic in suppressableDiagnostics)
            {
                var nestedActions = new List<CodeAction>();

                // pragma warning disable.
                nestedActions.Add(new PragmaWarningCodeAction(this, startToken, endToken, nodeWithTokens, document, diagnostic));

                // SuppressMessageAttribute suppression is not supported for compiler diagnostics.
                if (!skipSuppressMessage && !IsCompilerDiagnostic(diagnostic))
                {
                    // local member-level suppress message attribute.
                    if (targetMemberNode != null && targetSymbol.Kind != SymbolKind.Namespace)
                    {
                        nestedActions.Add(new LocalSuppressMessageCodeAction(this, targetSymbol, targetMemberNode, document, diagnostic));
                    }

                    // global assembly-level suppress message attribute.
                    nestedActions.Add(new GlobalSuppressMessageCodeAction(this, targetSymbol, document, diagnostic));
                }

                result.Add(new CodeFix(new SuppressionCodeAction(diagnostic, nestedActions), diagnostic));
            }

            return result;
        }