~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Formatter/CSharpIndentEngine.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// CSharpIndentEngine.cs
 
3
//
 
4
// Author:
 
5
//       Mike KrĆ¼ger <mkrueger@xamarin.com>
 
6
//
 
7
// Copyright (c) 2012 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.
 
26
using System;
 
27
using ICSharpCode.NRefactory.Editor;
 
28
using System.Text;
 
29
using System.Collections.Generic;
 
30
using System.Linq;
 
31
using System.Globalization;
 
32
 
 
33
namespace ICSharpCode.NRefactory.CSharp
 
34
{
 
35
        public class CSharpIndentEngine
 
36
        {
 
37
                readonly IDocument document;
 
38
                readonly CSharpFormattingOptions options;
 
39
                readonly TextEditorOptions textEditorOptions;
 
40
                readonly StringBuilder wordBuf = new StringBuilder();
 
41
                readonly StringBuilder currentIndent = new StringBuilder();
 
42
                Indent thisLineindent;
 
43
                Indent indent;
 
44
                Indent indentDelta;
 
45
 
 
46
                public IList<string> ConditionalSymbols {
 
47
                        get;
 
48
                        set;
 
49
                }
 
50
 
 
51
                public TextLocation Location {
 
52
                        get {
 
53
                                return new TextLocation(line, col);
 
54
                        }
 
55
                }
 
56
 
 
57
                public int Offset {
 
58
                        get {
 
59
                                return offset;
 
60
                        }
 
61
                }
 
62
 
 
63
                public string ThisLineIndent {
 
64
                        get {
 
65
                                return thisLineindent.IndentString;
 
66
                        }
 
67
                }
 
68
 
 
69
                public string NewLineIndent {
 
70
                        get {
 
71
                                return indent.IndentString + indentDelta.IndentString;
 
72
                        }
 
73
                }
 
74
 
 
75
                public bool NeedsReindent {
 
76
                        get {
 
77
                                return ThisLineIndent != currentIndent.ToString();
 
78
                        }
 
79
                }
 
80
 
 
81
                public CSharpIndentEngine(IDocument document, TextEditorOptions textEditorOptions, CSharpFormattingOptions formattingOptions)
 
82
                {
 
83
                        this.document = document;
 
84
                        this.options = formattingOptions;
 
85
                        this.textEditorOptions = textEditorOptions;
 
86
                        this.indent = new Indent(textEditorOptions);
 
87
                        this.indentDelta = new Indent(textEditorOptions);
 
88
                        this.thisLineindent = new Indent(textEditorOptions);
 
89
                }
 
90
 
 
91
                CSharpIndentEngine(CSharpIndentEngine prototype)
 
92
                {
 
93
                        this.document = prototype.document;
 
94
                        this.options = prototype.options;
 
95
                        this.textEditorOptions = prototype.textEditorOptions;
 
96
                        this.indent = prototype.indent.Clone();
 
97
                        this.indentDelta = prototype.indentDelta.Clone();
 
98
                        this.thisLineindent = prototype.thisLineindent.Clone();
 
99
                        this.offset = prototype.offset;
 
100
                        this.inside = prototype.inside;
 
101
                        this.IsLineStart = prototype.IsLineStart;
 
102
                        this.pc = prototype.pc;
 
103
                        this.parenStack = new Stack<TextLocation>(prototype.parenStack.Reverse());
 
104
                        this.currentBody = prototype.currentBody;
 
105
                        this.nextBody = prototype.nextBody;
 
106
                        this.addContinuation = prototype.addContinuation;
 
107
                        this.line = prototype.line;
 
108
                        this.col = prototype.col;
 
109
                        this.popNextParenBlock = prototype.popNextParenBlock;
 
110
                }
 
111
 
 
112
                public CSharpIndentEngine Clone()
 
113
                {
 
114
                        return new CSharpIndentEngine(this);
 
115
                }
 
116
 
 
117
                int offset;
 
118
                Inside inside = Inside.Empty;
 
119
                bool IsLineStart = true;
 
120
                char pc;
 
121
                Stack<TextLocation> parenStack = new Stack<TextLocation>();
 
122
                Body currentBody;
 
123
                Body nextBody;
 
124
                bool addContinuation;
 
125
                int line, col;
 
126
                bool popNextParenBlock;
 
127
                bool readPreprocessorExpression;
 
128
 
 
129
                public void Reset()
 
130
                {
 
131
                        offset = 0;
 
132
                        thisLineindent.Reset();
 
133
                        indent.Reset();
 
134
                        pc = '\0';
 
135
                        IsLineStart = true;
 
136
                        addContinuation = false;
 
137
                        popNextParenBlock = false;
 
138
                        parenStack.Clear();
 
139
                        inside = Inside.Empty;
 
140
                        nextBody = currentBody = Body.None;
 
141
                        line = col = 1;
 
142
                }
 
143
 
 
144
                public void UpdateToOffset(int toOffset)
 
145
                {
 
146
                        if (toOffset < offset)
 
147
                                Reset();
 
148
                        for (int i = offset; i < toOffset; i++)
 
149
                                Push(document.GetCharAt(i));
 
150
                }
 
151
 
 
152
                public bool IsInStringOrChar {
 
153
                        get {
 
154
                                return inside.HasFlag(Inside.StringOrChar);
 
155
                        }
 
156
                }
 
157
 
 
158
                public bool IsInComment {
 
159
                        get {
 
160
                                return inside.HasFlag(Inside.Comment);
 
161
                        }
 
162
                }
 
163
 
 
164
                public bool IsInPreProcessorComment {
 
165
                        get {
 
166
                                return inside.HasFlag(Inside.PreProcessorComment);
 
167
                        }
 
168
                }
 
169
 
 
170
                public bool IsInPreProcessorDirective {
 
171
                        get {
 
172
                                return inside.HasFlag(Inside.PreProcessor);
 
173
                        }
 
174
                }
 
175
 
 
176
                public bool IsInVerbatimString {
 
177
                        get {
 
178
                                return inside.HasFlag(Inside.VerbatimString);
 
179
                        }
 
180
                }
 
181
 
 
182
                public bool IsInsideDocLineComment {
 
183
                        get {
 
184
                                return inside.HasFlag(Inside.DocComment);
 
185
                        }
 
186
                }
 
187
 
 
188
                public bool IsInsideMultiLineComment {
 
189
                        get {
 
190
                                return inside.HasFlag(Inside.MultiLineComment);
 
191
                        }
 
192
                }
 
193
 
 
194
                public bool IsInsideStringLiteral {
 
195
                        get {
 
196
                                return inside.HasFlag(Inside.StringLiteral);
 
197
                        }
 
198
                }
 
199
 
 
200
                [Flags]
 
201
                public enum Inside
 
202
                {
 
203
                        Empty              = 0,
 
204
 
 
205
                        PreProcessor       = (1 << 0),
 
206
                        PreProcessorComment = (1 << 12),
 
207
 
 
208
                        MultiLineComment   = (1 << 1),
 
209
                        LineComment        = (1 << 2),
 
210
                        DocComment         = (1 << 11),
 
211
                        Comment            = (MultiLineComment | LineComment | DocComment),
 
212
 
 
213
                        VerbatimString     = (1 << 3),
 
214
                        StringLiteral      = (1 << 4),
 
215
                        CharLiteral        = (1 << 5),
 
216
                        String             = (VerbatimString | StringLiteral),
 
217
                        StringOrChar       = (String | CharLiteral),
 
218
 
 
219
                        Attribute          = (1 << 6),
 
220
                        ParenList          = (1 << 7),
 
221
 
 
222
                        FoldedStatement    = (1 << 8),
 
223
                        Block              = (1 << 9),
 
224
                        Case               = (1 << 10),
 
225
 
 
226
                        FoldedOrBlock      = (FoldedStatement | Block),
 
227
                        FoldedBlockOrCase  = (FoldedStatement | Block | Case)
 
228
                }
 
229
 
 
230
                                                                                                                                #region Pre processor evaluation (from cs-tokenizer.cs)
 
231
                static bool is_identifier_start_character(int c)
 
232
                {
 
233
                        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || Char.IsLetter((char)c);
 
234
                }
 
235
 
 
236
                static bool is_identifier_part_character(char c)
 
237
                {
 
238
                        if (c >= 'a' && c <= 'z')
 
239
                                return true;
 
240
 
 
241
                        if (c >= 'A' && c <= 'Z')
 
242
                                return true;
 
243
 
 
244
                        if (c == '_' || (c >= '0' && c <= '9'))
 
245
                                return true;
 
246
 
 
247
                        if (c < 0x80)
 
248
                                return false;
 
249
 
 
250
                        return Char.IsLetter(c) || Char.GetUnicodeCategory(c) == UnicodeCategory.ConnectorPunctuation;
 
251
                }
 
252
 
 
253
                bool eval_val(string s)
 
254
                {
 
255
                        if (s == "true")
 
256
                                return true;
 
257
                        if (s == "false")
 
258
                                return false;
 
259
 
 
260
                        return ConditionalSymbols != null && ConditionalSymbols.Contains(s);
 
261
                }
 
262
 
 
263
                bool pp_primary(ref string s)
 
264
                {
 
265
                        s = s.Trim();
 
266
                        int len = s.Length;
 
267
 
 
268
                        if (len > 0) {
 
269
                                char c = s [0];
 
270
 
 
271
                                if (c == '(') {
 
272
                                        s = s.Substring(1);
 
273
                                        bool val = pp_expr(ref s, false);
 
274
                                        if (s.Length > 0 && s [0] == ')') {
 
275
                                                s = s.Substring(1);
 
276
                                                return val;
 
277
                                        }
 
278
                                        return false;
 
279
                                }
 
280
 
 
281
                                if (is_identifier_start_character(c)) {
 
282
                                        int j = 1;
 
283
 
 
284
                                        while (j < len) {
 
285
                                                c = s [j];
 
286
 
 
287
                                                if (is_identifier_part_character(c)) {
 
288
                                                        j++;
 
289
                                                        continue;
 
290
                                                }
 
291
                                                bool v = eval_val(s.Substring(0, j));
 
292
                                                s = s.Substring(j);
 
293
                                                return v;
 
294
                                        }
 
295
                                        bool vv = eval_val(s);
 
296
                                        s = "";
 
297
                                        return vv;
 
298
                                }
 
299
                        }
 
300
                        return false;
 
301
                }
 
302
 
 
303
                bool pp_unary(ref string s)
 
304
                {
 
305
                        s = s.Trim();
 
306
                        int len = s.Length;
 
307
 
 
308
                        if (len > 0) {
 
309
                                if (s [0] == '!') {
 
310
                                        if (len > 1 && s [1] == '=') {
 
311
                                                return false;
 
312
                                        }
 
313
                                        s = s.Substring(1);
 
314
                                        return ! pp_primary(ref s);
 
315
                                } else
 
316
                                        return pp_primary(ref s);
 
317
                        } else {
 
318
                                return false;
 
319
                        }
 
320
                }
 
321
 
 
322
                bool pp_eq(ref string s)
 
323
                {
 
324
                        bool va = pp_unary(ref s);
 
325
 
 
326
                        s = s.Trim();
 
327
                        int len = s.Length;
 
328
                        if (len > 0) {
 
329
                                if (s [0] == '=') {
 
330
                                        if (len > 2 && s [1] == '=') {
 
331
                                                s = s.Substring(2);
 
332
                                                return va == pp_unary(ref s);
 
333
                                        } else {
 
334
                                                return false;
 
335
                                        }
 
336
                                } else if (s [0] == '!' && len > 1 && s [1] == '=') {
 
337
                                        s = s.Substring(2);
 
338
 
 
339
                                        return va != pp_unary(ref s);
 
340
 
 
341
                                } 
 
342
                        }
 
343
 
 
344
                        return va;
 
345
 
 
346
                }
 
347
 
 
348
                bool pp_and(ref string s)
 
349
                {
 
350
                        bool va = pp_eq(ref s);
 
351
 
 
352
                        s = s.Trim();
 
353
                        int len = s.Length;
 
354
                        if (len > 0) {
 
355
                                if (s [0] == '&') {
 
356
                                        if (len > 2 && s [1] == '&') {
 
357
                                                s = s.Substring(2);
 
358
                                                return (va & pp_and(ref s));
 
359
                                        } else {
 
360
                                                return false;
 
361
                                        }
 
362
                                } 
 
363
                        }
 
364
                        return va;
 
365
                }
 
366
 
 
367
                //
 
368
                // Evaluates an expression for `#if' or `#elif'
 
369
                //
 
370
                bool pp_expr(ref string s, bool isTerm)
 
371
                {
 
372
                        bool va = pp_and(ref s);
 
373
                        s = s.Trim();
 
374
                        int len = s.Length;
 
375
                        if (len > 0) {
 
376
                                char c = s [0];
 
377
 
 
378
                                if (c == '|') {
 
379
                                        if (len > 2 && s [1] == '|') {
 
380
                                                s = s.Substring(2);
 
381
                                                return va | pp_expr(ref s, isTerm);
 
382
                                        } else {
 
383
 
 
384
                                                return false;
 
385
                                        }
 
386
                                }
 
387
                                if (isTerm) {
 
388
                                        return false;
 
389
                                }
 
390
                        }
 
391
 
 
392
                        return va;
 
393
                }
 
394
 
 
395
                bool eval(string s)
 
396
                {
 
397
                        bool v = pp_expr(ref s, true);
 
398
                        s = s.Trim();
 
399
                        if (s.Length != 0) {
 
400
                                return false;
 
401
                        }
 
402
 
 
403
                        return v;
 
404
                }
 
405
                #endregion
 
406
                
 
407
                public void Push(char ch)
 
408
                {
 
409
                        if (readPreprocessorExpression) {
 
410
                                wordBuf.Append(ch);
 
411
                        }
 
412
 
 
413
                        if (inside.HasFlag(Inside.VerbatimString) && pc == '"' && ch != '"') {
 
414
                                inside &= ~Inside.StringLiteral;
 
415
                        }
 
416
                        switch (ch) {
 
417
                                case '#':
 
418
                                        if (IsLineStart)
 
419
                                                inside = Inside.PreProcessor;
 
420
                                        break;
 
421
                                case '/':
 
422
                                        if (IsInStringOrChar || IsInPreProcessorComment)
 
423
                                                break;
 
424
                                        if (pc == '/') {
 
425
                                                if (inside.HasFlag(Inside.Comment)) {
 
426
                                                        inside |= Inside.DocComment;
 
427
                                                } else {
 
428
                                                        inside |= Inside.Comment;
 
429
                                                }
 
430
                                        }
 
431
                                        break;
 
432
                                case '*':
 
433
                                        if (IsInStringOrChar || IsInComment || IsInPreProcessorComment)
 
434
                                                break;
 
435
                                        if (pc == '/')
 
436
                                                inside |= Inside.MultiLineComment;
 
437
                                        break;
 
438
                                case ' ':
 
439
                                        currentIndent.Append(' ');
 
440
                                        break;
 
441
                                case '\t':
 
442
                                        var nextTabStop = (col - 1 + textEditorOptions.IndentSize) / textEditorOptions.IndentSize;
 
443
                                        col = 1 + nextTabStop * textEditorOptions.IndentSize;
 
444
                                        currentIndent.Append('\t');
 
445
                                        offset++;
 
446
                                        return;
 
447
                                case '\r':
 
448
 
 
449
                                        if (readPreprocessorExpression) {
 
450
                                                if (!eval(wordBuf.ToString()))
 
451
                                                        inside |= Inside.PreProcessorComment;
 
452
                                        }
 
453
 
 
454
                                        inside &= ~(Inside.Comment | Inside.String | Inside.CharLiteral | Inside.PreProcessor);
 
455
                                        CheckKeyword(wordBuf.ToString());
 
456
                                        wordBuf.Length = 0;
 
457
                                        indent.Push(indentDelta);
 
458
                                        indentDelta = new Indent(textEditorOptions);
 
459
 
 
460
 
 
461
                                        if (addContinuation) {
 
462
                                                indent.Push(IndentType.Continuation);
 
463
                                        }
 
464
                                        thisLineindent = indent.Clone();
 
465
                                        addContinuation = false;
 
466
                                        IsLineStart = true;
 
467
                                        readPreprocessorExpression = false;
 
468
                                        col = 1;
 
469
                                        line++;
 
470
                                        currentIndent.Length = 0;
 
471
                                        break;
 
472
                                case '\n':
 
473
                                        if (pc == '\r')
 
474
                                                break;
 
475
                                        goto case '\r';
 
476
                                case '"':
 
477
                                        if (IsInComment || IsInPreProcessorComment)
 
478
                                                break;
 
479
                                        if (inside.HasFlag(Inside.StringLiteral)) {
 
480
                                                if (pc != '\\')
 
481
                                                        inside &= ~Inside.StringLiteral;
 
482
                                                break;
 
483
                                        }
 
484
 
 
485
                                        if (pc == '@') {
 
486
                                                inside |= Inside.VerbatimString;
 
487
                                        } else {
 
488
                                                inside |= Inside.StringLiteral;
 
489
                                        }
 
490
                                        break;
 
491
                                case '<':
 
492
                                case '[':
 
493
                                case '(':
 
494
                                        if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
 
495
                                                break;
 
496
                                        parenStack.Push(new TextLocation(line, col));
 
497
                                        popNextParenBlock = true;
 
498
                                        indent.Push(IndentType.Block);
 
499
                                        break;
 
500
                                case '>':
 
501
                                case ']':
 
502
                                case ')':
 
503
                                        if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
 
504
                                                break;
 
505
                                        if (popNextParenBlock && parenStack.Count > 0)
 
506
                                                parenStack.Pop();
 
507
                                        if (indent.Count > 0)
 
508
                                                indent.Pop();
 
509
                                        indent.ExtraSpaces = 0;
 
510
                                        break;
 
511
                                case ',':
 
512
                                        if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
 
513
                                                break;
 
514
                                        if (parenStack.Count > 0 && parenStack.Peek().Line == line) {
 
515
                                                if (indent.Count > 0)
 
516
                                                        indent.Pop();
 
517
                                                popNextParenBlock = false;
 
518
                                                indent.ExtraSpaces = parenStack.Peek().Column - 1 - thisLineindent.CurIndent;
 
519
                                        }
 
520
                                        break;
 
521
                                case '{':
 
522
                                        if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
 
523
                                                break;
 
524
                                        currentBody = nextBody;
 
525
                                        if (indent.Count > 0 && indent.Peek() == IndentType.Continuation)
 
526
                                                indent.Pop();
 
527
                                        addContinuation = false;
 
528
                                        AddIndentation(currentBody);
 
529
                                        break;
 
530
                                case '}':
 
531
                                        if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
 
532
                                                break;
 
533
                                        if (indentDelta.CurIndent > 0) {
 
534
                                                indentDelta.Pop();
 
535
                                                if (indentDelta.Count > 0 && indentDelta.Peek() == IndentType.Continuation)
 
536
                                                        indentDelta.Pop();
 
537
                                        } else {
 
538
                                                if (thisLineindent.Count > 0)
 
539
                                                        thisLineindent.Pop();
 
540
                                                if (indent.Count > 0)
 
541
                                                        indent.Pop();
 
542
                                        }
 
543
                                        break;
 
544
                                case ';':
 
545
                                        if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
 
546
                                                break;
 
547
                                        if (indent.Count > 0 && indent.Peek() == IndentType.Continuation)
 
548
                                                indent.Pop();
 
549
                                        break;
 
550
                                case '\'':
 
551
                                        if (IsInComment || inside.HasFlag(Inside.StringLiteral) || IsInPreProcessorComment)
 
552
                                                break;
 
553
                                        if (inside.HasFlag(Inside.CharLiteral)) {
 
554
                                                if (pc != '\\')
 
555
                                                        inside &= ~Inside.CharLiteral;
 
556
                                        } else {
 
557
                                                inside &= Inside.CharLiteral;
 
558
                                        }
 
559
                                        break;
 
560
                        }
 
561
 
 
562
                        if (!IsInComment && !IsInStringOrChar && !readPreprocessorExpression) {
 
563
                                if ((wordBuf.Length == 0 ? char.IsLetter(ch) : char.IsLetterOrDigit(ch)) || ch == '_') {
 
564
                                        wordBuf.Append(ch);
 
565
                                } else {
 
566
                                        if (inside.HasFlag(Inside.PreProcessor)) {
 
567
                                                if (wordBuf.ToString() == "endif") {
 
568
                                                        inside &= ~Inside.PreProcessorComment;
 
569
                                                } else if (wordBuf.ToString() == "if") {
 
570
                                                        readPreprocessorExpression = true;
 
571
                                                } else if (wordBuf.ToString() == "elif") {
 
572
                                                        inside &= ~Inside.PreProcessorComment;
 
573
                                                        readPreprocessorExpression = true;
 
574
                                                }
 
575
                                        } else {
 
576
                                                CheckKeyword(wordBuf.ToString());
 
577
                                        }
 
578
                                        wordBuf.Length = 0;
 
579
                                }
 
580
                        }
 
581
                        if (addContinuation) {
 
582
                                indent.Push(IndentType.Continuation);
 
583
                                addContinuation = false;
 
584
                        }
 
585
                        IsLineStart &= ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
 
586
                        pc = ch;
 
587
                        if (ch != '\n' && ch != '\r')
 
588
                                col++;
 
589
                        offset++;
 
590
                }
 
591
 
 
592
                void AddIndentation(BraceStyle braceStyle)
 
593
                {
 
594
                        switch (braceStyle) {
 
595
                                case BraceStyle.DoNotChange:
 
596
                                case BraceStyle.EndOfLine:
 
597
                                case BraceStyle.EndOfLineWithoutSpace:
 
598
                                case BraceStyle.NextLine:
 
599
                                case BraceStyle.NextLineShifted:
 
600
                                case BraceStyle.BannerStyle:
 
601
                                        indentDelta.Push(IndentType.Block);
 
602
                                        break;
 
603
 
 
604
                                case BraceStyle.NextLineShifted2:
 
605
                                        indentDelta.Push(IndentType.DoubleBlock);
 
606
                                        break;
 
607
                        }
 
608
                }
 
609
 
 
610
                void AddIndentation(Body body)
 
611
                {
 
612
                        switch (body) {
 
613
                                case Body.None:
 
614
                                        indentDelta.Push(IndentType.Block);
 
615
                                        break;
 
616
                                case Body.Namespace:
 
617
                                        AddIndentation(options.NamespaceBraceStyle);
 
618
                                        break;
 
619
                                case Body.Class:
 
620
                                        AddIndentation(options.ClassBraceStyle);
 
621
                                        break;
 
622
                                case Body.Struct:
 
623
                                        AddIndentation(options.StructBraceStyle);
 
624
                                        break;
 
625
                                case Body.Interface:
 
626
                                        AddIndentation(options.InterfaceBraceStyle);
 
627
                                        break;
 
628
                                case Body.Enum:
 
629
                                        AddIndentation(options.EnumBraceStyle);
 
630
                                        break;
 
631
                                case Body.Switch:
 
632
                                        if (options.IndentSwitchBody)
 
633
                                                indentDelta.Push(IndentType.Empty);
 
634
                                        break;
 
635
                                default:
 
636
                                        throw new ArgumentOutOfRangeException();
 
637
                        }
 
638
                }
 
639
 
 
640
                enum Body
 
641
                {
 
642
                        None,
 
643
                        Namespace,
 
644
                        Class,
 
645
                        Struct,
 
646
                        Interface,
 
647
                        Enum,
 
648
                        Switch
 
649
                }
 
650
 
 
651
                void CheckKeyword(string keyword)
 
652
                {
 
653
                        switch (currentBody) {
 
654
                                case Body.None:
 
655
                                        if (keyword == "namespace") {
 
656
                                                nextBody = Body.Namespace;
 
657
                                                return;
 
658
                                        }
 
659
                                        goto case Body.Namespace;
 
660
                                case Body.Namespace:
 
661
                                        if (keyword == "class") {
 
662
                                                nextBody = Body.Class;
 
663
                                                return;
 
664
                                        }
 
665
                                        if (keyword == "enum") {
 
666
                                                nextBody = Body.Enum;
 
667
                                                return;
 
668
                                        }
 
669
                                        if (keyword == "struct") {
 
670
                                                nextBody = Body.Struct;
 
671
                                                return;
 
672
                                        }
 
673
                                        if (keyword == "interface") {
 
674
                                                nextBody = Body.Interface;
 
675
                                                return;
 
676
                                        }
 
677
                                        break;
 
678
                                case Body.Class:
 
679
                                case Body.Enum:
 
680
                                case Body.Struct:
 
681
                                case Body.Interface:
 
682
                                        if (keyword == "switch")
 
683
                                                nextBody = Body.Switch;
 
684
                                        if (keyword == "do" || keyword == "if" || keyword == "for" || keyword == "foreach" || keyword == "while") {
 
685
                                                addContinuation = true;
 
686
                                        }
 
687
                                        break;
 
688
                        }
 
689
                }
 
690
        }
 
691
}
 
692