1
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
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:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
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.
21
using ICSharpCode.NRefactory.Editor;
22
using ICSharpCode.NRefactory.TypeSystem;
23
using NUnit.Framework;
25
namespace ICSharpCode.NRefactory.CSharp.Parser
28
/// Test fixture that parses NRefactory itself,
29
/// ensures that there are no parser crashes while doing so,
30
/// and that the returned positions are consistent.
33
public class ParseSelfTests
40
string path = Path.GetFullPath (Path.Combine ("..", ".."));
41
if (!File.Exists(Path.Combine(path, "NRefactory.sln")))
42
throw new InvalidOperationException("Test cannot find the NRefactory source code in " + path);
43
fileNames = Directory.GetFiles(path, "*.cs", SearchOption.AllDirectories);
47
public void GenerateTypeSystem()
49
IProjectContent pc = new CSharpProjectContent();
50
CSharpParser parser = new CSharpParser();
51
parser.GenerateTypeSystemMode = true;
52
foreach (string fileName in fileNames) {
53
SyntaxTree syntaxTree;
54
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) {
55
syntaxTree = parser.Parse(fs, fileName);
57
var unresolvedFile = syntaxTree.ToTypeSystem();
58
foreach (var td in unresolvedFile.GetAllTypeDefinitions()) {
59
Assert.AreSame(unresolvedFile, td.UnresolvedFile);
60
foreach (var member in td.Members) {
61
Assert.AreSame(unresolvedFile, member.UnresolvedFile);
62
Assert.AreSame(td, member.DeclaringTypeDefinition);
65
pc = pc.AddOrUpdateFiles(unresolvedFile);
69
#region ParseAndCheckPositions
70
string currentFileName;
71
ReadOnlyDocument currentDocument;
73
[Test, Ignore("Positions still are incorrect in several cases")]
74
public void ParseAndCheckPositions()
76
CSharpParser parser = new CSharpParser();
77
foreach (string fileName in fileNames) {
78
this.currentDocument = new ReadOnlyDocument(File.ReadAllText(fileName));
79
SyntaxTree syntaxTree = parser.Parse(currentDocument, fileName);
82
this.currentFileName = fileName;
83
CheckPositionConsistency(syntaxTree);
84
CheckMissingTokens(syntaxTree);
88
void PrintNode (AstNode node)
90
Console.WriteLine ("Parent:" + node.GetType ());
91
Console.WriteLine ("Children:");
92
foreach (var c in node.Children)
93
Console.WriteLine (c.GetType () +" at:"+ c.StartLocation +"-"+ c.EndLocation + " Role: "+ c.Role);
94
Console.WriteLine ("----");
97
void CheckPositionConsistency (AstNode node)
99
string comment = "(" + node.GetType ().Name + " at " + node.StartLocation + " in " + currentFileName + ")";
100
var pred = node.StartLocation <= node.EndLocation;
103
Assert.IsTrue(pred, "StartLocation must be before EndLocation " + comment);
104
var prevNodeEnd = node.StartLocation;
106
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
107
bool assertion = child.StartLocation >= prevNodeEnd;
109
PrintNode (prevNode);
113
Assert.IsTrue(assertion, currentFileName + ": Child " + child.GetType () +" (" + child.StartLocation + ")" +" must start after previous sibling " + prevNode.GetType () + "(" + prevNode.StartLocation + ")");
114
CheckPositionConsistency(child);
115
prevNodeEnd = child.EndLocation;
118
Assert.IsTrue(prevNodeEnd <= node.EndLocation, "Last child must end before parent node ends " + comment);
121
void CheckMissingTokens(AstNode node)
123
if (node is CSharpTokenNode) {
124
Assert.IsNull(node.FirstChild, "Token nodes should not have children");
126
var prevNodeEnd = node.StartLocation;
128
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
129
CheckWhitespace(prevNode, prevNodeEnd, child, child.StartLocation);
130
CheckMissingTokens(child);
132
prevNodeEnd = child.EndLocation;
134
CheckWhitespace(prevNode, prevNodeEnd, node, node.EndLocation);
138
void CheckWhitespace(AstNode startNode, TextLocation whitespaceStart, AstNode endNode, TextLocation whitespaceEnd)
140
if (whitespaceStart == whitespaceEnd || startNode == endNode)
142
int start = currentDocument.GetOffset(whitespaceStart.Line, whitespaceStart.Column);
143
int end = currentDocument.GetOffset(whitespaceEnd.Line, whitespaceEnd.Column);
144
string text = currentDocument.GetText(start, end - start);
145
bool assertion = string.IsNullOrWhiteSpace(text);
147
if (startNode.Parent != endNode.Parent)
148
PrintNode (startNode.Parent);
149
PrintNode (endNode.Parent);
151
Assert.IsTrue(assertion, "Expected whitespace between " + startNode.GetType () +":" + whitespaceStart + " and " + endNode.GetType () + ":" + whitespaceEnd
152
+ ", but got '" + text + "' (in " + currentFileName + " parent:" + startNode.Parent.GetType () +")");