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

« back to all changes in this revision

Viewing changes to src/addins/AspNet/MonoDevelop.AspNet/MonoDevelop.AspNet.Parser.Dom/RootNode.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
 
// RootNode.cs: Root node in ASP.NET document tree; can populate itself from 
3
 
//     a file stream.
4
 
//
5
 
// Authors:
6
 
//   Michael Hutchinson <m.j.hutchinson@gmail.com>
7
 
//
8
 
// Copyright (C) 2006 Michael Hutchinson
9
 
//
10
 
//
11
 
// This source code is licenced under The MIT License:
12
 
//
13
 
// Permission is hereby granted, free of charge, to any person obtaining
14
 
// a copy of this software and associated documentation files (the
15
 
// "Software"), to deal in the Software without restriction, including
16
 
// without limitation the rights to use, copy, modify, merge, publish,
17
 
// distribute, sublicense, and/or sell copies of the Software, and to
18
 
// permit persons to whom the Software is furnished to do so, subject to
19
 
// the following conditions:
20
 
// 
21
 
// The above copyright notice and this permission notice shall be
22
 
// included in all copies or substantial portions of the Software.
23
 
// 
24
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
 
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
 
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
 
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
 
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
 
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
 
//
32
 
 
33
 
using System;
34
 
using System.IO;
35
 
using System.Collections.Generic;
36
 
 
37
 
using MonoDevelop.AspNet.Parser;
38
 
using MonoDevelop.AspNet.Parser.Internal;
39
 
 
40
 
namespace MonoDevelop.AspNet.Parser.Dom
41
 
