private SyntaxToken AnnotationResolver(
                SyntaxNode node,
                TriviaLocation location,
                SyntaxAnnotation annotation,
                SyntaxNode callsite,
                MethodDeclarationSyntax method)
            {
                var token = node.GetAnnotatedNodesAndTokens(annotation).FirstOrDefault().AsToken();
                if (token.RawKind != 0)
                {
                    return token;
                }

                switch (location)
                {
                    case TriviaLocation.BeforeBeginningOfSpan:
                        return callsite.GetFirstToken(includeZeroWidth: true).GetPreviousToken(includeZeroWidth: true);
                    case TriviaLocation.AfterEndOfSpan:
                        return callsite.GetLastToken(includeZeroWidth: true).GetNextToken(includeZeroWidth: true);
                    case TriviaLocation.AfterBeginningOfSpan:
                        return method.Body.OpenBraceToken.GetNextToken(includeZeroWidth: true);
                    case TriviaLocation.BeforeEndOfSpan:
                        return method.Body.CloseBraceToken.GetPreviousToken(includeZeroWidth: true);
                }

                return Contract.FailWithReturn<SyntaxToken>("can't happen");
            }
Esempio n. 2
0
        public TreeData(SyntaxNode root)
        {
            Contract.ThrowIfNull(root);
            _root = root;

            _firstToken = _root.GetFirstToken(includeZeroWidth: true);
            _lastToken = _root.GetLastToken(includeZeroWidth: true);
        }
        public ValidationMessage(SyntaxNode messageSource, string message)
        {
            var path = messageSource.SyntaxTree.FilePath;
            var token = messageSource.GetFirstToken();
            var text = messageSource.SyntaxTree.GetText();

            var startLine = text.Lines.GetLineFromPosition(token.SpanStart);
            var startColumn = token.SpanStart - startLine.Start;

            var endLine = text.Lines.GetLineFromPosition(token.Span.End);
            var endColumn = token.Span.End - endLine.Start;

            _message = string.Format("{0}({1},{2},{3},{4}):{5}", 
                path, 
                startLine.LineNumber + 1, startColumn + 1, 
                endLine.LineNumber + 1, endColumn + 1, 
                message);
        }
        private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, SyntaxNode node)
        {
            // The first token is the open parenthesis token. This token has all the inner trivia
            var firstToken = node.GetFirstToken();
            var lastToken = node.GetLastToken();

            var previousToken = firstToken.GetPreviousToken();

            // We want to keep all trivia. The easiest way to do that is by doing it manually
            var newSyntaxRoot = root.RemoveNode(node, SyntaxRemoveOptions.KeepNoTrivia);

            // The removing operation has not changed the location of the previous token
            var newPreviousToken = newSyntaxRoot.FindToken(previousToken.Span.Start);

            var newTrailingTrivia = newPreviousToken.TrailingTrivia.AddRange(firstToken.GetAllTrivia()).AddRange(lastToken.GetAllTrivia());

            newSyntaxRoot = newSyntaxRoot.ReplaceToken(newPreviousToken, newPreviousToken.WithTrailingTrivia(newTrailingTrivia));

            return Task.FromResult(document.WithSyntaxRoot(newSyntaxRoot));
        }
        /// <summary>
        /// Parses a comment-only file header.
        /// </summary>
        /// <param name="root">The root of the syntax tree.</param>
        /// <returns>The copyright string, as parsed from the file header.</returns>
        internal static FileHeader ParseFileHeader(SyntaxNode root)
        {
            var firstToken = root.GetFirstToken(includeZeroWidth: true);

            if (!firstToken.HasLeadingTrivia)
            {
                return FileHeader.MissingFileHeader;
            }

            var sb = new StringBuilder();
            var endOfLineCount = 0;
            var done = false;
            var fileHeaderStart = int.MaxValue;
            var fileHeaderEnd = int.MinValue;

            int i;
            for (i = 0; !done && (i < firstToken.LeadingTrivia.Count); i++)
            {
                var trivia = firstToken.LeadingTrivia[i];

                switch (trivia.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    endOfLineCount = 0;
                    break;
                case SyntaxKind.SingleLineCommentTrivia:
                    endOfLineCount = 0;

                    var commentString = trivia.ToFullString();

                    fileHeaderStart = Math.Min(trivia.FullSpan.Start, fileHeaderStart);
                    fileHeaderEnd = trivia.FullSpan.End;

                    sb.AppendLine(commentString.Substring(2).Trim());
                    break;
                case SyntaxKind.MultiLineCommentTrivia:
                    // only process a MultiLineCommentTrivia if no SingleLineCommentTrivia have been processed
                    if (sb.Length == 0)
                    {
                        var triviaString = trivia.ToFullString();

                        var startIndex = triviaString.IndexOf("/*", StringComparison.Ordinal) + 2;
                        var endIndex = triviaString.LastIndexOf("*/", StringComparison.Ordinal);
                        var commentContext = triviaString.Substring(startIndex, endIndex - startIndex).Trim();

                        var triviaStringParts = commentContext.Replace("\r\n", "\n").Split('\n');

                        foreach (var part in triviaStringParts)
                        {
                            var trimmedPart = part.TrimStart(' ', '*');
                            sb.AppendLine(trimmedPart);
                        }

                        fileHeaderStart = trivia.FullSpan.Start;
                        fileHeaderEnd = trivia.FullSpan.End;
                    }

                    done = true;
                    break;
                case SyntaxKind.EndOfLineTrivia:
                    endOfLineCount++;
                    done = endOfLineCount > 1;
                    break;
                default:
                    done = (fileHeaderStart < fileHeaderEnd) || !trivia.IsDirective;
                    break;
                }
            }

            if (fileHeaderStart > fileHeaderEnd)
            {
                return FileHeader.MissingFileHeader;
            }

            if (sb.Length > 0)
            {
                // remove the final newline
                var eolLength = Environment.NewLine.Length;
                sb.Remove(sb.Length - eolLength, eolLength);
            }

            return new FileHeader(sb.ToString(), fileHeaderStart, fileHeaderEnd);
        }
        /// <summary>
        /// Parses an XML-based file header.
        /// </summary>
        /// <param name="root">The root of the syntax tree.</param>
        /// <returns>The parsed file header.</returns>
        internal static XmlFileHeader ParseXmlFileHeader(SyntaxNode root)
        {
            var firstToken = root.GetFirstToken(includeZeroWidth: true);
            string xmlString;
            int fileHeaderStart;
            int fileHeaderEnd;

            var firstNonWhitespaceTrivia = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia, false);
            if (firstNonWhitespaceTrivia == -1)
            {
                return XmlFileHeader.MissingFileHeader;
            }

            switch (firstToken.LeadingTrivia[firstNonWhitespaceTrivia].Kind())
            {
            case SyntaxKind.SingleLineCommentTrivia:
                xmlString = ProcessSingleLineCommentsHeader(firstToken.LeadingTrivia, firstNonWhitespaceTrivia, out fileHeaderStart, out fileHeaderEnd);
                break;

            case SyntaxKind.MultiLineCommentTrivia:
                xmlString = ProcessMultiLineCommentsHeader(firstToken.LeadingTrivia[firstNonWhitespaceTrivia], out fileHeaderStart, out fileHeaderEnd);
                break;

            default:
                return XmlFileHeader.MissingFileHeader;
            }

            if (fileHeaderStart > fileHeaderEnd)
            {
                return XmlFileHeader.MissingFileHeader;
            }

            try
            {
                var parsedFileHeaderXml = XElement.Parse(xmlString);

                // a header without any XML tags is malformed.
                if (!parsedFileHeaderXml.Descendants().Any())
                {
                    return XmlFileHeader.MalformedFileHeader;
                }

                return new XmlFileHeader(parsedFileHeaderXml, fileHeaderStart, fileHeaderEnd);
            }
            catch (XmlException)
            {
                return XmlFileHeader.MalformedFileHeader;
            }
        }
            private static void AddIndentBlockOperations(List<IndentBlockOperation> list, SyntaxNode node)
            {
                // only add indent block operation if the base token is the first token on line
                var text = node.SyntaxTree.GetText();
                var baseToken = node.Parent.GetFirstToken(includeZeroWidth: true);

                list.Add(FormattingOperations.CreateRelativeIndentBlockOperation(
                    baseToken,
                    node.GetFirstToken(includeZeroWidth: true).GetNextToken(includeZeroWidth: true),
                    node.GetLastToken(includeZeroWidth: true).GetPreviousToken(includeZeroWidth: true),
                    indentationDelta: 1,
                    option: IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine));
            }
