~ubuntu-branches/ubuntu/natty/monodevelop/natty

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/Syntax/CSharpSyntaxMode.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2010-01-07 19:06:58 UTC
  • mto: (1.6.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 46.
  • Revision ID: james.westby@ubuntu.com-20100107190658-z9z95lgk4kwfes7p
ImportĀ upstreamĀ versionĀ 2.2+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// 
2
 
// SyntaxMode.cs
3
 
//  
4
 
// Author:
5
 
//   Mike KrĆ¼ger <mkrueger@novell.com>
6
 
//
7
 
// Copyright (C) 2009 Novell, Inc (http://www.novell.com)
8
 
// 
9
 
// Permission is hereby granted, free of charge, to any person obtaining
10
 
// a copy of this software and associated documentation files (the
11
 
// "Software"), to deal in the Software without restriction, including
12
 
// without limitation the rights to use, copy, modify, merge, publish,
13
 
// distribute, sublicense, and/or sell copies of the Software, and to
14
 
// permit persons to whom the Software is furnished to do so, subject to
15
 
// the following conditions:
16
 
// 
17
 
// The above copyright notice and this permission notice shall be
18
 
// included in all copies or substantial portions of the Software.
19
 
// 
20
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
 
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
 
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
 
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
 
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
 
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
 
//
28
 
 
29
 
using System;
30
 
using System.Linq;
31
 
using System.Collections.Generic;
32
 
using Mono.TextEditor.Highlighting;
33
 
using Mono.TextEditor;
34
 
using System.Xml;
35
 
using MonoDevelop.Projects;
36
 
using CSharpBinding;
37
 
 
38
 
 
39
 
 
40
 
namespace MonoDevelop.CSharpBinding
41
 
{
42
 
        public class CSharpSyntaxMode : Mono.TextEditor.Highlighting.SyntaxMode
43
 
        {
44
 
                public CSharpSyntaxMode ()
45
 
                {
46
 
                        ResourceXmlProvider provider = new ResourceXmlProvider (typeof(IXmlProvider).Assembly, "CSharpSyntaxMode.xml");
47
 
                        using (XmlReader reader = provider.Open ()) {
48
 
                                SyntaxMode baseMode = SyntaxMode.Read (reader);
49
 
                                this.rules = new List<Rule> (baseMode.Rules);
50
 
                                this.keywords = new List<Keywords> (baseMode.Keywords);
51
 
                                this.spans = baseMode.Spans;
52
 
                                this.matches = baseMode.Matches;
53
 
                                this.prevMarker = baseMode.PrevMarker;
54
 
                                this.SemanticRules = new List<SemanticRule> (baseMode.SemanticRules);
55
 
                                this.table = baseMode.Table;
56
 
                                this.properties = baseMode.Properties;
57
 
                        }
58
 
                        
59
 
                        AddSemanticRule ("Comment", new HighlightUrlSemanticRule ("comment"));
60
 
                        AddSemanticRule ("XmlDocumentation", new HighlightUrlSemanticRule ("comment"));
61
 
                        AddSemanticRule ("String", new HighlightUrlSemanticRule ("string"));
62
 
                        AddSemanticRule (new HighlightCSharpSemanticRule ());
63
 
                }
64
 
                
65
 
                public override SpanParser CreateSpanParser (Document doc, SyntaxMode mode, LineSegment line, Stack<Span> spanStack)
66
 
                {
67
 
                        return new CSharpSpanParser (doc, mode, line, spanStack);
68
 
                }
69
 
                
70
 
                class IfBlockSpan : Span
71
 
                {
72
 
                        public bool IsValid {
73
 
                                get;
74
 
                                private set;
75
 
                        }
76
 
                        
77
 
                        public IfBlockSpan (bool isValid)
78
 
                        {
79
 
                                this.IsValid = isValid;
80
 
                                TagColor = "text.preprocessor";
81
 
                                if (!isValid) {
82
 
                                        Color = "comment.block";
83
 
                                        Rule = "String";
84
 
                                } else {
85
 
                                        Color = "text";
86
 
                                        Rule = "<root>";
87
 
                                }
88
 
                                StopAtEol = false;
89
 
                        }
90
 
                        public override string ToString ()
91
 
                        {
92
 
                                return string.Format("[IfBlockSpan: IsValid={0}, Color={1}, Rule={2}]", IsValid, Color, Rule);
93
 
                        }
94
 
                }
95
 
                
96
 
                class ElseIfBlockSpan : Span
97
 
                {
98
 
                        public bool IsValid {
99
 
                                get;
100
 
                                private set;
101
 
                        }
102
 
                        
103
 
                        public ElseIfBlockSpan (bool isValid)
104
 
                        {
105
 
                                this.IsValid = isValid;
106
 
                                TagColor = "text.preprocessor";
107
 
                                if (!isValid) {
108
 
                                        Color = "comment.block";
109
 
                                        Rule = "String";
110
 
                                } else {
111
 
                                        Color = "text";
112
 
                                        Rule = "<root>";
113
 
                                }
114
 
                                StopAtEol = false;
115
 
                        }
116
 
                        public override string ToString ()
117
 
                        {
118
 
                                return string.Format("[ElseIfBlockSpan: IsValid={0}, Color={1}, Rule={2}]", IsValid, Color, Rule);
119
 
                        }
120
 
                }
121
 
                
122
 
                class ElseBlockSpan : Span
123
 
                {
124
 
                        public bool IsValid {
125
 
                                get;
126
 
                                private set;
127
 
                        }
128
 
                        
129
 
                        public ElseBlockSpan (bool isValid)
130
 
                        {
131
 
                                this.IsValid = isValid;
132
 
                                TagColor = "text.preprocessor";
133
 
                                if (!isValid) {
134
 
                                        Color = "comment.block";
135
 
                                        Rule = "String";
136
 
                                } else {
137
 
                                        Color = "text";
138
 
                                        Rule = "<root>";
139
 
                                }
140
 
                                StopAtEol = false;
141
 
                        }
142
 
                        
143
 
                        public override string ToString ()
144
 
                        {
145
 
                                return string.Format("[ElseBlockSpan: IsValid={0}, Color={1}, Rule={2}]", IsValid, Color, Rule);
146
 
                        }
147
 
                }
148
 
                
149
 
                protected class CSharpSpanParser : SpanParser
150
 
                {
151
 
                        class ConditinalExpressionEvaluator : ICSharpCode.NRefactory.Visitors.AbstractAstVisitor
152
 
                        {
153
 
                                HashSet<string> symbols = new HashSet<string> ();
154
 
                                public ConditinalExpressionEvaluator ()
155
 
                                {
156
 
                                        Project project = MonoDevelop.Ide.Gui.IdeApp.ProjectOperations.CurrentSelectedProject;
157
 
                                        if (project != null) {
158
 
                                                CSharpCompilerParameters cparams = ((DotNetProjectConfiguration)project.GetActiveConfiguration (project.ParentSolution.DefaultConfigurationId)).CompilationParameters as CSharpCompilerParameters;
159
 
                                                if (cparams != null) {
160
 
                                                        string[] syms = cparams.DefineSymbols.Split (';', ',');
161
 
                                                        foreach (string s in syms) {
162
 
                                                                string ss = s.Trim ();
163
 
                                                                if (ss.Length > 0 && !symbols.Contains (ss))
164
 
                                                                        symbols.Add (ss);
165
 
                                                        }
166
 
                                                }
167
 
                                        }
168
 
                                }
169
 
                                
170
 
                                public override object VisitIdentifierExpression (ICSharpCode.NRefactory.Ast.IdentifierExpression identifierExpression, object data)
171
 
                                {
172
 
                                        return symbols.Contains (identifierExpression.Identifier);
173
 
                                }
174
 
                                
175
 
                                public override object VisitUnaryOperatorExpression (ICSharpCode.NRefactory.Ast.UnaryOperatorExpression unaryOperatorExpression, object data)
176
 
                                {
177
 
                                        bool result = (bool)(unaryOperatorExpression.Expression.AcceptVisitor (this, data) ?? (object)false);
178
 
                                        if (unaryOperatorExpression.Op == ICSharpCode.NRefactory.Ast.UnaryOperatorType.Not)
179
 
                                                return !result;
180
 
                                        return result;
181
 
                                }
182
 
                                
183
 
                                public override object VisitPrimitiveExpression (ICSharpCode.NRefactory.Ast.PrimitiveExpression primitiveExpression, object data)
184
 
                                {
185
 
                                        return (bool)primitiveExpression.Value;
186
 
                                }
187
 
 
188
 
                                public override object VisitBinaryOperatorExpression (ICSharpCode.NRefactory.Ast.BinaryOperatorExpression binaryOperatorExpression, object data)
189
 
                                {
190
 
                                        bool left  = (bool)(binaryOperatorExpression.Left.AcceptVisitor (this, data) ?? (object)false);
191
 
                                        bool right = (bool)(binaryOperatorExpression.Right.AcceptVisitor (this, data) ?? (object)false);
192
 
                                        
193
 
                                        switch (binaryOperatorExpression.Op) {
194
 
                                        case ICSharpCode.NRefactory.Ast.BinaryOperatorType.InEquality:
195
 
                                                return left != right;
196
 
                                        case ICSharpCode.NRefactory.Ast.BinaryOperatorType.Equality:
197
 
                                                return left == right;
198
 
                                        case ICSharpCode.NRefactory.Ast.BinaryOperatorType.LogicalOr:
199
 
                                                return left || right;
200
 
                                        case ICSharpCode.NRefactory.Ast.BinaryOperatorType.LogicalAnd:
201
 
                                                return left && right;
202
 
                                        }
203
 
                                        
204
 
                                        Console.WriteLine ("Unknown operator:" + binaryOperatorExpression.Op);
205
 
                                        return left;
206
 
                                }
207
 
                        }
208
 
                        
209
 
                        protected override void ScanSpan (ref int i)
210
 
                        {
211
 
                                if (i + 5 < doc.Length && doc.GetTextAt (i, 5) == "#else" && spanStack.Any (span => span is IfBlockSpan)) {
212
 
                                        bool previousResult = false;
213
 
                                        foreach (Span span in spanStack.ToArray ().Reverse ()) {
214
 
                                                if (span is IfBlockSpan) {
215
 
                                                        previousResult = ((IfBlockSpan)span).IsValid;
216
 
                                                }
217
 
                                                if (span is ElseIfBlockSpan) {
218
 
                                                        previousResult |= ((ElseIfBlockSpan)span).IsValid;
219
 
                                                }
220
 
                                        }
221
 
                                        
222
 
                                        LineSegment line = doc.GetLineByOffset (i);
223
 
                                        int length = line.Offset + line.EditableLength - i;
224
 
                                        while (spanStack.Count > 0 && !(CurSpan is IfBlockSpan)) {
225
 
                                                spanStack.Pop ();
226
 
                                        }
227
 
//                                      IfBlockSpan ifBlock = (IfBlockSpan)CurSpan;
228
 
                                        
229
 
                                        ElseBlockSpan elseBlockSpan = new ElseBlockSpan (!previousResult);
230
 
                                        OnFoundSpanBegin (elseBlockSpan, i, 0);
231
 
                                        
232
 
                                        spanStack.Push (elseBlockSpan);
233
 
                                        ruleStack.Push (GetRule (elseBlockSpan));
234
 
                                        
235
 
                                        // put pre processor eol span on stack, so that '#else' gets the correct highlight
236
 
                                        OnFoundSpanBegin (preprocessorSpan, i, 1);
237
 
                                        spanStack.Push (preprocessorSpan);
238
 
                                        ruleStack.Push (preprocessorRule);
239
 
                                        i += length - 1;
240
 
                                        return;
241
 
                                }
242
 
                                if (CurRule.Name == "text.preprocessor" && i >= 3 && doc.GetTextAt (i - 3, 3) == "#if") {
243
 
                                        LineSegment line = doc.GetLineByOffset (i);
244
 
                                        int length = line.Offset + line.EditableLength - i;
245
 
                                        string parameter = doc.GetTextAt (i, length);
246
 
                                        ICSharpCode.NRefactory.Parser.CSharp.Lexer lexer = new ICSharpCode.NRefactory.Parser.CSharp.Lexer (new System.IO.StringReader (parameter));
247
 
                                        ICSharpCode.NRefactory.Ast.Expression expr = lexer.PPExpression ();
248
 
                                        bool result = false;
249
 
                                        if (expr != null && !expr.IsNull) {
250
 
                                                object o = expr.AcceptVisitor (new ConditinalExpressionEvaluator (), null);
251
 
                                                if (o is bool)
252
 
                                                        result = (bool)o;
253
 
                                        }
254
 
                                        IfBlockSpan ifBlockSpan = new IfBlockSpan (result);
255
 
                                        OnFoundSpanBegin (ifBlockSpan, i, length);
256
 
                                        i += length - 1;
257
 
                                        spanStack.Push (ifBlockSpan);
258
 
                                        ruleStack.Push (GetRule (ifBlockSpan));
259
 
                                        return;
260
 
                                }
261
 
                                if (i + 5 < doc.Length && doc.GetTextAt (i, 5) == "#elif" && spanStack.Any (span => span is IfBlockSpan)) {
262
 
                                        LineSegment line = doc.GetLineByOffset (i);
263
 
                                        int length = line.Offset + line.EditableLength - i;
264
 
                                        string parameter = doc.GetTextAt (i + 5, length - 5);
265
 
                                        
266
 
                                        ICSharpCode.NRefactory.Parser.CSharp.Lexer lexer = new ICSharpCode.NRefactory.Parser.CSharp.Lexer (new System.IO.StringReader (parameter));
267
 
                                        ICSharpCode.NRefactory.Ast.Expression expr = lexer.PPExpression ();
268
 
                                
269
 
                                        bool result = !expr.IsNull ? (bool)expr.AcceptVisitor (new ConditinalExpressionEvaluator (), null) : false;
270
 
                                        
271
 
                                        if (result) {
272
 
                                                bool previousResult = false;
273
 
                                                foreach (Span span in spanStack.ToArray ().Reverse ()) {
274
 
                                                        if (span is IfBlockSpan) {
275
 
                                                                previousResult = ((IfBlockSpan)span).IsValid;
276
 
                                                        }
277
 
                                                        if (span is ElseIfBlockSpan) {
278
 
                                                                previousResult |= ((ElseIfBlockSpan)span).IsValid;
279
 
                                                        }
280
 
                                                }
281
 
                                                
282
 
                                                result = !previousResult;
283
 
                                        }
284
 
                                        
285
 
                                        ElseIfBlockSpan elseIfBlockSpan = new ElseIfBlockSpan (result);
286
 
                                        OnFoundSpanBegin (elseIfBlockSpan, i, 0);
287
 
                                        
288
 
                                        spanStack.Push (elseIfBlockSpan);
289
 
                                        ruleStack.Push (GetRule (elseIfBlockSpan));
290
 
                                        
291
 
                                        // put pre processor eol span on stack, so that '#elif' gets the correct highlight
292
 
                                        OnFoundSpanBegin (preprocessorSpan, i, 1);
293
 
                                        spanStack.Push (preprocessorSpan);
294
 
                                        ruleStack.Push (preprocessorRule);
295
 
                                        //i += length - 1;
296
 
                                        return;
297
 
                                }
298
 
                                base.ScanSpan (ref i);
299
 
                        }
300
 
                        
301
 
                        protected override bool ScanSpanEnd (Mono.TextEditor.Highlighting.Span cur, int i)
302
 
                        {
303
 
                                if (cur is IfBlockSpan || cur is ElseIfBlockSpan || cur is ElseBlockSpan) {
304
 
                                        bool end = i + 6 < doc.Length && doc.GetTextAt (i, 6) == "#endif";
305
 
                                        if (end) {
306
 
                                                OnFoundSpanEnd (cur, i, 0); // put empty end tag in
307
 
                                                while (!(spanStack.Peek () is IfBlockSpan)) {
308
 
                                                        spanStack.Pop ();
309
 
                                                        if (ruleStack.Count > 1) // rulStack[1] is always syntax mode
310
 
                                                                ruleStack.Pop ();
311
 
                                                }
312
 
                                                spanStack.Pop ();
313
 
                                                if (ruleStack.Count > 1) // rulStack[1] is always syntax mode
314
 
                                                        ruleStack.Pop ();
315
 
                                                // put pre processor eol span on stack, so that '#endif' gets the correct highlight
316
 
                                                foreach (Span span in mode.Spans) {
317
 
                                                        if (span.Rule == "text.preprocessor") {
318
 
                                                                OnFoundSpanBegin (span, i, 1);
319
 
                                                                spanStack.Push (span);
320
 
                                                                ruleStack.Push (GetRule (span));
321
 
                                                                break;
322
 
                                                        }
323
 
                                                }
324
 
                                        }
325
 
                                        return end;
326
 
                                }
327
 
                                return base.ScanSpanEnd (cur, i);
328
 
                        }
329
 
                        
330
 
                        Span preprocessorSpan;
331
 
                        Rule preprocessorRule;
332
 
                        
333
 
                        public CSharpSpanParser (Document doc, SyntaxMode mode, LineSegment line, Stack<Span> spanStack) : base (doc, mode, line, spanStack)
334
 
                        {
335
 
                                foreach (Span span in mode.Spans) {
336
 
                                        if (span.Rule == "text.preprocessor") {
337
 
                                                preprocessorSpan = span;
338
 
                                                preprocessorRule = GetRule (span);
339
 
                                        }
340
 
                                }
341
 
                        }
342
 
                }
343
 
        }
344
 
}
345
 
 
 
 
b'\\ No newline at end of file'