{
42
 
        public class RootNode : ParentNode
43
 
        {
44
 
                string fileName;
45
 
                List<ParseException> errors = new List<ParseException> ();
46
 
                                
47
 
                public RootNode () : base (null)
48
 
                {
49
 
                }
50
 
                
51
 
                internal ICollection<ParseException> ParseErrors {
52
 
                        get { return errors; }
53
 
                }
54
 
                
55
 
                public override void AcceptVisit (Visitor visitor)
56
 
                {
57
 
                        visitor.Visit (this);
58
 
                        foreach (Node n in children) {
59
 
                                if (visitor.QuickExit)
60
 
                                        break;
61
 
                                n.AcceptVisit (visitor);
62
 
                        }
63
 
                        visitor.Leave (this);
64
 
                }
65
 
                
66
 
                public override string ToString ()
67
 
                {
68
 
                        return string.Format ("[RootNode Filename='{0}']", fileName);
69
 
                }
70
 
                
71
 
                public override int ContainsPosition (int line, int col)
72
 
                {
73
 
                        return 0;
74
 
                }
75
 
                
76
 
                #region Parsing code
77
 
                
78
 
                Node currentNode;
79
 
                static string[] implicitSelfClosing = { "hr", "br", "img" };
80
 
                static string[] implicitCloseOnBlock = { "p" };
81
 
                static string[] blockLevel = { "p", "div", "hr", "img", "blockquote", "html", "body", "form" };
82
 
                
83
 
                public void Parse (string fileName, TextReader textStream)
84
 
                {
85
 
                        var parser = new AspParser (fileName, textStream);
86
 
                        this.fileName = fileName;
87
 
                        
88
 
                        parser.Error      += ParseError;
89
 
                        parser.TagParsed  += TagParsed;
90
 
                        parser.TextParsed += TextParsed;
91
 
                        
92
 
                        currentNode = this;
93
 
                        
94
 
                        parser.Parse ();
95
 
                }
96
 
                
97
 
                void TagParsed (ILocation location, TagType tagtype, string tagId, TagAttributes attributes)
98
 
                {
99
 
                        switch (tagtype)
100
 
                        {
101
 
                        case TagType.Close:
102
 
                                TagNode tn = currentNode as TagNode;
103
 
                                if (tn == null) {
104
 
                                        errors.Add (new ParseException (location, "Closing tag '" + tagId +"' does not match an opening tag."));
105
 
                                } else {
106
 
                                        if (tn.TagName == tagId) {
107
 
                                                tn.EndLocation = location;
108
 
                                                currentNode = currentNode.Parent;
109
 
                                                tn.Close ();
110
 
                                        } else {
111
 
                                                errors.Add (new ParseException (location, "Closing tag '" + tagId +"' does not match opening tag '" + tn.TagName + "'."));
112
 
                                                currentNode = currentNode.Parent;
113
 
                                                TagParsed (location, TagType.Close, tagId, null);
114
 
                                        }
115
 
                                }
116
 
                                break;
117
 
                                
118
 
                        case TagType.CodeRender:
119
 
                        case TagType.CodeRenderExpression:
120
 
                        case TagType.DataBinding:
121
 
                                try {
122
 
                                        AddtoCurrent (location, new ExpressionNode (location, tagId, tagtype == TagType.CodeRenderExpression));
123
 
                                } catch (ParseException ex) {
124
 
                                        errors.Add (ex);
125
 
                                }
126
 
                                break;
127
 
                                
128
 
                        case TagType.Directive:
129
 
                                try {
130
 
                                        AddtoCurrent (location, new DirectiveNode (location, tagId, attributes));
131
 
                                } catch (ParseException ex) {
132
 
                                        errors.Add (ex);
133
 
                                }       
134
 
                                break;
135
 
                                
136
 
                        case TagType.Include:
137
 
                                throw new NotImplementedException ("Server-side includes have not yet been implemented: " + location.PlainText);
138
 
                                
139
 
                        case TagType.ServerComment:
140
 
                                //FIXME: the parser doesn't actually return these
141
 
                                throw new NotImplementedException ("Server comments have not yet been implemented: " + location.PlainText);
142
 
                                
143
 
                        case TagType.SelfClosing:
144
 
                                try {
145
 
                                        tn = new TagNode (location, tagId, attributes);
146
 
                                        AddtoCurrent (location, tn);
147
 
                                        tn.Close ();
148
 
                                } catch (ParseException ex) {
149
 
                                        errors.Add (ex);
150
 
                                }
151
 
                                break;
152
 
                                
153
 
                        case TagType.Tag:
154
 
                                try {
155
 
                                        //HACK: implicit close on block level in HTML4
156
 
                                        TagNode prevTag = currentNode as TagNode;
157
 
                                        if (prevTag != null) {
158
 
                                                if (Array.IndexOf (implicitCloseOnBlock, prevTag.TagName.ToLowerInvariant ()) > -1
159
 
                                                    && Array.IndexOf (blockLevel, tagId.ToLowerInvariant ()) > -1) {
160
 
                                                        errors.Add (new ParseException (location, "Unclosed " + prevTag.TagName + " tag. Assuming implicitly closed by block level tag."));
161
 
                                                        prevTag.Close ();
162
 
                                                        currentNode = currentNode.Parent;
163
 
                                                }
164
 
                                        }
165
 
                                        
166
 
                                        //create and add the new tag
167
 
                                        TagNode child = new TagNode (location, tagId, attributes);
168
 
                                        AddtoCurrent (location, child);
169
 
                                        
170
 
                                        //HACK: implicitly closing tags in HTML4
171
 
                                        if (Array.IndexOf (implicitSelfClosing, tagId.ToLowerInvariant ()) > -1) {
172
 
                                                errors.Add (new ParseException (location, "Unclosed " + tagId + " tag. Assuming implicitly closed."));
173
 
                                                child.Close ();
174
 
                                        } else {
175
 
                                                currentNode = child;
176
 
                                        }
177
 
                                        
178
 
                                } catch (ParseException ex) {
179
 
                                        errors.Add (ex);
180
 
                                }
181
 
                                break;
182
 
                                
183
 
                        case TagType.Text:
184
 
                                //FIXME: the parser doesn't actually return these
185
 
                                throw new NotImplementedException("Text tagtypes have not yet been implemented: " + location.PlainText);
186
 
                        }
187
 
                }
188
 
                
189
 
                void AddtoCurrent (ILocation location, Node n)
190
 
                {
191
 
                        ParentNode pn = currentNode as ParentNode;
192
 
                        if (pn == null)
193
 
                                throw new ParseException (location, "Nodes of type " + n.GetType () + " must be inside other tags");
194
 
                        pn.AddChild (n);
195
 
                }
196
 
                
197
 
                void TextParsed (ILocation location, string text)
198
 
                {
199
 
                        currentNode.AddText (location, text);
200
 
                }
201
 
                
202
 
                void ParseError (ILocation location, string message)
203
 
                {
204
 
                        errors.Add (new ParseException (location, message));
205
 
                }
206
 
                
207
 
                #endregion
208
 
        }
209
 
}