Esempio n. 8
0
        private void SuppressVariableDeclaration(List<SuppressOperation> list, SyntaxNode node, OptionSet optionSet)
        {
            if (node.IsKind(SyntaxKind.FieldDeclaration) || node.IsKind(SyntaxKind.EventDeclaration) ||
                node.IsKind(SyntaxKind.EventFieldDeclaration) || node.IsKind(SyntaxKind.LocalDeclarationStatement))
            {
                if (optionSet.GetOption(CSharpFormattingOptions.SpacesIgnoreAroundVariableDeclaration))
                {
                    var firstToken = node.GetFirstToken(includeZeroWidth: true);
                    var lastToken = node.GetLastToken(includeZeroWidth: true);

                    list.Add(FormattingOperations.CreateSuppressOperation(firstToken, lastToken, SuppressOption.NoSpacing));
                }
            }
        }
        public override string GetComment(SyntaxNode node)
        {
            var firstToken = node.GetFirstToken();
            var commentList = CollectComments(firstToken.LeadingTrivia.ToArray());

            if (commentList.Count == 0)
            {
                return string.Empty;
            }

            var textBuilder = new StringBuilder();
            foreach (var trivia in commentList)
            {
                if (trivia.IsRegularComment())
                {
                    textBuilder.AppendLine(trivia.GetCommentText());
                }
                else
                {
                    throw Exceptions.ThrowEFail();
                }
            }

            return textBuilder.ToString();
        }
        private void RemoveSuppressOperationForBlock(List<SuppressOperation> list, SyntaxNode node)
        {
            var bracePair = GetBracePair(node);
            if (!bracePair.IsValidBracePair())
            {
                return;
            }

            var firstTokenOfNode = node.GetFirstToken(includeZeroWidth: true);

            if (node.IsLambdaBodyBlock())
            {
                // include lambda itself.
                firstTokenOfNode = node.Parent.GetFirstToken(includeZeroWidth: true);
            }

            // suppress wrapping on whole construct that owns braces and also brace pair itself if it is on same line
            RemoveSuppressOperation(list, firstTokenOfNode, bracePair.Item2);
            RemoveSuppressOperation(list, bracePair.Item1, bracePair.Item2);
        }
        private static SyntaxNode ReAddFileHeader(SyntaxNode syntaxRoot, SyntaxNode newSyntaxRoot)
        {
            var oldFirstToken = syntaxRoot.GetFirstToken();
            if (!oldFirstToken.HasLeadingTrivia)
            {
                return newSyntaxRoot;
            }

            var fileHeader = UsingsHelper.GetFileHeader(oldFirstToken.LeadingTrivia.ToList());
            if (!fileHeader.Any())
            {
                return newSyntaxRoot;
            }

            var newFirstToken = newSyntaxRoot.GetFirstToken();
            var newLeadingTrivia = newFirstToken.LeadingTrivia.InsertRange(0, fileHeader);
            return newSyntaxRoot.ReplaceToken(newFirstToken, newFirstToken.WithLeadingTrivia(newLeadingTrivia));
        }
        private static void CheckChildStatement(SyntaxNodeAnalysisContext context, SyntaxNode node, StatementSyntax childStatement)
        {
            if (childStatement == null || childStatement.IsMissing)
            {
                return;
            }

            if (childStatement is BlockSyntax)
            {
                // BlockSyntax child statements are handled by HandleBlock
                return;
            }

            // We are only interested in the first instance of this violation on a line.
            if (!node.GetFirstToken().IsFirstInLine())
            {
                return;
            }

            // We are only interested in the case where statement and childStatement start on the same line. Use
            // IsFirstInLine to detect this condition easily.
            SyntaxToken firstChildToken = childStatement.GetFirstToken();
            if (firstChildToken.IsMissingOrDefault() || firstChildToken.IsFirstInLine())
            {
                return;
            }

            if (!context.IsAnalyzerSuppressed(SA1519CurlyBracketsMustNotBeOmittedFromMultiLineChildStatement.DiagnosticId))
            {
                // diagnostics for multi-line statements is handled by SA1519, as long as it's not suppressed
                FileLinePositionSpan lineSpan = childStatement.GetLineSpan();
                if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line)
                {
                    return;
                }
            }

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, childStatement.GetLocation()));
        }
