Browse Source
- added PropertyPathTokenizer and PropertyPathParser - added unit tests * fixed an "off by one" error in TaskService * corrected typo in MemberResolveResult documentation git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4600 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
13 changed files with 926 additions and 14 deletions
@ -0,0 +1,267 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Linq; |
||||||
|
|
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace ICSharpCode.XamlBinding.Tests |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class ParserTests |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public void SimplePropertyTest() |
||||||
|
{ |
||||||
|
string text = "Test"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "Test") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SimpleIndexerTest() |
||||||
|
{ |
||||||
|
string text = "[key]"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "key") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TwoPartsTest() |
||||||
|
{ |
||||||
|
string text = "propertyName.propertyName2"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName"), |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName2") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void AttachedPropertyTest() |
||||||
|
{ |
||||||
|
string text = "(ownerType.propertyName)"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "ownerType.propertyName") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SourceTraversalTest() |
||||||
|
{ |
||||||
|
string text = "propertyName/propertyNameX"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.SourceTraversal, "propertyName/propertyNameX") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MultipleIndexerTest() |
||||||
|
{ |
||||||
|
string text = "[index1,index2]"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "index1,index2") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MultipleIndexerTest4() |
||||||
|
{ |
||||||
|
string text = "[ index1 , index2 ]"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "index1,index2") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MultipleIndexerTest2() |
||||||
|
{ |
||||||
|
string text = "propertyName[index1,index2]"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName"), |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "index1,index2") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MultipleIndexerTest3() |
||||||
|
{ |
||||||
|
string text = "propertyName[index1, index2]"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName"), |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "index1,index2") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ComplexTest() |
||||||
|
{ |
||||||
|
string text = "ColorGrid[20,30].SolidColorBrushResult"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "ColorGrid"), |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "20,30"), |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "SolidColorBrushResult") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ComplexTest2() |
||||||
|
{ |
||||||
|
string text = "(TextBlock.Background).(SolidColorBrush.Color)"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "TextBlock.Background"), |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "SolidColorBrush.Color") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ComplexTest3() |
||||||
|
{ |
||||||
|
string text = "(TextBlock.Background).(SolidColorBrush.Color).X"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "TextBlock.Background"), |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "SolidColorBrush.Color"), |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "X") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ComplexTest4() |
||||||
|
{ |
||||||
|
string text = "(TextBlock.Background).(SolidColorBrush.Color).X/Y"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "TextBlock.Background"), |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "SolidColorBrush.Color"), |
||||||
|
new PropertyPathSegment(SegmentKind.SourceTraversal, "X/Y") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ComplexTest5() |
||||||
|
{ |
||||||
|
string text = "propertyName.propertyName2[index].propertyName3"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName"), |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName2"), |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "index"), |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName3") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ControlChar1() |
||||||
|
{ |
||||||
|
string text = "propertyName.propertyName2[index]."; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName"), |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "propertyName2"), |
||||||
|
new PropertyPathSegment(SegmentKind.Indexer, "index"), |
||||||
|
new PropertyPathSegment(SegmentKind.ControlChar, ".") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ControlChar2() |
||||||
|
{ |
||||||
|
string text = "("; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.ControlChar, "(") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ControlChar3() |
||||||
|
{ |
||||||
|
string text = "test["; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.PropertyOrType, "test"), |
||||||
|
new PropertyPathSegment(SegmentKind.ControlChar, "[") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ControlChar4() |
||||||
|
{ |
||||||
|
string text = "(testType."; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "(testType"), |
||||||
|
new PropertyPathSegment(SegmentKind.ControlChar, ".") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ControlChar5() |
||||||
|
{ |
||||||
|
string text = "(testType.prop).(someType."; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "testType.prop"), |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "(someType"), |
||||||
|
new PropertyPathSegment(SegmentKind.ControlChar, ".") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MixedTest1() |
||||||
|
{ |
||||||
|
string text = "(testType.prop).(someType.as"; |
||||||
|
PropertyPathSegment[] result = PropertyPathParser.Parse(text).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "testType.prop"), |
||||||
|
new PropertyPathSegment(SegmentKind.AttachedProperty, "(someType.as") |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
void CompareResults(PropertyPathSegment[] result, params PropertyPathSegment[] expected) |
||||||
|
{ |
||||||
|
Assert.AreEqual(expected, result); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,158 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Linq; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace ICSharpCode.XamlBinding.Tests |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class TokenizerTests |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public void SimpleTest() |
||||||
|
{ |
||||||
|
string input = "Test"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyGroupTest() |
||||||
|
{ |
||||||
|
string input = "Test.Count"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", ".", "Count"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyGroupDotEndTest() |
||||||
|
{ |
||||||
|
string input = "Test."; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", "."); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyIndexerSimpleTest() |
||||||
|
{ |
||||||
|
string input = "Test[1]"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", "[", "1", "]"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyIndexerMultiTest() |
||||||
|
{ |
||||||
|
string input = "Test[1,2]"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", "[", "1", ",", "2", "]"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyAtIndexerTest() |
||||||
|
{ |
||||||
|
string input = "Test["; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", "["); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyAtCommaTest() |
||||||
|
{ |
||||||
|
string input = "Test[1,"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", "[", "1", ","); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyGroupAfterIndexTest() |
||||||
|
{ |
||||||
|
string input = "Test[1].Property"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", "[", "1", "]", ".", "Property"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyDotAfterIndexTest() |
||||||
|
{ |
||||||
|
string input = "Test[1]."; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "Test", "[", "1", "]", "."); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertyIndexAtStartTest() |
||||||
|
{ |
||||||
|
string input = "[1]."; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "[", "1", "]", "."); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PropertySourceTraversalTest() |
||||||
|
{ |
||||||
|
string input = "propertyName/propertyNameX"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "propertyName", "/", "propertyNameX"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WhitespaceTest() |
||||||
|
{ |
||||||
|
string input = " propertyName / propertyNameX [ 1 , 2 ] .property"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "propertyName", "/", "propertyNameX", "[", "1", ",", "2", "]", ".", "property"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void AttachedPropertiesTest() |
||||||
|
{ |
||||||
|
string input = "(typeName.propertyName).(otherType.otherProperty).property"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "(", "typeName", ".", "propertyName", ")", ".", "(", "otherType", ".", "otherProperty", ")", ".", "property"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InvalidStringTest() |
||||||
|
{ |
||||||
|
string input = "(typeName&.propert$$yName).(##otherType . otherProperty).property"; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "(", "typeName", ".", "propert", "yName", ")", ".", "(", "otherType", ".", "otherProperty", ")", ".", "property"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InCompletionSituationTest1() |
||||||
|
{ |
||||||
|
string input = "(typeName."; |
||||||
|
string[] result = PropertyPathTokenizer.Tokenize(input).ToArray(); |
||||||
|
|
||||||
|
CompareResults(result, "(", "typeName", "."); |
||||||
|
} |
||||||
|
|
||||||
|
void CompareResults(string[] result, params string[] expected) |
||||||
|
{ |
||||||
|
Assert.AreEqual(expected, result); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,99 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Linq; |
||||||
|
|
||||||
|
namespace ICSharpCode.XamlBinding |
||||||
|
{ |
||||||
|
public class PropertyPathParser |
||||||
|
{ |
||||||
|
public static IEnumerable<PropertyPathSegment> Parse(string text) |
||||||
|
{ |
||||||
|
string token = ""; |
||||||
|
|
||||||
|
bool inBrace = false; |
||||||
|
bool inIndexer = false; |
||||||
|
bool isSourceTraversal = false; |
||||||
|
|
||||||
|
string lastToken = ""; |
||||||
|
|
||||||
|
foreach (string v in PropertyPathTokenizer.Tokenize(text)) { |
||||||
|
lastToken = v; |
||||||
|
|
||||||
|
if (v == "(") { |
||||||
|
inBrace = true; |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (v == "[") { |
||||||
|
inIndexer = true; |
||||||
|
if (!inBrace && !string.IsNullOrEmpty(token)) { |
||||||
|
yield return new PropertyPathSegment(SegmentKind.PropertyOrType, token); |
||||||
|
token = ""; |
||||||
|
} |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (v == ")") { |
||||||
|
inBrace = false; |
||||||
|
if (!string.IsNullOrEmpty(token)) |
||||||
|
yield return new PropertyPathSegment(SegmentKind.AttachedProperty, token); |
||||||
|
token = ""; |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (v == "]") { |
||||||
|
inIndexer = false; |
||||||
|
if (!inBrace && !string.IsNullOrEmpty(token)) { |
||||||
|
yield return new PropertyPathSegment(SegmentKind.Indexer, token); |
||||||
|
token = ""; |
||||||
|
} |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (inBrace) |
||||||
|
token += v; |
||||||
|
else if (inIndexer) |
||||||
|
token += v; |
||||||
|
else if (v == ".") { |
||||||
|
if (!string.IsNullOrEmpty(token)) |
||||||
|
yield return new PropertyPathSegment(isSourceTraversal ? SegmentKind.SourceTraversal : SegmentKind.PropertyOrType, token); |
||||||
|
token = ""; |
||||||
|
isSourceTraversal = false; |
||||||
|
} else if (v == "/") { |
||||||
|
token += v; |
||||||
|
isSourceTraversal = true; |
||||||
|
} else { |
||||||
|
token += v; |
||||||
|
} |
||||||
|
|
||||||
|
Debug.Print("inBrace: " + inBrace + " token: '" + token + "'"); |
||||||
|
} |
||||||
|
|
||||||
|
Debug.Print("inBrace: " + inBrace + " token: '" + token + "' lastToken: '" + lastToken + "'"); |
||||||
|
|
||||||
|
|
||||||
|
if (inBrace && !string.IsNullOrEmpty(token)) { |
||||||
|
yield return new PropertyPathSegment(SegmentKind.AttachedProperty, "(" + token.Trim('.', '/')); |
||||||
|
} |
||||||
|
if (!string.IsNullOrEmpty(lastToken)) { |
||||||
|
char c = lastToken.First(); |
||||||
|
|
||||||
|
if (c == ')' || c == ']') |
||||||
|
yield break; |
||||||
|
|
||||||
|
if (PropertyPathTokenizer.ControlChars.Contains(c)) |
||||||
|
yield return new PropertyPathSegment(SegmentKind.ControlChar, c.ToString()); |
||||||
|
else if (!inBrace && !string.IsNullOrEmpty(token)) |
||||||
|
yield return new PropertyPathSegment(isSourceTraversal ? SegmentKind.SourceTraversal : SegmentKind.PropertyOrType, token); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,61 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Linq; |
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace ICSharpCode.XamlBinding |
||||||
|
{ |
||||||
|
public struct PropertyPathSegment : IEquatable<PropertyPathSegment> |
||||||
|
{ |
||||||
|
public SegmentKind Kind; |
||||||
|
public string Content; |
||||||
|
|
||||||
|
public PropertyPathSegment(SegmentKind kind, string content) |
||||||
|
{ |
||||||
|
this.Kind = kind; |
||||||
|
this.Content = content; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() |
||||||
|
{ |
||||||
|
return "[PropertyPathSegment Kind: " + Kind + ", Content: " + Content + " ]"; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object obj) |
||||||
|
{ |
||||||
|
if (obj is PropertyPathSegment) |
||||||
|
return Equals((PropertyPathSegment)obj); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public bool Equals(PropertyPathSegment other) |
||||||
|
{ |
||||||
|
if (other == null) |
||||||
|
return false; |
||||||
|
|
||||||
|
return other.Content == this.Content && |
||||||
|
other.Kind == this.Kind; |
||||||
|
} |
||||||
|
|
||||||
|
public int GetHashCode(PropertyPathSegment obj) |
||||||
|
{ |
||||||
|
return obj.Content.GetHashCode() ^ obj.Kind.GetHashCode(); |
||||||
|
} |
||||||
|
|
||||||
|
public static bool operator ==(PropertyPathSegment lhs, PropertyPathSegment rhs) |
||||||
|
{ |
||||||
|
return Equals(lhs, rhs); |
||||||
|
} |
||||||
|
|
||||||
|
public static bool operator !=(PropertyPathSegment lhs, PropertyPathSegment rhs) |
||||||
|
{ |
||||||
|
return !(lhs == rhs); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,85 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Linq; |
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace ICSharpCode.XamlBinding |
||||||
|
{ |
||||||
|
public class PropertyPathTokenizer |
||||||
|
{ |
||||||
|
string value; |
||||||
|
int offset; |
||||||
|
|
||||||
|
public static readonly char[] ControlChars = new char[] { '.', ',', '(', ')', '[', ']', '/' }; |
||||||
|
|
||||||
|
PropertyPathTokenizer(string value) |
||||||
|
{ |
||||||
|
this.value = value; |
||||||
|
this.offset = 0; |
||||||
|
} |
||||||
|
|
||||||
|
bool NextToken(out string token) |
||||||
|
{ |
||||||
|
token = ""; |
||||||
|
|
||||||
|
if (MoveToNext()) { |
||||||
|
switch (value[offset]) { |
||||||
|
case '.': |
||||||
|
case '(': |
||||||
|
case ')': |
||||||
|
case '[': |
||||||
|
case ']': |
||||||
|
case ',': |
||||||
|
case '/': |
||||||
|
token = value[offset].ToString(); |
||||||
|
offset++; |
||||||
|
return true; |
||||||
|
default: |
||||||
|
string text = ""; |
||||||
|
while (!AtEnd() && char.IsLetterOrDigit(value[offset])) { |
||||||
|
text += value[offset]; |
||||||
|
offset++; |
||||||
|
} |
||||||
|
|
||||||
|
token = text; |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool MoveToNext() |
||||||
|
{ |
||||||
|
// skip all invalid chars
|
||||||
|
while (!AtEnd() && !char.IsLetterOrDigit(value[offset]) && !ControlChars.Contains(value[offset])) |
||||||
|
offset++; |
||||||
|
|
||||||
|
return !AtEnd(); |
||||||
|
} |
||||||
|
|
||||||
|
bool AtEnd() |
||||||
|
{ |
||||||
|
return offset >= value.Length; |
||||||
|
} |
||||||
|
|
||||||
|
public static IEnumerable<string> Tokenize(string value) |
||||||
|
{ |
||||||
|
if (value == null) |
||||||
|
throw new ArgumentNullException("value"); |
||||||
|
|
||||||
|
PropertyPathTokenizer tokenizer = new PropertyPathTokenizer(value); |
||||||
|
|
||||||
|
string token; |
||||||
|
|
||||||
|
while (tokenizer.NextToken(out token)) |
||||||
|
yield return token; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.XamlBinding |
||||||
|
{ |
||||||
|
public enum SegmentKind { |
||||||
|
ControlChar, |
||||||
|
PropertyOrType, |
||||||
|
AttachedProperty, |
||||||
|
Indexer, |
||||||
|
SourceTraversal |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue