PageRenderTime 51ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

https://gitlab.com/N3X15/ILSpy
C# | 1652 lines | 1363 code | 197 blank | 92 comment | 373 complexity | a2eaf3551b3bde56688acd330b93fe19 MD5 | raw file
Possible License(s): CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. //
  2. // AstFormattingVisitor.cs
  3. //
  4. // Author:
  5. // Mike Krüger <mkrueger@novell.com>
  6. //
  7. // Copyright (c) 2010 Novell, Inc (http://www.novell.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.
  26. using System;
  27. using System.Text;
  28. using System.Collections.Generic;
  29. using System.Linq;
  30. using ICSharpCode.NRefactory.Editor;
  31. using ICSharpCode.NRefactory.TypeSystem;
  32. using ICSharpCode.NRefactory.CSharp.Refactoring;
  33. namespace ICSharpCode.NRefactory.CSharp
  34. {
  35. public class AstFormattingVisitor : DepthFirstAstVisitor<object, object>
  36. {
  37. CSharpFormattingOptions policy;
  38. IDocument document;
  39. IActionFactory factory;
  40. List<TextReplaceAction> changes = new List<TextReplaceAction> ();
  41. Indent curIndent = new Indent ();
  42. public int IndentLevel {
  43. get {
  44. return curIndent.Level;
  45. }
  46. set {
  47. curIndent.Level = value;
  48. }
  49. }
  50. public int CurrentSpaceIndents {
  51. get;
  52. set;
  53. }
  54. public List<TextReplaceAction> Changes {
  55. get { return this.changes; }
  56. }
  57. public bool CorrectBlankLines {
  58. get;
  59. set;
  60. }
  61. public bool HadErrors {
  62. get;
  63. set;
  64. }
  65. public string EolMarker { get; set; }
  66. public AstFormattingVisitor (CSharpFormattingOptions policy, IDocument document, IActionFactory factory,
  67. bool tabsToSpaces = false, int indentationSize = 4)
  68. {
  69. if (factory == null)
  70. throw new ArgumentNullException ("factory");
  71. this.policy = policy;
  72. this.document = document;
  73. this.curIndent.TabsToSpaces = tabsToSpaces;
  74. this.curIndent.TabSize = indentationSize;
  75. this.factory = factory;
  76. this.EolMarker = Environment.NewLine;
  77. CorrectBlankLines = true;
  78. }
  79. public override object VisitCompilationUnit (CompilationUnit unit, object data)
  80. {
  81. base.VisitCompilationUnit (unit, data);
  82. return null;
  83. }
  84. public void EnsureBlankLinesAfter (AstNode node, int blankLines)
  85. {
  86. if (!CorrectBlankLines)
  87. return;
  88. var loc = node.EndLocation;
  89. int line = loc.Line;
  90. do {
  91. line++;
  92. } while (line < document.LineCount && IsSpacing(document.GetLineByNumber(line)));
  93. var start = document.GetOffset (node.EndLocation);
  94. int foundBlankLines = line - loc.Line - 1;
  95. StringBuilder sb = new StringBuilder ();
  96. for (int i = 0; i < blankLines - foundBlankLines; i++)
  97. sb.Append (this.EolMarker);
  98. int ws = start;
  99. while (ws < document.TextLength && IsSpacing (document.GetCharAt (ws)))
  100. ws++;
  101. int removedChars = ws - start;
  102. if (foundBlankLines > blankLines) {
  103. removedChars += document.GetLineByNumber (loc.Line + foundBlankLines - blankLines).EndOffset
  104. - document.GetLineByNumber (loc.Line).EndOffset;
  105. }
  106. AddChange (start, removedChars, sb.ToString ());
  107. }
  108. public void EnsureBlankLinesBefore (AstNode node, int blankLines)
  109. {
  110. if (!CorrectBlankLines)
  111. return;
  112. var loc = node.StartLocation;
  113. int line = loc.Line;
  114. do {
  115. line--;
  116. } while (line > 0 && IsSpacing(document.GetLineByNumber(line)));
  117. int end = document.GetOffset (loc.Line, 1);
  118. int start = document.GetOffset (line + 1, 1);
  119. StringBuilder sb = new StringBuilder ();
  120. for (int i = 0; i < blankLines; i++)
  121. sb.Append (this.EolMarker);
  122. AddChange (start, end - start, sb.ToString ());
  123. }
  124. public override object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data)
  125. {
  126. if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration))
  127. EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings);
  128. if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration))
  129. EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings);
  130. return null;
  131. }
  132. public override object VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, object data)
  133. {
  134. if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration))
  135. EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings);
  136. if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration))
  137. EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings);
  138. return null;
  139. }
  140. public override object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data)
  141. {
  142. var firstNsMember = namespaceDeclaration.Members.FirstOrDefault ();
  143. if (firstNsMember != null)
  144. EnsureBlankLinesBefore (firstNsMember, policy.BlankLinesBeforeFirstDeclaration);
  145. FixIndentationForceNewLine (namespaceDeclaration.StartLocation);
  146. EnforceBraceStyle (policy.NamespaceBraceStyle, namespaceDeclaration.LBraceToken, namespaceDeclaration.RBraceToken);
  147. if (policy.IndentNamespaceBody)
  148. IndentLevel++;
  149. object result = base.VisitNamespaceDeclaration (namespaceDeclaration, data);
  150. if (policy.IndentNamespaceBody)
  151. IndentLevel--;
  152. FixIndentation (namespaceDeclaration.RBraceToken.StartLocation);
  153. return result;
  154. }
  155. public override object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data)
  156. {
  157. FormatAttributedNode (typeDeclaration);
  158. BraceStyle braceStyle;
  159. bool indentBody = false;
  160. switch (typeDeclaration.ClassType) {
  161. case ClassType.Class:
  162. braceStyle = policy.ClassBraceStyle;
  163. indentBody = policy.IndentClassBody;
  164. break;
  165. case ClassType.Struct:
  166. braceStyle = policy.StructBraceStyle;
  167. indentBody = policy.IndentStructBody;
  168. break;
  169. case ClassType.Interface:
  170. braceStyle = policy.InterfaceBraceStyle;
  171. indentBody = policy.IndentInterfaceBody;
  172. break;
  173. case ClassType.Enum:
  174. braceStyle = policy.EnumBraceStyle;
  175. indentBody = policy.IndentEnumBody;
  176. break;
  177. default:
  178. throw new InvalidOperationException ("unsupported class type : " + typeDeclaration.ClassType);
  179. }
  180. EnforceBraceStyle (braceStyle, typeDeclaration.LBraceToken, typeDeclaration.RBraceToken);
  181. if (indentBody)
  182. IndentLevel++;
  183. object result = base.VisitTypeDeclaration (typeDeclaration, data);
  184. if (indentBody)
  185. IndentLevel--;
  186. if (typeDeclaration.NextSibling is TypeDeclaration || typeDeclaration.NextSibling is DelegateDeclaration)
  187. EnsureBlankLinesAfter (typeDeclaration, policy.BlankLinesBetweenTypes);
  188. return result;
  189. }
  190. bool IsSimpleAccessor (Accessor accessor)
  191. {
  192. if (accessor.IsNull || accessor.Body.IsNull || accessor.Body.FirstChild == null)
  193. return true;
  194. if (accessor.Body.Statements.Count () != 1)
  195. return false;
  196. return !(accessor.Body.Statements.FirstOrDefault () is BlockStatement);
  197. }
  198. bool IsSpacing (char ch)
  199. {
  200. return ch == ' ' || ch == '\t';
  201. }
  202. bool IsSpacing (ISegment segment)
  203. {
  204. int endOffset = segment.EndOffset;
  205. for (int i = segment.Offset; i < endOffset; i++) {
  206. if (!IsSpacing(document.GetCharAt(i)))
  207. return false;
  208. }
  209. return true;
  210. }
  211. int SearchLastNonWsChar (int startOffset, int endOffset)
  212. {
  213. startOffset = System.Math.Max (0, startOffset);
  214. endOffset = System.Math.Max (startOffset, endOffset);
  215. if (startOffset >= endOffset)
  216. return startOffset;
  217. int result = -1;
  218. bool inComment = false;
  219. for (int i = startOffset; i < endOffset && i < document.TextLength; i++) {
  220. char ch = document.GetCharAt (i);
  221. if (IsSpacing (ch))
  222. continue;
  223. if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '/')
  224. return result;
  225. if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '*') {
  226. inComment = true;
  227. i++;
  228. continue;
  229. }
  230. if (inComment && ch == '*' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '/') {
  231. inComment = false;
  232. i++;
  233. continue;
  234. }
  235. if (!inComment)
  236. result = i;
  237. }
  238. return result;
  239. }
  240. void ForceSpace (int startOffset, int endOffset, bool forceSpace)
  241. {
  242. int lastNonWs = SearchLastNonWsChar (startOffset, endOffset);
  243. AddChange (lastNonWs + 1, System.Math.Max (0, endOffset - lastNonWs - 1), forceSpace ? " " : "");
  244. }
  245. // void ForceSpacesAfter (AstNode n, bool forceSpaces)
  246. // {
  247. // if (n == null)
  248. // return;
  249. // AstLocation location = n.EndLocation;
  250. // int offset = data.LocationToOffset (location.Line, location.Column);
  251. // int i = offset;
  252. // while (i < data.Length && IsSpacing (data.GetCharAt (i))) {
  253. // i++;
  254. // }
  255. // ForceSpace (offset - 1, i, forceSpaces);
  256. // }
  257. void ForceSpacesAfter (AstNode n, bool forceSpaces)
  258. {
  259. if (n == null)
  260. return;
  261. TextLocation location = n.EndLocation;
  262. int offset = document.GetOffset (location);
  263. if (location.Column > document.GetLineByNumber (location.Line).Length)
  264. return;
  265. int i = offset;
  266. while (i < document.TextLength && IsSpacing (document.GetCharAt (i))) {
  267. i++;
  268. }
  269. ForceSpace (offset - 1, i, forceSpaces);
  270. }
  271. // int ForceSpacesBefore (AstNode n, bool forceSpaces)
  272. // {
  273. // if (n == null || n.IsNull)
  274. // return 0;
  275. // AstLocation location = n.StartLocation;
  276. //
  277. // int offset = data.LocationToOffset (location.Line, location.Column);
  278. // int i = offset - 1;
  279. //
  280. // while (i >= 0 && IsSpacing (data.GetCharAt (i))) {
  281. // i--;
  282. // }
  283. // ForceSpace (i, offset, forceSpaces);
  284. // return i;
  285. // }
  286. int ForceSpacesBefore (AstNode n, bool forceSpaces)
  287. {
  288. if (n == null || n.IsNull)
  289. return 0;
  290. TextLocation location = n.StartLocation;
  291. // respect manual line breaks.
  292. if (location.Column <= 1 || GetIndentation (location.Line).Length == location.Column - 1)
  293. return 0;
  294. int offset = document.GetOffset (location);
  295. int i = offset - 1;
  296. while (i >= 0 && IsSpacing (document.GetCharAt (i))) {
  297. i--;
  298. }
  299. ForceSpace (i, offset, forceSpaces);
  300. return i;
  301. }
  302. public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data)
  303. {
  304. FormatAttributedNode (propertyDeclaration);
  305. bool oneLine = false;
  306. switch (policy.PropertyFormatting) {
  307. case PropertyFormatting.AllowOneLine:
  308. bool isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter);
  309. if (!isSimple || propertyDeclaration.LBraceToken.StartLocation.Line != propertyDeclaration.RBraceToken.StartLocation.Line) {
  310. EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken);
  311. } else {
  312. ForceSpacesBefore (propertyDeclaration.Getter, true);
  313. ForceSpacesBefore (propertyDeclaration.Setter, true);
  314. ForceSpacesBefore (propertyDeclaration.RBraceToken, true);
  315. oneLine = true;
  316. }
  317. break;
  318. case PropertyFormatting.ForceNewLine:
  319. EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken);
  320. break;
  321. case PropertyFormatting.ForceOneLine:
  322. isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter);
  323. if (isSimple) {
  324. int offset = this.document.GetOffset (propertyDeclaration.LBraceToken.StartLocation);
  325. int start = SearchWhitespaceStart (offset);
  326. int end = SearchWhitespaceEnd (offset);
  327. AddChange (start, offset - start, " ");
  328. AddChange (offset + 1, end - offset - 2, " ");
  329. offset = this.document.GetOffset (propertyDeclaration.RBraceToken.StartLocation);
  330. start = SearchWhitespaceStart (offset);
  331. AddChange (start, offset - start, " ");
  332. oneLine = true;
  333. } else {
  334. EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken);
  335. }
  336. break;
  337. }
  338. if (policy.IndentPropertyBody)
  339. IndentLevel++;
  340. ///System.Console.WriteLine ("one line: " + oneLine);
  341. if (!propertyDeclaration.Getter.IsNull) {
  342. if (!oneLine) {
  343. if (!IsLineIsEmptyUpToEol (propertyDeclaration.Getter.StartLocation)) {
  344. int offset = this.document.GetOffset (propertyDeclaration.Getter.StartLocation);
  345. int start = SearchWhitespaceStart (offset);
  346. string indentString = this.curIndent.IndentString;
  347. AddChange (start, offset - start, this.EolMarker + indentString);
  348. } else {
  349. FixIndentation (propertyDeclaration.Getter.StartLocation);
  350. }
  351. } else {
  352. int offset = this.document.GetOffset (propertyDeclaration.Getter.StartLocation);
  353. int start = SearchWhitespaceStart (offset);
  354. AddChange (start, offset - start, " ");
  355. ForceSpacesBefore (propertyDeclaration.Getter.Body.LBraceToken, true);
  356. ForceSpacesBefore (propertyDeclaration.Getter.Body.RBraceToken, true);
  357. }
  358. if (!propertyDeclaration.Getter.Body.IsNull) {
  359. if (!policy.AllowPropertyGetBlockInline || propertyDeclaration.Getter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Getter.Body.RBraceToken.StartLocation.Line) {
  360. EnforceBraceStyle (policy.PropertyGetBraceStyle, propertyDeclaration.Getter.Body.LBraceToken, propertyDeclaration.Getter.Body.RBraceToken);
  361. } else {
  362. nextStatementIndent = " ";
  363. }
  364. VisitBlockWithoutFixIndentation (propertyDeclaration.Getter.Body, policy.IndentBlocks, data);
  365. }
  366. }
  367. if (!propertyDeclaration.Setter.IsNull) {
  368. if (!oneLine) {
  369. if (!IsLineIsEmptyUpToEol (propertyDeclaration.Setter.StartLocation)) {
  370. int offset = this.document.GetOffset (propertyDeclaration.Setter.StartLocation);
  371. int start = SearchWhitespaceStart (offset);
  372. string indentString = this.curIndent.IndentString;
  373. AddChange (start, offset - start, this.EolMarker + indentString);
  374. } else {
  375. FixIndentation (propertyDeclaration.Setter.StartLocation);
  376. }
  377. } else {
  378. int offset = this.document.GetOffset (propertyDeclaration.Setter.StartLocation);
  379. int start = SearchWhitespaceStart (offset);
  380. AddChange (start, offset - start, " ");
  381. ForceSpacesBefore (propertyDeclaration.Setter.Body.LBraceToken, true);
  382. ForceSpacesBefore (propertyDeclaration.Setter.Body.RBraceToken, true);
  383. }
  384. if (!propertyDeclaration.Setter.Body.IsNull) {
  385. if (!policy.AllowPropertySetBlockInline || propertyDeclaration.Setter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Setter.Body.RBraceToken.StartLocation.Line) {
  386. EnforceBraceStyle (policy.PropertySetBraceStyle, propertyDeclaration.Setter.Body.LBraceToken, propertyDeclaration.Setter.Body.RBraceToken);
  387. } else {
  388. nextStatementIndent = " ";
  389. }
  390. VisitBlockWithoutFixIndentation (propertyDeclaration.Setter.Body, policy.IndentBlocks, data);
  391. }
  392. }
  393. if (policy.IndentPropertyBody)
  394. IndentLevel--;
  395. if (IsMember (propertyDeclaration.NextSibling))
  396. EnsureBlankLinesAfter (propertyDeclaration, policy.BlankLinesBetweenMembers);
  397. return null;
  398. }
  399. public override object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data)
  400. {
  401. ForceSpacesBefore (indexerDeclaration.LBracketToken, policy.SpaceBeforeIndexerDeclarationBracket);
  402. ForceSpacesAfter (indexerDeclaration.LBracketToken, policy.SpaceWithinIndexerDeclarationBracket);
  403. ForceSpacesBefore (indexerDeclaration.RBracketToken, policy.SpaceWithinIndexerDeclarationBracket);
  404. FormatCommas (indexerDeclaration, policy.SpaceBeforeIndexerDeclarationParameterComma, policy.SpaceAfterIndexerDeclarationParameterComma);
  405. FormatAttributedNode (indexerDeclaration);
  406. EnforceBraceStyle (policy.PropertyBraceStyle, indexerDeclaration.LBraceToken, indexerDeclaration.RBraceToken);
  407. if (policy.IndentPropertyBody)
  408. IndentLevel++;
  409. if (!indexerDeclaration.Getter.IsNull) {
  410. FixIndentation (indexerDeclaration.Getter.StartLocation);
  411. if (!indexerDeclaration.Getter.Body.IsNull) {
  412. if (!policy.AllowPropertyGetBlockInline || indexerDeclaration.Getter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Getter.Body.RBraceToken.StartLocation.Line) {
  413. EnforceBraceStyle (policy.PropertyGetBraceStyle, indexerDeclaration.Getter.Body.LBraceToken, indexerDeclaration.Getter.Body.RBraceToken);
  414. } else {
  415. nextStatementIndent = " ";
  416. }
  417. VisitBlockWithoutFixIndentation (indexerDeclaration.Getter.Body, policy.IndentBlocks, data);
  418. }
  419. }
  420. if (!indexerDeclaration.Setter.IsNull) {
  421. FixIndentation (indexerDeclaration.Setter.StartLocation);
  422. if (!indexerDeclaration.Setter.Body.IsNull) {
  423. if (!policy.AllowPropertySetBlockInline || indexerDeclaration.Setter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Setter.Body.RBraceToken.StartLocation.Line) {
  424. EnforceBraceStyle (policy.PropertySetBraceStyle, indexerDeclaration.Setter.Body.LBraceToken, indexerDeclaration.Setter.Body.RBraceToken);
  425. } else {
  426. nextStatementIndent = " ";
  427. }
  428. VisitBlockWithoutFixIndentation (indexerDeclaration.Setter.Body, policy.IndentBlocks, data);
  429. }
  430. }
  431. if (policy.IndentPropertyBody)
  432. IndentLevel--;
  433. if (IsMember (indexerDeclaration.NextSibling))
  434. EnsureBlankLinesAfter (indexerDeclaration, policy.BlankLinesBetweenMembers);
  435. return null;
  436. }
  437. static bool IsSimpleEvent (AstNode node)
  438. {
  439. return node is EventDeclaration;
  440. }
  441. public override object VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, object data)
  442. {
  443. FormatAttributedNode (eventDeclaration);
  444. EnforceBraceStyle (policy.EventBraceStyle, eventDeclaration.LBraceToken, eventDeclaration.RBraceToken);
  445. if (policy.IndentEventBody)
  446. IndentLevel++;
  447. if (!eventDeclaration.AddAccessor.IsNull) {
  448. FixIndentation (eventDeclaration.AddAccessor.StartLocation);
  449. if (!eventDeclaration.AddAccessor.Body.IsNull) {
  450. if (!policy.AllowEventAddBlockInline || eventDeclaration.AddAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.AddAccessor.Body.RBraceToken.StartLocation.Line) {
  451. EnforceBraceStyle (policy.EventAddBraceStyle, eventDeclaration.AddAccessor.Body.LBraceToken, eventDeclaration.AddAccessor.Body.RBraceToken);
  452. } else {
  453. nextStatementIndent = " ";
  454. }
  455. VisitBlockWithoutFixIndentation (eventDeclaration.AddAccessor.Body, policy.IndentBlocks, data);
  456. }
  457. }
  458. if (!eventDeclaration.RemoveAccessor.IsNull) {
  459. FixIndentation (eventDeclaration.RemoveAccessor.StartLocation);
  460. if (!eventDeclaration.RemoveAccessor.Body.IsNull) {
  461. if (!policy.AllowEventRemoveBlockInline || eventDeclaration.RemoveAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.RemoveAccessor.Body.RBraceToken.StartLocation.Line) {
  462. EnforceBraceStyle (policy.EventRemoveBraceStyle, eventDeclaration.RemoveAccessor.Body.LBraceToken, eventDeclaration.RemoveAccessor.Body.RBraceToken);
  463. } else {
  464. nextStatementIndent = " ";
  465. }
  466. VisitBlockWithoutFixIndentation (eventDeclaration.RemoveAccessor.Body, policy.IndentBlocks, data);
  467. }
  468. }
  469. if (policy.IndentEventBody)
  470. IndentLevel--;
  471. if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) {
  472. EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields);
  473. } else if (IsMember (eventDeclaration.NextSibling)) {
  474. EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenMembers);
  475. }
  476. return null;
  477. }
  478. public override object VisitEventDeclaration (EventDeclaration eventDeclaration, object data)
  479. {
  480. FormatAttributedNode (eventDeclaration);
  481. if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) {
  482. EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields);
  483. } else if (IsMember (eventDeclaration.NextSibling)) {
  484. EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenMembers);
  485. }
  486. return null;
  487. }
  488. public override object VisitAccessor (Accessor accessor, object data)
  489. {
  490. FixIndentationForceNewLine (accessor.StartLocation);
  491. object result = base.VisitAccessor (accessor, data);
  492. return result;
  493. }
  494. public override object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data)
  495. {
  496. FormatAttributedNode (fieldDeclaration);
  497. FormatCommas (fieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma);
  498. if (fieldDeclaration.NextSibling is FieldDeclaration || fieldDeclaration.NextSibling is FixedFieldDeclaration) {
  499. EnsureBlankLinesAfter (fieldDeclaration, policy.BlankLinesBetweenFields);
  500. } else if (IsMember (fieldDeclaration.NextSibling)) {
  501. EnsureBlankLinesAfter (fieldDeclaration, policy.BlankLinesBetweenMembers);
  502. }
  503. return base.VisitFieldDeclaration (fieldDeclaration, data);
  504. }
  505. public override object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data)
  506. {
  507. FormatAttributedNode (fixedFieldDeclaration);
  508. FormatCommas (fixedFieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma);
  509. if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration) {
  510. EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenFields);
  511. } else if (IsMember (fixedFieldDeclaration.NextSibling)) {
  512. EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenMembers);
  513. }
  514. return base.VisitFixedFieldDeclaration (fixedFieldDeclaration, data);
  515. }
  516. public override object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data)
  517. {
  518. FormatAttributedNode (enumMemberDeclaration);
  519. return base.VisitEnumMemberDeclaration (enumMemberDeclaration, data);
  520. }
  521. public override object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data)
  522. {
  523. FormatAttributedNode (delegateDeclaration);
  524. ForceSpacesBefore (delegateDeclaration.LParToken, policy.SpaceBeforeDelegateDeclarationParentheses);
  525. if (delegateDeclaration.Parameters.Any ()) {
  526. ForceSpacesAfter (delegateDeclaration.LParToken, policy.SpaceWithinDelegateDeclarationParentheses);
  527. ForceSpacesBefore (delegateDeclaration.RParToken, policy.SpaceWithinDelegateDeclarationParentheses);
  528. } else {
  529. ForceSpacesAfter (delegateDeclaration.LParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses);
  530. ForceSpacesBefore (delegateDeclaration.RParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses);
  531. }
  532. FormatCommas (delegateDeclaration, policy.SpaceBeforeDelegateDeclarationParameterComma, policy.SpaceAfterDelegateDeclarationParameterComma);
  533. if (delegateDeclaration.NextSibling is TypeDeclaration || delegateDeclaration.NextSibling is DelegateDeclaration) {
  534. EnsureBlankLinesAfter (delegateDeclaration, policy.BlankLinesBetweenTypes);
  535. } else if (IsMember (delegateDeclaration.NextSibling)) {
  536. EnsureBlankLinesAfter (delegateDeclaration, policy.BlankLinesBetweenMembers);
  537. }
  538. return base.VisitDelegateDeclaration (delegateDeclaration, data);
  539. }
  540. static bool IsMember (AstNode nextSibling)
  541. {
  542. return nextSibling != null && nextSibling.NodeType == NodeType.Member;
  543. }
  544. void FormatAttributedNode (AstNode node)
  545. {
  546. if (node == null)
  547. return;
  548. AstNode child = node.FirstChild;
  549. while (child != null && child is AttributeSection) {
  550. FixIndentationForceNewLine (child.StartLocation);
  551. child = child.NextSibling;
  552. }
  553. if (child != null)
  554. FixIndentationForceNewLine (child.StartLocation);
  555. }
  556. public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data)
  557. {
  558. FormatAttributedNode (methodDeclaration);
  559. ForceSpacesBefore (methodDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses);
  560. if (methodDeclaration.Parameters.Any ()) {
  561. ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses);
  562. ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses);
  563. } else {
  564. ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
  565. ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
  566. }
  567. FormatCommas (methodDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma);
  568. if (!methodDeclaration.Body.IsNull) {
  569. EnforceBraceStyle (policy.MethodBraceStyle, methodDeclaration.Body.LBraceToken, methodDeclaration.Body.RBraceToken);
  570. if (policy.IndentMethodBody)
  571. IndentLevel++;
  572. base.VisitBlockStatement (methodDeclaration.Body, data);
  573. if (policy.IndentMethodBody)
  574. IndentLevel--;
  575. }
  576. if (IsMember (methodDeclaration.NextSibling))
  577. EnsureBlankLinesAfter (methodDeclaration, policy.BlankLinesBetweenMembers);
  578. return null;
  579. }
  580. public override object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data)
  581. {
  582. FormatAttributedNode (operatorDeclaration);
  583. ForceSpacesBefore (operatorDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses);
  584. if (operatorDeclaration.Parameters.Any ()) {
  585. ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses);
  586. ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses);
  587. } else {
  588. ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
  589. ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses);
  590. }
  591. FormatCommas (operatorDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma);
  592. if (!operatorDeclaration.Body.IsNull) {
  593. EnforceBraceStyle (policy.MethodBraceStyle, operatorDeclaration.Body.LBraceToken, operatorDeclaration.Body.RBraceToken);
  594. if (policy.IndentMethodBody)
  595. IndentLevel++;
  596. base.VisitBlockStatement (operatorDeclaration.Body, data);
  597. if (policy.IndentMethodBody)
  598. IndentLevel--;
  599. }
  600. if (IsMember (operatorDeclaration.NextSibling))
  601. EnsureBlankLinesAfter (operatorDeclaration, policy.BlankLinesBetweenMembers);
  602. return null;
  603. }
  604. public override object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data)
  605. {
  606. FormatAttributedNode (constructorDeclaration);
  607. ForceSpacesBefore (constructorDeclaration.LParToken, policy.SpaceBeforeConstructorDeclarationParentheses);
  608. if (constructorDeclaration.Parameters.Any ()) {
  609. ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceWithinConstructorDeclarationParentheses);
  610. ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceWithinConstructorDeclarationParentheses);
  611. } else {
  612. ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses);
  613. ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses);
  614. }
  615. FormatCommas (constructorDeclaration, policy.SpaceBeforeConstructorDeclarationParameterComma, policy.SpaceAfterConstructorDeclarationParameterComma);
  616. object result = null;
  617. if (!constructorDeclaration.Body.IsNull) {
  618. EnforceBraceStyle (policy.ConstructorBraceStyle, constructorDeclaration.Body.LBraceToken, constructorDeclaration.Body.RBraceToken);
  619. if (policy.IndentMethodBody)
  620. IndentLevel++;
  621. result = base.VisitBlockStatement (constructorDeclaration.Body, data);
  622. if (policy.IndentMethodBody)
  623. IndentLevel--;
  624. }
  625. if (IsMember (constructorDeclaration.NextSibling))
  626. EnsureBlankLinesAfter (constructorDeclaration, policy.BlankLinesBetweenMembers);
  627. return result;
  628. }
  629. public override object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data)
  630. {
  631. FormatAttributedNode (destructorDeclaration);
  632. CSharpTokenNode lParen = destructorDeclaration.LParToken;
  633. int offset = this.document.GetOffset (lParen.StartLocation);
  634. ForceSpaceBefore (offset, policy.SpaceBeforeConstructorDeclarationParentheses);
  635. object result = null;
  636. if (!destructorDeclaration.Body.IsNull) {
  637. EnforceBraceStyle (policy.DestructorBraceStyle, destructorDeclaration.Body.LBraceToken, destructorDeclaration.Body.RBraceToken);
  638. if (policy.IndentMethodBody)
  639. IndentLevel++;
  640. result = base.VisitBlockStatement (destructorDeclaration.Body, data);
  641. if (policy.IndentMethodBody)
  642. IndentLevel--;
  643. }
  644. if (IsMember (destructorDeclaration.NextSibling))
  645. EnsureBlankLinesAfter (destructorDeclaration, policy.BlankLinesBetweenMembers);
  646. return result;
  647. }
  648. #region Statements
  649. public override object VisitExpressionStatement (ExpressionStatement expressionStatement, object data)
  650. {
  651. FixStatementIndentation (expressionStatement.StartLocation);
  652. FixSemicolon (expressionStatement.SemicolonToken);
  653. return base.VisitExpressionStatement (expressionStatement, data);
  654. }
  655. object VisitBlockWithoutFixIndentation (BlockStatement blockStatement, bool indent, object data)
  656. {
  657. if (indent)
  658. IndentLevel++;
  659. object result = base.VisitBlockStatement (blockStatement, data);
  660. if (indent)
  661. IndentLevel--;
  662. return result;
  663. }
  664. public override object VisitBlockStatement (BlockStatement blockStatement, object data)
  665. {
  666. FixIndentation (blockStatement.StartLocation);
  667. object result = VisitBlockWithoutFixIndentation (blockStatement, policy.IndentBlocks, data);
  668. FixIndentation (blockStatement.EndLocation, -1);
  669. return result;
  670. }
  671. public override object VisitComment (Comment comment, object data)
  672. {
  673. if (comment.StartsLine && !HadErrors && comment.StartLocation.Column > 1)
  674. FixIndentation (comment.StartLocation);
  675. return null;
  676. }
  677. public override object VisitBreakStatement (BreakStatement breakStatement, object data)
  678. {
  679. FixStatementIndentation (breakStatement.StartLocation);
  680. return null;
  681. }
  682. public override object VisitCheckedStatement (CheckedStatement checkedStatement, object data)
  683. {
  684. FixStatementIndentation (checkedStatement.StartLocation);
  685. return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, checkedStatement.Body);
  686. }
  687. public override object VisitContinueStatement (ContinueStatement continueStatement, object data)
  688. {
  689. FixStatementIndentation (continueStatement.StartLocation);
  690. return null;
  691. }
  692. public override object VisitEmptyStatement (EmptyStatement emptyStatement, object data)
  693. {
  694. FixStatementIndentation (emptyStatement.StartLocation);
  695. return null;
  696. }
  697. public override object VisitFixedStatement (FixedStatement fixedStatement, object data)
  698. {
  699. FixStatementIndentation (fixedStatement.StartLocation);
  700. return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, fixedStatement.EmbeddedStatement);
  701. }
  702. public override object VisitForeachStatement (ForeachStatement foreachStatement, object data)
  703. {
  704. FixStatementIndentation (foreachStatement.StartLocation);
  705. ForceSpacesBefore (foreachStatement.LParToken, policy.SpaceBeforeForeachParentheses);
  706. ForceSpacesAfter (foreachStatement.LParToken, policy.SpacesWithinForeachParentheses);
  707. ForceSpacesBefore (foreachStatement.RParToken, policy.SpacesWithinForeachParentheses);
  708. return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForEachBraceForcement, foreachStatement.EmbeddedStatement);
  709. }
  710. object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, AstNode node)
  711. {
  712. return FixEmbeddedStatment (braceStyle, braceForcement, null, false, node);
  713. }
  714. object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, CSharpTokenNode token, bool allowInLine, AstNode node)
  715. {
  716. if (node == null)
  717. return null;
  718. int originalLevel = curIndent.Level;
  719. bool isBlock = node is BlockStatement;
  720. switch (braceForcement) {
  721. case BraceForcement.DoNotChange:
  722. //nothing
  723. break;
  724. case BraceForcement.AddBraces:
  725. if (!isBlock) {
  726. AstNode n = node.Parent.GetCSharpNodeBefore (node);
  727. int start = document.GetOffset (n.EndLocation);
  728. var next = n.GetNextNode ();
  729. int offset = document.GetOffset (next.StartLocation);
  730. string startBrace = "";
  731. switch (braceStyle) {
  732. case BraceStyle.EndOfLineWithoutSpace:
  733. startBrace = "{";
  734. break;
  735. case BraceStyle.EndOfLine:
  736. startBrace = " {";
  737. break;
  738. case BraceStyle.NextLine:
  739. startBrace = this.EolMarker + curIndent.IndentString + "{";
  740. break;
  741. case BraceStyle.NextLineShifted2:
  742. case BraceStyle.NextLineShifted:
  743. startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{";
  744. break;
  745. }
  746. if (IsLineIsEmptyUpToEol (document.GetOffset (node.StartLocation)))
  747. startBrace += this.EolMarker + GetIndentation (node.StartLocation.Line);
  748. AddChange (start, offset - start, startBrace);
  749. }
  750. break;
  751. case BraceForcement.RemoveBraces:
  752. if (isBlock) {
  753. BlockStatement block = node as BlockStatement;
  754. if (block.Statements.Count () == 1) {
  755. int offset1 = document.GetOffset (node.StartLocation);
  756. int start = SearchWhitespaceStart (offset1);
  757. int offset2 = document.GetOffset (node.EndLocation);
  758. int end = SearchWhitespaceStart (offset2 - 1);
  759. AddChange (start, offset1 - start + 1, null);
  760. AddChange (end + 1, offset2 - end, null);
  761. node = block.FirstChild;
  762. isBlock = false;
  763. }
  764. }
  765. break;
  766. }
  767. if (isBlock) {
  768. BlockStatement block = node as BlockStatement;
  769. if (allowInLine && block.StartLocation.Line == block.EndLocation.Line && block.Statements.Count () <= 1) {
  770. if (block.Statements.Count () == 1)
  771. nextStatementIndent = " ";
  772. } else {
  773. EnforceBraceStyle (braceStyle, block.LBraceToken, block.RBraceToken);
  774. }
  775. if (braceStyle == BraceStyle.NextLineShifted2)
  776. curIndent.Level++;
  777. } else {
  778. if (allowInLine && token.StartLocation.Line == node.EndLocation.Line) {
  779. nextStatementIndent = " ";
  780. }
  781. }
  782. if (!(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement ||
  783. policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement))
  784. curIndent.Level++;
  785. object result = isBlock ? base.VisitBlockStatement ((BlockStatement)node, null) : node.AcceptVisitor (this, null);
  786. curIndent.Level = originalLevel;
  787. switch (braceForcement) {
  788. case BraceForcement.DoNotChange:
  789. break;
  790. case BraceForcement.AddBraces:
  791. if (!isBlock) {
  792. int offset = document.GetOffset (node.EndLocation);
  793. if (!char.IsWhiteSpace (document.GetCharAt (offset)))
  794. offset++;
  795. string startBrace = "";
  796. switch (braceStyle) {
  797. case BraceStyle.DoNotChange:
  798. startBrace = null;
  799. break;
  800. case BraceStyle.EndOfLineWithoutSpace:
  801. startBrace = this.EolMarker + curIndent.IndentString + "}";
  802. break;
  803. case BraceStyle.EndOfLine:
  804. startBrace = this.EolMarker + curIndent.IndentString + "}";
  805. break;
  806. case BraceStyle.NextLine:
  807. startBrace = this.EolMarker + curIndent.IndentString + "}";
  808. break;
  809. case BraceStyle.NextLineShifted2:
  810. case BraceStyle.NextLineShifted:
  811. startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}";
  812. break;
  813. }
  814. if (startBrace != null)
  815. AddChange (offset, 0, startBrace);
  816. }
  817. break;
  818. }
  819. return result;
  820. }
  821. void EnforceBraceStyle (BraceStyle braceStyle, AstNode lbrace, AstNode rbrace)
  822. {
  823. if (lbrace.IsNull || rbrace.IsNull)
  824. return;
  825. // LineSegment lbraceLineSegment = data.Document.GetLine (lbrace.StartLocation.Line);
  826. int lbraceOffset = document.GetOffset (lbrace.StartLocation);
  827. // LineSegment rbraceLineSegment = data.Document.GetLine (rbrace.StartLocation.Line);
  828. int rbraceOffset = document.GetOffset (rbrace.StartLocation);
  829. int whitespaceStart = SearchWhitespaceStart (lbraceOffset);
  830. int whitespaceEnd = SearchWhitespaceLineStart (rbraceOffset);
  831. string startIndent = "";
  832. string endIndent = "";
  833. switch (braceStyle) {
  834. case BraceStyle.DoNotChange:
  835. startIndent = endIndent = null;
  836. break;
  837. case BraceStyle.EndOfLineWithoutSpace:
  838. startIndent = "";
  839. endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString;
  840. break;
  841. case BraceStyle.EndOfLine:
  842. var prevNode = lbrace.GetPrevNode ();
  843. if (prevNode is Comment) {
  844. // delete old bracket
  845. AddChange (whitespaceStart, lbraceOffset - whitespaceStart + 1, "");
  846. while (prevNode is Comment) {
  847. prevNode = prevNode.GetPrevNode ();
  848. }
  849. whitespaceStart = document.GetOffset (prevNode.EndLocation);
  850. lbraceOffset = whitespaceStart;
  851. startIndent = " {";
  852. } else {
  853. startIndent = " ";
  854. }
  855. endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString;
  856. break;
  857. case BraceStyle.NextLine:
  858. startIndent = this.EolMarker + curIndent.IndentString;
  859. endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString;
  860. break;
  861. case BraceStyle.NextLineShifted2:
  862. case BraceStyle.NextLineShifted:
  863. startIndent = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent;
  864. endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : this.EolMarker + curIndent.IndentString + curIndent.SingleIndent;
  865. break;
  866. }
  867. if (lbraceOffset > 0 && startIndent != null)
  868. AddChange (whitespaceStart, lbraceOffset - whitespaceStart, startIndent);
  869. if (rbraceOffset > 0 && endIndent != null)
  870. AddChange (whitespaceEnd, rbraceOffset - whitespaceEnd, endIndent);
  871. }
  872. void AddChange (int offset, int removedChars, string insertedText)
  873. {
  874. if (changes.Any (c => c.Offset == offset && c.RemovedChars == removedChars
  875. && c.InsertedText == insertedText))
  876. return;
  877. string currentText = document.GetText (offset, removedChars);
  878. if (currentText == insertedText)
  879. return;
  880. if (currentText.Any (c => !(char.IsWhiteSpace (c) || c == '\r' || c == '\t' || c == '{' || c == '}')))
  881. throw new InvalidOperationException ("Tried to remove non ws chars: '" + currentText + "'");
  882. foreach (var change in changes) {
  883. if (change.Offset == offset) {
  884. if (removedChars > 0 && insertedText == change.InsertedText) {
  885. change.RemovedChars = removedChars;
  886. // change.InsertedText = insertedText;
  887. return;
  888. }
  889. if (!string.IsNullOrEmpty (change.InsertedText)) {
  890. change.InsertedText += insertedText;
  891. } else {
  892. change.InsertedText = insertedText;
  893. }
  894. change.RemovedChars = System.Math.Max (removedChars, change.RemovedChars);
  895. return;
  896. }
  897. }
  898. //Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "<null>" : insertedText.Replace ("\n", "\\n").Replace ("\r", "\\r").Replace ("\t", "\\t").Replace (" ", "."));
  899. //Console.WriteLine (Environment.StackTrace);
  900. changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText));
  901. }
  902. public bool IsLineIsEmptyUpToEol (TextLocation startLocation)
  903. {
  904. return IsLineIsEmptyUpToEol (document.GetOffset (startLocation) - 1);
  905. }
  906. bool IsLineIsEmptyUpToEol (int startOffset)
  907. {
  908. for (int offset = startOffset - 1; offset >= 0; offset--) {
  909. char ch = document.GetCharAt (offset);
  910. if (ch != ' ' && ch != '\t')
  911. return ch == '\n' || ch == '\r';
  912. }
  913. return true;
  914. }
  915. int SearchWhitespaceStart (int startOffset)
  916. {
  917. if (startOffset < 0)
  918. throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset);
  919. for (int offset = startOffset - 1; offset >= 0; offset--) {
  920. char ch = document.GetCharAt (offset);
  921. if (!Char.IsWhiteSpace (ch)) {
  922. return offset + 1;
  923. }
  924. }
  925. return 0;
  926. }
  927. int SearchWhitespaceEnd (int startOffset)
  928. {
  929. if (startOffset > document.TextLength)
  930. throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset);
  931. for (int offset = startOffset + 1; offset < document.TextLength; offset++) {
  932. char ch = document.GetCharAt (offset);
  933. if (!Char.IsWhiteSpace (ch)) {
  934. return offset + 1;
  935. }
  936. }
  937. return document.TextLength - 1;
  938. }
  939. int SearchWhitespaceLineStart (int startOffset)
  940. {
  941. if (startOffset < 0)
  942. throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset);
  943. for (int offset = startOffset - 1; offset >= 0; offset--) {
  944. char ch = document.GetCharAt (offset);
  945. if (ch != ' ' && ch != '\t') {
  946. return offset + 1;
  947. }
  948. }
  949. return 0;
  950. }
  951. public override object VisitForStatement (ForStatement forStatement, object data)
  952. {
  953. FixStatementIndentation (forStatement.StartLocation);
  954. foreach (AstNode node in forStatement.Children) {
  955. if (node.Role == ForStatement.Roles.Semicolon) {
  956. if (node.NextSibling is CSharpTokenNode || node.NextSibling is EmptyStatement)
  957. continue;
  958. ForceSpacesBefore (node, policy.SpaceBeforeForSemicolon);
  959. ForceSpacesAfter (node, policy.SpaceAfterForSemicolon);
  960. }
  961. }
  962. ForceSpacesBefore (forStatement.LParToken, policy.SpaceBeforeForParentheses);
  963. ForceSpacesAfter (forStatement.LParToken, policy.SpacesWithinForParentheses);
  964. ForceSpacesBefore (forStatement.RParToken, policy.SpacesWithinForParentheses);
  965. return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForBraceForcement, forStatement.EmbeddedStatement);
  966. }
  967. public override object VisitGotoStatement (GotoStatement gotoStatement, object data)
  968. {
  969. FixStatementIndentation (gotoStatement.StartLocation);
  970. return VisitChildren (gotoStatement, data);
  971. }
  972. public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data)
  973. {
  974. ForceSpacesBefore (ifElseStatement.LParToken, policy.SpaceBeforeIfParentheses);
  975. ForceSpacesAfter (ifElseStatement.LParToken, policy.SpacesWithinIfParentheses);
  976. ForceSpacesBefore (ifElseStatement.RParToken, policy.SpacesWithinIfParentheses);
  977. if (!(ifElseStatement.Parent is IfElseStatement && ((IfElseStatement)ifElseStatement.Parent).FalseStatement == ifElseStatement))
  978. FixStatementIndentation (ifElseStatement.StartLocation);
  979. if (!ifElseStatement.Condition.IsNull)
  980. ifElseStatement.Condition.AcceptVisitor (this, data);
  981. if (!ifElseStatement.TrueStatement.IsNull)
  982. FixEmbeddedStatment (policy.StatementBraceStyle, policy.IfElseBraceForcement, ifElseStatement.IfToken, policy.AllowIfBlockInline, ifElseStatement.TrueStatement);
  983. if (!ifElseStatement.FalseStatement.IsNull) {
  984. PlaceOnNewLine (policy.PlaceElseOnNewLine || !(ifElseStatement.TrueStatement is BlockStatement) && policy.IfElseBraceForcement != BraceForcement.AddBraces, ifElseStatement.ElseToken);
  985. var forcement = policy.IfElseBraceForcement;
  986. if (ifElseStatement.FalseStatement is IfElseStatement) {
  987. forcement = BraceForcement.DoNotChange;
  988. PlaceOnNewLine (policy.PlaceElseIfOnNewLine, ((IfElseStatement)ifElseStatement.FalseStatement).IfToken);
  989. }
  990. FixEmbeddedStatment (policy.StatementBraceStyle, forcement, ifElseStatement.ElseToken, policy.AllowIfBlockInline, ifElseStatement.FalseStatement);
  991. }
  992. return null;
  993. }
  994. public override object VisitLabelStatement (LabelStatement labelStatement, object data)
  995. {
  996. // TODO
  997. return VisitChildren (labelStatement, data);
  998. }
  999. public override object VisitLockStatement (LockStatement lockStatement, object data)
  1000. {
  1001. FixStatementIndentation (lockStatement.StartLocation);
  1002. ForceSpacesBefore (lockStatement.LParToken, policy.SpaceBeforeLockParentheses);
  1003. ForceSpacesAfter (lockStatement.LParToken, policy.SpacesWithinLockParentheses);
  1004. ForceSpacesBefore (lockStatement.RParToken, policy.SpacesWithinLockParentheses);
  1005. return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, lockStatement.EmbeddedStatement);
  1006. }
  1007. public override object VisitReturnStatement (ReturnStatement returnStatement, object data)
  1008. {
  1009. FixStatementIndentation (returnStatement.StartLocation);
  1010. return VisitChildren (returnStatement, data);
  1011. }
  1012. public override object VisitSwitchStatement (SwitchStatement switchStatement, object data)
  1013. {
  1014. FixStatementIndentation (switchStatement.StartLocation);
  1015. ForceSpacesBefore (switchStatement.LParToken, policy.SpaceBeforeSwitchParentheses);
  1016. ForceSpacesAfter (switchStatement.LParToken, policy.SpacesWithinSwitchParentheses);
  1017. ForceSpacesBefore (switchStatement.RParToken, policy.SpacesWithinSwitchParentheses);
  1018. EnforceBraceStyle (policy.StatementBraceStyle, switchStatement.LBraceToken, switchStatement.RBraceToken);
  1019. object result = VisitChildren (switchStatement, data);
  1020. return result;
  1021. }
  1022. public override object VisitSwitchSection (SwitchSection switchSection, object data)
  1023. {
  1024. if (policy.IndentSwitchBody)
  1025. curIndent.Level++;
  1026. foreach (CaseLabel label in switchSection.CaseLabels) {
  1027. FixStatementIndentation (label.StartLocation);
  1028. }
  1029. if (policy.IndentCaseBody)
  1030. curIndent.Level++;
  1031. foreach (var stmt in switchSection.Statements) {
  1032. stmt.AcceptVisitor (this, null);
  1033. }
  1034. if (policy.IndentCaseBody)
  1035. curIndent.Level--;
  1036. if (policy.IndentSwitchBody)
  1037. curIndent.Level--;
  1038. return null;
  1039. }
  1040. public override object VisitCaseLabel (CaseLabel caseLabel, object data)
  1041. {
  1042. // handled in switchsection
  1043. return null;
  1044. }
  1045. public override object VisitThrowStatement (ThrowStatement throwStatement, object data)
  1046. {
  1047. FixStatementIndentation (throwStatement.StartLocation);
  1048. return VisitChildren (throwStatement, data);
  1049. }
  1050. public override object VisitTryCatchStatement (TryCatchStatement tryCatchStatement, object data)
  1051. {
  1052. FixStatementIndentation (tryCatchStatement.StartLocation);
  1053. if (!tryCatchStatement.TryBlock.IsNull)
  1054. FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.TryBlock);
  1055. foreach (CatchClause clause in tryCatchStatement.CatchClauses) {
  1056. PlaceOnNewLine (policy.PlaceCatchOnNewLine, clause.CatchToken);
  1057. if (!clause.LParToken.IsNull) {
  1058. ForceSpacesBefore (clause.LParToken, policy.SpaceBeforeCatchParentheses);
  1059. ForceSpacesAfter (clause.LParToken, policy.SpacesWithinCatchParentheses);
  1060. ForceSpacesBefore (clause.RParToken, policy.SpacesWithinCatchParentheses);
  1061. }
  1062. FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, clause.Body);
  1063. }
  1064. if (!tryCatchStatement.FinallyBlock.IsNull) {
  1065. PlaceOnNewLine (policy.PlaceFinallyOnNewLine, tryCatchStatement.FinallyToken);
  1066. FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.FinallyBlock);
  1067. }
  1068. return VisitChildren (tryCatchStatement, data);
  1069. }
  1070. public override object VisitCatchClause (CatchClause catchClause, object data)
  1071. {
  1072. // Handled in TryCatchStatement
  1073. return null;
  1074. }
  1075. public override object VisitUncheckedStatement (UncheckedStatement uncheckedStatement, object data)
  1076. {
  1077. FixStatementIndentation (uncheckedStatement.StartLocation);
  1078. return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, uncheckedStatement.Body);
  1079. }
  1080. public override object VisitUnsafeStatement (UnsafeStatement unsafeStatement, object data)
  1081. {
  1082. FixStatementIndentation (unsafeStatement.StartLocation);
  1083. return FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, unsafeStatement.Body);
  1084. }
  1085. public override object VisitUsingStatement (UsingStatement usingStatement, object data)
  1086. {
  1087. FixStatementIndentation (usingStatement.StartLocation);
  1088. ForceSpacesBefore (usingStatement.LParToken, policy.SpaceBeforeUsingParentheses);
  1089. ForceSpacesAfter (usingStatement.LParToken, policy.SpacesWithinUsingParentheses);
  1090. ForceSpacesBefore (usingStatement.RParToken, policy.SpacesWithinUsingParentheses);
  1091. return FixEmbeddedStatment (policy.StatementBraceStyle, policy.UsingBraceForcement, usingStatement.EmbeddedStatement);
  1092. }
  1093. public override object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data)
  1094. {
  1095. if (!variableDeclarationStatement.SemicolonToken.IsNull)
  1096. FixStatementIndentation (variableDeclarationStatement.StartLocation);
  1097. if ((variableDeclarationStatement.Modifiers & Modifiers.Const) == Modifiers.Const) {
  1098. ForceSpacesAround (variableDeclarationStatement.Type, true);
  1099. } else {
  1100. ForceSpacesAfter (variableDeclarationStatement.Type, true);
  1101. }
  1102. foreach (var initializer in variableDeclarationStatement.Variables) {
  1103. initializer.AcceptVisitor (this, data);
  1104. }
  1105. FormatCommas (variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma);
  1106. FixSemicolon (variableDeclarationStatement.SemicolonToken);
  1107. return null;
  1108. }
  1109. public override object VisitDoWhileStatement (DoWhileStatement doWhile

Large files files are truncated, but you can click here to view the full file