Esempio n. 13
0
        protected void AddBraceSuppressOperations(List<SuppressOperation> list, SyntaxNode node, SyntaxToken lastToken)
        {
            var bracePair = node.GetBracePair();
            if (!bracePair.IsValidBracePair())
            {
                return;
            }

            var firstTokenOfNode = node.GetFirstToken(includeZeroWidth: true);

            var memberDeclNode = node as MemberDeclarationSyntax;
            if (memberDeclNode != null)
            {
                var firstAndLastTokens = memberDeclNode.GetFirstAndLastMemberDeclarationTokensAfterAttributes();
                firstTokenOfNode = firstAndLastTokens.Item1;
            }

            if (node.IsLambdaBodyBlock())
            {
                // include lambda itself.
                firstTokenOfNode = node.Parent.GetFirstToken(includeZeroWidth: true);
            }

            // We may think we have a complete set of braces, but that may not actually be the case
            // due incomplete code.  i.e. we have something like:
            //
            // class C
            // {
            //      int Blah {
            //          get { return blah
            // }
            //
            // In this case the parse will think that the get-accessor is actually on two lines 
            // (because it will consume the close curly that more accurately belongs to the class.
            //
            // Now there are different behaviors we want depending on what the user is doing 
            // and what we are formatting.  For example, if the user hits semicolon at the end of
            // "blah", then we want to keep the accessor on a single line.  In this scenario we
            // effectively want to ignore the following close curly as it may not be important to
            // this construct in the mind of the user. 
            //
            // However, say the user hits semicolon, then hits enter, then types a close curly.
            // In this scenario we would actually want the get-accessor to be formatted over multiple 
            // lines.  The difference here is that because the user just hit close-curly here we can 
            // consider it as being part of the closest construct and we can consider its placement
            // when deciding if the construct is on a single line.

            var endToken = bracePair.Item2;
            if (lastToken.Kind() != SyntaxKind.CloseBraceToken &&
                lastToken.Kind() != SyntaxKind.EndOfFileToken &&
                !endToken.IsMissing)
            {
                // The user didn't just type the close brace.  So any close brace we have may 
                // actually belong to a containing construct.  See if any containers are missing
                // a close brace, and if so, act as if our own close brace is missing.

                if (SomeParentHasMissingCloseBrace(node.Parent))
                {
                    if (node.IsKind(SyntaxKind.Block) && ((BlockSyntax)node).Statements.Count >= 1)
                    {
                        // In the case of a block, see if the first statement is on the same line 
                        // as the open curly.  If so then we'll want to consider the end of the
                        // block as the end of the first statement.  i.e. if you have:
                        //
                        //  try { }
                        //  catch { return;     // <-- the end of this block is the end of the return statement.
                        //  Method();
                        var firstStatement = ((BlockSyntax)node).Statements[0];
                        if (FormattingRangeHelper.AreTwoTokensOnSameLine(firstTokenOfNode, firstStatement.GetFirstToken()))
                        {
                            endToken = firstStatement.GetLastToken();
                        }
                    }
                    else
                    {
                        endToken = endToken.GetPreviousToken();
                    }
                }
            }

            // suppress wrapping on whole construct that owns braces and also brace pair itself if 
            // it is on same line
            AddSuppressWrappingIfOnSingleLineOperation(list, firstTokenOfNode, endToken);
            AddSuppressWrappingIfOnSingleLineOperation(list, bracePair.Item1, endToken);
        }
        /// <summary>
        /// Parses an XML-based file header.
        /// </summary>
        /// <param name="root">The root of the syntax tree.</param>
        /// <returns>The parsed file header.</returns>
        internal static XmlFileHeader ParseXmlFileHeader(SyntaxNode root)
        {
            var firstToken = root.GetFirstToken(includeZeroWidth: true);

            if (!firstToken.HasLeadingTrivia)
            {
                return XmlFileHeader.MissingFileHeader;
            }

            var sb = new StringBuilder();
            var endOfLineCount = 0;
            var done = false;
            var fileHeaderStart = int.MaxValue;
            var fileHeaderEnd = int.MinValue;

            // wrap the XML from the file header in a single root element to make XML parsing work.
            sb.AppendLine("<root>");

            int i;
            for (i = 0; !done && (i < firstToken.LeadingTrivia.Count); i++)
            {
                var trivia = firstToken.LeadingTrivia[i];

                switch (trivia.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    endOfLineCount = 0;
                    break;
                case SyntaxKind.SingleLineCommentTrivia:
                    endOfLineCount = 0;

                    var commentString = trivia.ToFullString();

                    // ignore borders
                    if (commentString.StartsWith("//-", StringComparison.OrdinalIgnoreCase))
                    {
                        break;
                    }

                    fileHeaderStart = Math.Min(trivia.FullSpan.Start, fileHeaderStart);
                    fileHeaderEnd = trivia.FullSpan.End;

                    sb.AppendLine(commentString.Substring(2));
                    break;
                case SyntaxKind.EndOfLineTrivia:
                    endOfLineCount++;
                    done = endOfLineCount > 1;
                    break;
                default:
                    done = (fileHeaderStart < fileHeaderEnd) || !trivia.IsDirective;
                    break;
                }
            }

            if (fileHeaderStart > fileHeaderEnd)
            {
                return XmlFileHeader.MissingFileHeader;
            }

            sb.AppendLine("</root>");

            try
            {
                var parsedFileHeaderXml = XElement.Parse(sb.ToString());

                // a header without any XML tags is malformed.
                if (!parsedFileHeaderXml.Descendants().Any())
                {
                    return XmlFileHeader.MalformedFileHeader;
                }

                return new XmlFileHeader(parsedFileHeaderXml, fileHeaderStart, fileHeaderEnd);
            }
            catch (XmlException)
            {
                return XmlFileHeader.MalformedFileHeader;
            }
        }
        private static SyntaxNode MoveMember(SyntaxNode syntaxRoot, MemberDeclarationSyntax member, MemberDeclarationSyntax targetMember, IndentationOptions indentationOptions)
        {
            var firstToken = syntaxRoot.GetFirstToken();
            var fileHeader = GetFileHeader(firstToken.LeadingTrivia);
            syntaxRoot = syntaxRoot.TrackNodes(member, targetMember, firstToken.Parent);
            var memberToMove = syntaxRoot.GetCurrentNode(member);
            var targetMemberTracked = syntaxRoot.GetCurrentNode(targetMember);
            if (!memberToMove.HasLeadingTrivia)
            {
                var targetIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, targetMember);
                var indentationString = IndentationHelper.GenerateIndentationString(indentationOptions, targetIndentationLevel);
                memberToMove = memberToMove.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString));
            }

            if (!HasLeadingBlankLines(targetMember)
                && HasLeadingBlankLines(member))
            {
                memberToMove = memberToMove.WithTrailingTrivia(memberToMove.GetTrailingTrivia().Add(SyntaxFactory.CarriageReturnLineFeed));
                memberToMove = memberToMove.WithLeadingTrivia(GetLeadingTriviaWithoutLeadingBlankLines(memberToMove));
            }

            syntaxRoot = syntaxRoot.InsertNodesBefore(targetMemberTracked, new[] { memberToMove });
            var fieldToMoveTracked = syntaxRoot.GetCurrentNodes(member).Last();
            syntaxRoot = syntaxRoot.RemoveNode(fieldToMoveTracked, SyntaxRemoveOptions.KeepNoTrivia);
            if (fileHeader.Any())
            {
                var oldFirstToken = syntaxRoot.GetCurrentNode(firstToken.Parent).ChildTokens().First();
                syntaxRoot = syntaxRoot.ReplaceToken(oldFirstToken, oldFirstToken.WithLeadingTrivia(StripFileHeader(oldFirstToken.LeadingTrivia)));
                var newFirstToken = syntaxRoot.GetFirstToken();
                syntaxRoot = syntaxRoot.ReplaceToken(newFirstToken, newFirstToken.WithLeadingTrivia(fileHeader.AddRange(newFirstToken.LeadingTrivia)));
            }

            return syntaxRoot;
        }
        private static ImmutableArray<SyntaxTrivia> GetFileHeader(SyntaxNode syntaxRoot)
        {
            var onBlankLine = false;
            var hasHeader = false;
            var fileHeaderBuilder = ImmutableArray.CreateBuilder<SyntaxTrivia>();

            var firstToken = syntaxRoot.GetFirstToken(includeZeroWidth: true);
            var firstTokenLeadingTrivia = firstToken.LeadingTrivia;

            int i;
            for (i = 0; i < firstTokenLeadingTrivia.Count; i++)
            {
                bool done = false;
                switch (firstTokenLeadingTrivia[i].Kind())
                {
                case SyntaxKind.SingleLineCommentTrivia:
                case SyntaxKind.MultiLineCommentTrivia:
                    fileHeaderBuilder.Add(firstTokenLeadingTrivia[i]);
                    onBlankLine = false;
                    hasHeader = true;
                    break;

                case SyntaxKind.WhitespaceTrivia:
                    fileHeaderBuilder.Add(firstTokenLeadingTrivia[i]);
                    break;

                case SyntaxKind.EndOfLineTrivia:
                    fileHeaderBuilder.Add(firstTokenLeadingTrivia[i]);

                    if (onBlankLine)
                    {
                        done = true;
                    }
                    else
                    {
                        onBlankLine = true;
                    }

                    break;

                default:
                    done = true;
                    break;
                }

                if (done)
                {
                    break;
                }
            }

            return hasHeader ? fileHeaderBuilder.ToImmutableArray() : ImmutableArray.Create<SyntaxTrivia>();
        }
        private static SyntaxNode ReAddFileHeader(SyntaxNode syntaxRoot, ImmutableArray<SyntaxTrivia> fileHeader)
        {
            if (fileHeader.IsEmpty)
            {
                // Only re-add the file header if it was stripped.
                return syntaxRoot;
            }

            var firstToken = syntaxRoot.GetFirstToken(includeZeroWidth: true);
            var newLeadingTrivia = firstToken.LeadingTrivia.InsertRange(0, fileHeader);
            return syntaxRoot.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(newLeadingTrivia));
        }
        protected override SyntaxNode InsertAttributeListIntoContainer(int index, SyntaxNode list, SyntaxNode container)
        {
            // If the attribute list is being inserted at the first index and the container is not the compilation unit, copy leading trivia
            // to the list that is being inserted.
            if (index == 0 && !(container is CompilationUnitSyntax))
            {
                var firstToken = container.GetFirstToken();
                if (firstToken.HasLeadingTrivia)
                {
                    var trivia = firstToken.LeadingTrivia;

                    container = container.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(SyntaxTriviaList.Empty));
                    list = list.WithLeadingTrivia(trivia);
                }
            }

            if (container is CompilationUnitSyntax)
            {
                var compilationUnit = (CompilationUnitSyntax)container;
                var newAttributeLists = compilationUnit.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return compilationUnit.WithAttributeLists(newAttributeLists);
            }
            else if (container is EnumDeclarationSyntax)
            {
                var enumDeclaration = (EnumDeclarationSyntax)container;
                var newAttributeLists = enumDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return enumDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is ClassDeclarationSyntax)
            {
                var classDeclaration = (ClassDeclarationSyntax)container;
                var newAttributeLists = classDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return classDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is StructDeclarationSyntax)
            {
                var structDeclaration = (StructDeclarationSyntax)container;
                var newAttributeLists = structDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return structDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is InterfaceDeclarationSyntax)
            {
                var interfaceDeclaration = (InterfaceDeclarationSyntax)container;
                var newAttributeLists = interfaceDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return interfaceDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is MethodDeclarationSyntax)
            {
                var method = (MethodDeclarationSyntax)container;
                var newAttributeLists = method.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return method.WithAttributeLists(newAttributeLists);
            }
            else if (container is OperatorDeclarationSyntax)
            {
                var operationDeclaration = (OperatorDeclarationSyntax)container;
                var newAttributeLists = operationDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return operationDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is ConversionOperatorDeclarationSyntax)
            {
                var conversion = (ConversionOperatorDeclarationSyntax)container;
                var newAttributeLists = conversion.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return conversion.WithAttributeLists(newAttributeLists);
            }
            else if (container is ConstructorDeclarationSyntax)
            {
                var constructor = (ConstructorDeclarationSyntax)container;
                var newAttributeLists = constructor.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return constructor.WithAttributeLists(newAttributeLists);
            }
            else if (container is DestructorDeclarationSyntax)
            {
                var destructor = (DestructorDeclarationSyntax)container;
                var newAttributeLists = destructor.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return destructor.WithAttributeLists(newAttributeLists);
            }
            else if (container is PropertyDeclarationSyntax)
            {
                var property = (PropertyDeclarationSyntax)container;
                var newAttributeLists = property.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return property.WithAttributeLists(newAttributeLists);
            }
            else if (container is EventDeclarationSyntax)
            {
                var eventDeclaration = (EventDeclarationSyntax)container;
                var newAttributeLists = eventDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return eventDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is IndexerDeclarationSyntax)
            {
                var indexer = (IndexerDeclarationSyntax)container;
                var newAttributeLists = indexer.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return indexer.WithAttributeLists(newAttributeLists);
            }
            else if (container is FieldDeclarationSyntax)
            {
                var field = (FieldDeclarationSyntax)container;
                var newAttributeLists = field.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return field.WithAttributeLists(newAttributeLists);
            }
            else if (container is EventFieldDeclarationSyntax)
            {
                var eventFieldDeclaration = (EventFieldDeclarationSyntax)container;
                var newAttributeLists = eventFieldDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return eventFieldDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is DelegateDeclarationSyntax)
            {
                var delegateDeclaration = (DelegateDeclarationSyntax)container;
                var newAttributeLists = delegateDeclaration.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return delegateDeclaration.WithAttributeLists(newAttributeLists);
            }
            else if (container is EnumMemberDeclarationSyntax)
            {
                var member = (EnumMemberDeclarationSyntax)container;
                var newAttributeLists = member.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return member.WithAttributeLists(newAttributeLists);
            }
            else if (container is ParameterSyntax)
            {
                var parameter = (ParameterSyntax)container;
                var newAttributeLists = parameter.AttributeLists.Insert(index, (AttributeListSyntax)list);
                return parameter.WithAttributeLists(newAttributeLists);
            }
            else if (container is VariableDeclaratorSyntax ||
                     container is VariableDeclarationSyntax)
            {
                return InsertAttributeListIntoContainer(index, list, container.Parent);
            }

            throw Exceptions.ThrowEUnexpected();
        }
