Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/OutputVisitor/InsertRequiredSpacesDecorator.cs @ 11700

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

#2077: created branch and added first version

File size: 6.1 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Collections.Generic;
21using System.Diagnostics;
22using System.Globalization;
23using System.IO;
24using System.Linq;
25using System.Text;
26using System.Threading.Tasks;
27using ICSharpCode.NRefactory.PatternMatching;
28using ICSharpCode.NRefactory.TypeSystem;
29using ICSharpCode.NRefactory.CSharp;
30
31namespace ICSharpCode.NRefactory.CSharp
32{
33  class InsertRequiredSpacesDecorator : DecoratingTokenWriter
34  {
35    /// <summary>
36    /// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written.
37    /// </summary>
38    LastWritten lastWritten;
39   
40    enum LastWritten
41    {
42      Whitespace,
43      Other,
44      KeywordOrIdentifier,
45      Plus,
46      Minus,
47      Ampersand,
48      QuestionMark,
49      Division
50    }
51   
52    public InsertRequiredSpacesDecorator(TokenWriter writer)
53      : base(writer)
54    {
55    }
56   
57    public override void WriteIdentifier(Identifier identifier)
58    {
59      if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) {
60        if (lastWritten == LastWritten.KeywordOrIdentifier) {
61          // this space is not strictly required, so we call Space()
62          Space();
63        }
64      } else if (lastWritten == LastWritten.KeywordOrIdentifier) {
65        // this space is strictly required, so we directly call the formatter
66        base.Space();
67      }
68      base.WriteIdentifier(identifier);
69      lastWritten = LastWritten.KeywordOrIdentifier;
70    }
71   
72    public override void WriteKeyword(Role role, string keyword)
73    {
74      if (lastWritten == LastWritten.KeywordOrIdentifier) {
75        Space();
76      }
77      base.WriteKeyword(role, keyword);
78      lastWritten = LastWritten.KeywordOrIdentifier;
79    }
80   
81    public override void WriteToken(Role role, string token)
82    {
83      // Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token.
84      // Note that we don't need to handle tokens like = because there's no valid
85      // C# program that contains the single token twice in a row.
86      // (for +, - and &, this can happen with unary operators;
87      // for ?, this can happen in "a is int? ? b : c" or "a as int? ?? 0";
88      // and for /, this can happen with "1/ *ptr" or "1/ //comment".)
89      if (lastWritten == LastWritten.Plus && token[0] == '+' ||
90          lastWritten == LastWritten.Minus && token[0] == '-' ||
91          lastWritten == LastWritten.Ampersand && token[0] == '&' ||
92          lastWritten == LastWritten.QuestionMark && token[0] == '?' ||
93          lastWritten == LastWritten.Division && token[0] == '*') {
94        base.Space();
95      }
96      base.WriteToken(role, token);
97      if (token == "+") {
98        lastWritten = LastWritten.Plus;
99      } else if (token == "-") {
100        lastWritten = LastWritten.Minus;
101      } else if (token == "&") {
102        lastWritten = LastWritten.Ampersand;
103      } else if (token == "?") {
104        lastWritten = LastWritten.QuestionMark;
105      } else if (token == "/") {
106        lastWritten = LastWritten.Division;
107      } else {
108        lastWritten = LastWritten.Other;
109      }
110    }
111   
112    public override void Space()
113    {
114      base.Space();
115      lastWritten = LastWritten.Whitespace;
116    }
117   
118    public override void NewLine()
119    {
120      base.NewLine();
121      lastWritten = LastWritten.Whitespace;
122    }
123   
124    public override void WriteComment(CommentType commentType, string content)
125    {
126      if (lastWritten == LastWritten.Division) {
127        // When there's a comment starting after a division operator
128        // "1.0 / /*comment*/a", then we need to insert a space in front of the comment.
129        base.Space();
130      }
131      base.WriteComment(commentType, content);
132      lastWritten = LastWritten.Whitespace;
133    }
134   
135    public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument)
136    {
137      base.WritePreProcessorDirective(type, argument);
138      lastWritten = LastWritten.Whitespace;
139    }
140   
141    public override void WritePrimitiveValue(object value, string literalValue = null)
142    {
143      base.WritePrimitiveValue(value, literalValue);
144      if (value == null || value is bool)
145        return;
146      if (value is string) {
147        lastWritten = LastWritten.Other;
148      } else if (value is char) {
149        lastWritten = LastWritten.Other;
150      } else if (value is decimal) {
151        lastWritten = LastWritten.Other;
152      } else if (value is float) {
153        float f = (float)value;
154        if (float.IsInfinity(f) || float.IsNaN(f)) return;
155        lastWritten = LastWritten.Other;
156      } else if (value is double) {
157        double f = (double)value;
158        if (double.IsInfinity(f) || double.IsNaN(f)) return;
159        // needs space if identifier follows number;
160        // this avoids mistaking the following identifier as type suffix
161        lastWritten = LastWritten.KeywordOrIdentifier;
162      } else if (value is IFormattable) {
163        // needs space if identifier follows number;
164        // this avoids mistaking the following identifier as type suffix
165        lastWritten = LastWritten.KeywordOrIdentifier;
166      } else {
167        lastWritten = LastWritten.Other;
168      }
169    }
170   
171    public override void WritePrimitiveType(string type)
172    {
173      if (lastWritten == LastWritten.KeywordOrIdentifier) {
174        Space();
175      }
176      base.WritePrimitiveType(type);
177      if (type == "new") {
178        lastWritten = LastWritten.Other;
179      } else {
180        lastWritten = LastWritten.KeywordOrIdentifier;
181      }
182    }
183  }
184}
Note: See TracBrowser for help on using the repository browser.