Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Formatter/FormattingVisitor_Global.cs @ 13400

Last change on this file since 13400 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 11.9 KB
Line 
1//
2// AstFormattingVisitor_Global.cs
3//
4// Author:
5//       Mike KrÃŒger <mkrueger@xamarin.com>
6//
7// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy
10// of this software and associated documentation files (the "Software"), to deal
11// in the Software without restriction, including without limitation the rights
12// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the Software is
14// furnished to do so, subject to the following conditions:
15//
16// The above copyright notice and this permission notice shall be included in
17// all copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25// THE SOFTWARE.
26using System;
27using System.Linq;
28
29namespace ICSharpCode.NRefactory.CSharp
30{
31  partial class FormattingVisitor : DepthFirstAstVisitor
32  {
33    int GetGlobalNewLinesFor(AstNode child)
34    {
35      if (child.NextSibling == null)
36        // last node in the document => no extra newlines
37        return 0;
38      if (child.NextSibling.Role == Roles.RBrace)
39        // Last node in a block => no extra newlines, it's handled later by FixClosingBrace()
40        return 0;
41
42      int newLines = 1;
43      var nextSibling = child.GetNextSibling(NoWhitespacePredicate);
44      if (nextSibling is PreProcessorDirective) {
45        var directive = (PreProcessorDirective)nextSibling;
46        if (directive.Type == PreProcessorDirectiveType.Endif)
47          return -1;
48        if (directive.Type == PreProcessorDirectiveType.Undef)
49          return -1;
50      }
51      if ((child is UsingDeclaration || child is UsingAliasDeclaration) && !(nextSibling is UsingDeclaration || nextSibling is UsingAliasDeclaration)) {
52        newLines += policy.MinimumBlankLinesAfterUsings;
53      } else if ((child is TypeDeclaration) && (nextSibling is TypeDeclaration)) {
54        newLines += policy.MinimumBlankLinesBetweenTypes;
55      }
56
57      return newLines;
58    }
59
60    public override void VisitSyntaxTree(SyntaxTree unit)
61    {
62      bool first = true;
63      VisitChildrenToFormat(unit, child => {
64        if (first && (child is UsingDeclaration || child is UsingAliasDeclaration)) {
65          EnsureMinimumBlankLinesBefore(child, policy.MinimumBlankLinesBeforeUsings);
66          first = false;
67        }
68        if (NoWhitespacePredicate(child))
69          FixIndentation(child);
70        child.AcceptVisitor(this);
71        if (NoWhitespacePredicate(child) && !first)
72          EnsureMinimumNewLinesAfter(child, GetGlobalNewLinesFor(child));
73      });
74    }
75
76    public override void VisitAttributeSection(AttributeSection attributeSection)
77    {
78      VisitChildrenToFormat(attributeSection, child => {
79        child.AcceptVisitor(this);
80        if (child.NextSibling != null && child.NextSibling.Role == Roles.RBracket) {
81          ForceSpacesAfter(child, false);
82        }
83      });
84    }
85
86    public override void VisitAttribute(Attribute attribute)
87    {
88      if (attribute.HasArgumentList) {
89        ForceSpacesBefore(attribute.LParToken, policy.SpaceBeforeMethodCallParentheses);
90        if (attribute.Arguments.Any()) {
91          ForceSpacesAfter(attribute.LParToken, policy.SpaceWithinMethodCallParentheses);
92        } else {
93          ForceSpacesAfter(attribute.LParToken, policy.SpaceBetweenEmptyMethodCallParentheses);
94          ForceSpacesBefore(attribute.RParToken, policy.SpaceBetweenEmptyMethodCallParentheses);
95        }
96        FormatArguments(attribute);
97      }
98    }
99
100    public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
101    {
102      ForceSpacesAfter(usingDeclaration.UsingToken, true);
103      FixSemicolon(usingDeclaration.SemicolonToken);
104    }
105
106    public override void VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration)
107    {
108      ForceSpacesAfter(usingDeclaration.UsingToken, true);
109      ForceSpacesAround(usingDeclaration.AssignToken, policy.SpaceAroundAssignment);
110      FixSemicolon(usingDeclaration.SemicolonToken);
111    }
112
113    public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
114    {
115      FixOpenBrace(policy.NamespaceBraceStyle, namespaceDeclaration.LBraceToken);
116      if (policy.IndentNamespaceBody)
117        curIndent.Push(IndentType.Block);
118
119      bool first = true;
120      bool startFormat = false;
121      VisitChildrenToFormat(namespaceDeclaration, child => {
122        if (first) {
123          startFormat = child.StartLocation > namespaceDeclaration.LBraceToken.StartLocation;
124        }
125        if (child.Role == Roles.LBrace) {
126          var next = child.GetNextSibling(NoWhitespacePredicate);
127          var blankLines = 1;
128          if (next is UsingDeclaration || next is UsingAliasDeclaration) {
129            blankLines += policy.MinimumBlankLinesBeforeUsings;
130          } else {
131            blankLines += policy.MinimumBlankLinesBeforeFirstDeclaration;
132          }
133          EnsureMinimumNewLinesAfter(child, blankLines);
134          startFormat = true;
135          return;
136        }
137        if (child.Role == Roles.RBrace) {
138          startFormat = false;
139          return;
140        }
141        if (!startFormat || !NoWhitespacePredicate (child))
142          return;
143        if (first && (child is UsingDeclaration || child is UsingAliasDeclaration)) {
144          // TODO: policy.BlankLinesBeforeUsings
145          first = false;
146        }
147        if (NoWhitespacePredicate(child))
148          FixIndentationForceNewLine(child);
149        child.AcceptVisitor(this);
150        if (NoWhitespacePredicate(child))
151          EnsureMinimumNewLinesAfter(child, GetGlobalNewLinesFor(child));
152      });
153
154      if (policy.IndentNamespaceBody)
155        curIndent.Pop();
156
157      FixClosingBrace(policy.NamespaceBraceStyle, namespaceDeclaration.RBraceToken);
158    }
159
160    void FixAttributesAndDocComment(EntityDeclaration entity)
161    {
162      var node = entity.FirstChild;
163      while (node != null && node.Role == Roles.Comment) {
164        node = node.GetNextSibling(NoWhitespacePredicate);
165        FixIndentation(node);
166      }
167      if (entity.Attributes.Count > 0) {
168        AstNode n = null;
169        entity.Attributes.First().AcceptVisitor(this);
170        foreach (var attr in entity.Attributes.Skip (1)) {
171          FixIndentation(attr);
172          attr.AcceptVisitor(this);
173          n = attr;
174        }
175        if (n != null) {
176          FixIndentation(n.GetNextNode(NoWhitespacePredicate));
177        } else {
178          FixIndentation(entity.Attributes.First().GetNextNode(NoWhitespacePredicate));
179        }
180      }
181    }
182
183    public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
184    {
185      FixAttributesAndDocComment(typeDeclaration);
186      BraceStyle braceStyle;
187      bool indentBody = false;
188      switch (typeDeclaration.ClassType) {
189        case ClassType.Class:
190          braceStyle = policy.ClassBraceStyle;
191          indentBody = policy.IndentClassBody;
192          break;
193        case ClassType.Struct:
194          braceStyle = policy.StructBraceStyle;
195          indentBody = policy.IndentStructBody;
196          break;
197        case ClassType.Interface:
198          braceStyle = policy.InterfaceBraceStyle;
199          indentBody = policy.IndentInterfaceBody;
200          break;
201        case ClassType.Enum:
202          braceStyle = policy.EnumBraceStyle;
203          indentBody = policy.IndentEnumBody;
204          break;
205        default:
206          throw new InvalidOperationException("unsupported class type : " + typeDeclaration.ClassType);
207      }
208     
209      foreach (var constraint in typeDeclaration.Constraints)
210        constraint.AcceptVisitor (this);
211
212      FixOpenBrace(braceStyle, typeDeclaration.LBraceToken);
213
214      if (indentBody)
215        curIndent.Push(IndentType.Block);
216      bool startFormat = true;
217      bool first = true;
218      VisitChildrenToFormat(typeDeclaration, child => {
219        if (first) {
220          startFormat = child.StartLocation > typeDeclaration.LBraceToken.StartLocation;
221          first = false;
222        }
223        if (child.Role == Roles.LBrace) {
224          startFormat = true;
225          if (braceStyle != BraceStyle.DoNotChange)
226            EnsureMinimumNewLinesAfter(child, GetTypeLevelNewLinesFor(child));
227          return;
228        }
229        if (child.Role == Roles.RBrace) {
230          startFormat = false;
231          return;
232        }
233        if (!startFormat || !NoWhitespacePredicate (child))
234          return;
235        if (child.Role == Roles.Comma) {
236          ForceSpacesBeforeRemoveNewLines (child, false);
237          EnsureMinimumNewLinesAfter(child, 1);
238          return;
239        }
240        if (NoWhitespacePredicate(child))
241          FixIndentationForceNewLine(child);
242        child.AcceptVisitor(this);
243        if (NoWhitespacePredicate(child) && child.GetNextSibling (NoWhitespacePredicate).Role != Roles.Comma)
244          EnsureMinimumNewLinesAfter(child, GetTypeLevelNewLinesFor(child));
245      });
246
247      if (indentBody)
248        curIndent.Pop();
249
250      FixClosingBrace(braceStyle, typeDeclaration.RBraceToken);
251    }
252
253    int GetTypeLevelNewLinesFor(AstNode child)
254    {
255      var blankLines = 1;
256      var nextSibling = child.GetNextSibling(NoWhitespacePredicate);
257      if (child is PreProcessorDirective) {
258        var directive = (PreProcessorDirective)child;
259        if (directive.Type == PreProcessorDirectiveType.Region) {
260          blankLines += policy.MinimumBlankLinesInsideRegion;
261        }
262        if (directive.Type == PreProcessorDirectiveType.Endregion) {
263          if (child.GetNextSibling(NoWhitespacePredicate) is CSharpTokenNode)
264            return 1;
265          blankLines += policy.MinimumBlankLinesAroundRegion;
266        }
267        return blankLines;
268      }
269
270      if (nextSibling is PreProcessorDirective) {
271        var directive = (PreProcessorDirective)nextSibling;
272        if (directive.Type == PreProcessorDirectiveType.Region) {
273          if (child is CSharpTokenNode)
274            return 1;
275          blankLines += policy.MinimumBlankLinesAroundRegion;
276        }
277        if (directive.Type == PreProcessorDirectiveType.Endregion)
278          blankLines += policy.MinimumBlankLinesInsideRegion;
279        if (directive.Type == PreProcessorDirectiveType.Endif)
280          return -1;
281        if (directive.Type == PreProcessorDirectiveType.Undef)
282          return -1;
283        return blankLines;
284      }
285      if (child.Role == Roles.LBrace)
286        return 1;
287      if (child is Comment)
288        return 1;
289      if (child is EventDeclaration) {
290        if (nextSibling is EventDeclaration) {
291          blankLines += policy.MinimumBlankLinesBetweenEventFields;
292          return blankLines;
293        }
294      }
295
296      if (child is FieldDeclaration || child is FixedFieldDeclaration) {
297        if (nextSibling is FieldDeclaration || nextSibling is FixedFieldDeclaration) {
298          blankLines += policy.MinimumBlankLinesBetweenFields;
299          return blankLines;
300        }
301      }
302     
303      if (child is TypeDeclaration) {
304        if (nextSibling is TypeDeclaration) {
305          blankLines += policy.MinimumBlankLinesBetweenTypes;
306          return blankLines;
307        }
308      }
309
310      if (nextSibling.Role == Roles.TypeMemberRole)
311        blankLines += policy.MinimumBlankLinesBetweenMembers;
312      return blankLines;
313    }
314
315    public override void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
316    {
317      ForceSpacesBefore(delegateDeclaration.LParToken, policy.SpaceBeforeDelegateDeclarationParentheses);
318      if (delegateDeclaration.Parameters.Any()) {
319        ForceSpacesAfter(delegateDeclaration.LParToken, policy.SpaceWithinDelegateDeclarationParentheses);
320        ForceSpacesBefore(delegateDeclaration.RParToken, policy.SpaceWithinDelegateDeclarationParentheses);
321      } else {
322        ForceSpacesAfter(delegateDeclaration.LParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses);
323        ForceSpacesBefore(delegateDeclaration.RParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses);
324      }
325      FormatCommas(delegateDeclaration, policy.SpaceBeforeDelegateDeclarationParameterComma, policy.SpaceAfterDelegateDeclarationParameterComma);
326
327      base.VisitDelegateDeclaration(delegateDeclaration);
328    }
329
330    public override void VisitComment(Comment comment)
331    {
332      if (comment.StartsLine && !HadErrors && (!policy.KeepCommentsAtFirstColumn || comment.StartLocation.Column > 1))
333        FixIndentation(comment);
334    }
335
336    public override void VisitConstraint(Constraint constraint)
337    {
338      VisitChildrenToFormat (constraint, node => {
339        if (node is AstType) {
340          node.AcceptVisitor (this);
341        } else if (node.Role == Roles.LPar) {
342          ForceSpacesBefore (node, false);
343          ForceSpacesAfter (node, false);
344        } else if (node.Role ==Roles.Comma) {
345          ForceSpacesBefore (node, false);
346          ForceSpacesAfter (node, true);
347        }
348      });
349    }
350  }
351}
Note: See TracBrowser for help on using the repository browser.