Esempio n. 19
0
        protected void AddBraceSuppressOperations(List<SuppressOperation> list, SyntaxNode node, SyntaxToken lastToken)
        {
            var bracePair = node.GetBracePair();
            if (!bracePair.IsValidBracePair())
            {
                return;
            }

            var firstTokenOfNode = node.GetFirstToken(includeZeroWidth: true);

            if (node.IsLambdaBodyBlock())
            {
                // include lambda itself.
                firstTokenOfNode = node.Parent.GetFirstToken(includeZeroWidth: true);
            }

            // We may think we have a complete set of braces, but that may not actually be the case
            // due incomplete code.  i.e. we have something like:
            //
            // class C
            // {
            //      int Blah {
            //          get { return blah
            // }
            //
            // In this case the parse will think that the get-accessor is actually on two lines 
            // (because it will consume the close curly that more accurately belongs to the class.
            //
            // Now there are different behaviors we want depending on what the user is doing 
            // and what we are formatting.  For example, if the user hits semicolon at the end of
            // "blah", then we want to keep the accessor on a single line.  In this scenario we
            // effectively want to ignore the following close curly as it may not be important to
            // this construct in the mind of the user. 
            //
            // However, say the user hits semicolon, then hits enter, then types a close curly.
            // In this scenario we woudl actually want the get-accessor to be formatted over multiple 
            // lines.  The difference here is that because the user just hit close-curly here we can 
            // consider it as being part of the closest construct and we can consider its placement
            // when deciding if the construct is on a single line.

            var endBrace = bracePair.Item2;
            if (lastToken.Kind() != SyntaxKind.CloseBraceToken && 
                lastToken.Kind() != SyntaxKind.EndOfFileToken &&
                !endBrace.IsMissing)
            {
                // The user didn't just type the close brace.  So any close brace we have may 
                // actually belong to a containing construct.  See if any containers are missing
                // a close brace, and if so, act as if our own close brace is missing.

                if (SomeParentHasMissingCloseBrace(node.Parent))
                {
                    endBrace = endBrace.GetPreviousToken();
                }
            }

            // suppress wrapping on whole construct that owns braces and also brace pair itself if 
            // it is on same line
            AddSuppressWrappingIfOnSingleLineOperation(list, firstTokenOfNode, endBrace);
            AddSuppressWrappingIfOnSingleLineOperation(list, bracePair.Item1, endBrace);
        }