Browse Source

Added MarkupExtensionTokenizer and MarkupExtensionParser

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3973 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 16 years ago
parent
commit
63a5635d4b
  1. 53
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs
  2. 72
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs
  3. 48
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParseException.cs
  4. 52
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs
  5. 28
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionToken.cs
  6. 22
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenKind.cs
  7. 148
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs
  8. 6
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj
  9. 18
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs
  10. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerServer.cs

53
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs

@ -15,62 +15,9 @@ namespace ICSharpCode.XamlBinding @@ -15,62 +15,9 @@ namespace ICSharpCode.XamlBinding
{
public static class Extensions
{
static readonly char[] whitespaces = new char[] { ' ', '\t', '\n', '\r' };
public static string[] Split(this string s, StringSplitOptions options, params char[] delimiters)
{
return s.Split(delimiters, options);
}
public static MarkupExtensionInfo ParseMarkupExtension(this XamlParser parser, string fileName, string fileContent, int index)
{
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(fileContent, index);
ParseInformation info = ParserService.GetParseInformation(fileName);
if (path != null && path.Elements.Count > 0) {
if (XmlParser.IsInsideAttributeValue(fileContent, index)) {
string value = XmlParser.GetAttributeValueAtIndex(fileContent, index).Trim(whitespaces);
string name = XmlParser.GetAttributeNameAtIndex(fileContent, index);
if (!string.IsNullOrEmpty(value) && value.StartsWith("{")) {
string[] parts = value.Split(whitespaces, StringSplitOptions.RemoveEmptyEntries);
string extensionType = parts[0].TrimStart('{');
XamlResolver resolver = new XamlResolver();
TypeResolveResult trr = resolver.Resolve(new ExpressionResult(extensionType, new XamlExpressionContext(path, name, true)), info, fileContent) as TypeResolveResult;
if (trr != null) {
}
}
}
}
return MarkupExtensionInfo.Empty;
}
public static bool IsInsideMarkupExtension(this XamlParser parser, string fileContent, int index)
{
if (XmlParser.IsInsideAttributeValue(fileContent, index)) {
string value = XmlParser.GetAttributeValueAtIndex(fileContent, index).Trim(' ', '\t', '\n', '\r');
if (!string.IsNullOrEmpty(value) && value.StartsWith("{"))
return true;
}
return false;
}
}
public struct MarkupExtensionInfo
{
IEntity extension;
public static readonly MarkupExtensionInfo Empty = new MarkupExtensionInfo(null);
public MarkupExtensionInfo(IEntity extension)
{
this.extension = extension;
}
public IEntity Extension {
get { return extension; }
}
}
}

72
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
// <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.Linq;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding
{
public class MarkupExtensionInfo
{
public string Type { get; set; }
public IList<AttributeValue> PositionalArguments { get; set; }
public IDictionary<string, AttributeValue> NamedArguments { get; set; }
public MarkupExtensionInfo()
: this(string.Empty, new List<AttributeValue>(), new Dictionary<string, AttributeValue>())
{
}
public MarkupExtensionInfo(string type, IList<AttributeValue> posArgs, IDictionary<string, AttributeValue> namedArgs)
{
this.Type = type;
this.PositionalArguments = posArgs;
this.NamedArguments = namedArgs;
}
}
public class AttributeValue
{
string stringValue;
MarkupExtensionInfo extensionValue;
public bool IsString {
get { return stringValue != null; }
}
public string StringValue {
get { return stringValue; }
}
public MarkupExtensionInfo ExtensionValue {
get { return extensionValue; }
}
public AttributeValue(string value)
{
if (value == null)
throw new ArgumentNullException("value");
this.stringValue = value;
this.extensionValue = null;
}
public AttributeValue(MarkupExtensionInfo value)
{
if (value == null)
throw new ArgumentNullException("value");
this.stringValue = null;
this.extensionValue = value;
}
}
}

48
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParseException.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision: 3494 $</version>
// </file>
using System;
using System.Runtime.Serialization;
namespace ICSharpCode.XamlBinding
{
/// <summary>
/// Exception thrown when XAML loading fails because there is a syntax error in a markup extension.
/// </summary>
[Serializable]
public class MarkupExtensionParseException : Exception
{
/// <summary>
/// Create a new XamlMarkupExtensionParseException instance.
/// </summary>
public MarkupExtensionParseException()
{
}
/// <summary>
/// Create a new XamlMarkupExtensionParseException instance.
/// </summary>
public MarkupExtensionParseException(string message) : base(message)
{
}
/// <summary>
/// Create a new XamlMarkupExtensionParseException instance.
/// </summary>
public MarkupExtensionParseException(string message, Exception innerException) : base(message, innerException)
{
}
/// <summary>
/// Create a new XamlMarkupExtensionParseException instance.
/// </summary>
protected MarkupExtensionParseException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}

52
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
// <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
{
static class MarkupExtensionParser
{
public static MarkupExtensionInfo Parse(string text)
{
var info = new MarkupExtensionInfo();
var tokens = MarkupExtensionTokenizer.Tokenize(text);
string argumentName = null;
foreach (var token in tokens) {
switch (token.Kind) {
case MarkupExtensionTokenKind.TypeName:
info.Type = token.Value;
break;
case MarkupExtensionTokenKind.Membername:
argumentName = token.Value;
break;
case MarkupExtensionTokenKind.String:
if (argumentName != null) {
info.NamedArguments.Add(argumentName, ParseValue(token.Value));
argumentName = null;
} else {
info.PositionalArguments.Add(ParseValue(token.Value));
}
break;
}
}
return info;
}
static AttributeValue ParseValue(string text)
{
if (text.StartsWith("{", StringComparison.OrdinalIgnoreCase))
return new AttributeValue(Parse(text));
else
return new AttributeValue(text);
}
}
}

28
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionToken.cs

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision: 3494 $</version>
// </file>
using System;
namespace ICSharpCode.XamlBinding
{
public sealed class MarkupExtensionToken
{
public readonly MarkupExtensionTokenKind Kind;
public readonly string Value;
public MarkupExtensionToken(MarkupExtensionTokenKind kind, string value)
{
this.Kind = kind;
this.Value = value;
}
public override string ToString()
{
return "[" + Kind + " " + Value + "]";
}
}
}

22
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenKind.cs

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision: 3494 $</version>
// </file>
using System;
namespace ICSharpCode.XamlBinding
{
public enum MarkupExtensionTokenKind
{
OpenBrace,
CloseBrace,
Equals,
Comma,
TypeName,
Membername,
String
}
}

148
src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionTokenizer.cs

@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision: 3494 $</version>
// </file>
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.XamlBinding
{
/// <summary>
/// Tokenizer for markup extension attributes.
/// [MS-XAML 6.6.7.1]
/// </summary>
public sealed class MarkupExtensionTokenizer
{
private MarkupExtensionTokenizer() {}
string text;
int pos;
List<MarkupExtensionToken> tokens = new List<MarkupExtensionToken>();
public static List<MarkupExtensionToken> Tokenize(string text)
{
MarkupExtensionTokenizer t = new MarkupExtensionTokenizer();
t.text = text;
t.Parse();
return t.tokens;
}
void AddToken(MarkupExtensionTokenKind kind, string val)
{
tokens.Add(new MarkupExtensionToken(kind, val));
}
void Parse()
{
AddToken(MarkupExtensionTokenKind.OpenBrace, "{");
Expect('{');
ConsumeWhitespace();
CheckNotEOF();
StringBuilder b = new StringBuilder();
while (pos < text.Length && !char.IsWhiteSpace(text, pos) && text[pos] != '}')
b.Append(text[pos++]);
AddToken(MarkupExtensionTokenKind.TypeName, b.ToString());
ConsumeWhitespace();
while (pos < text.Length) {
switch (text[pos]) {
case '}':
AddToken(MarkupExtensionTokenKind.CloseBrace, "}");
pos++;
break;
case '=':
AddToken(MarkupExtensionTokenKind.Equals, "=");
pos++;
break;
case ',':
AddToken(MarkupExtensionTokenKind.Comma, ",");
pos++;
break;
default:
MembernameOrString();
break;
}
ConsumeWhitespace();
}
}
void MembernameOrString()
{
StringBuilder b = new StringBuilder();
if (text[pos] == '"' || text[pos] == '\'') {
char quote = text[pos++];
CheckNotEOF();
while (!(text[pos] == quote && text[pos-1] != '\\')) {
char c = text[pos++];
if (c != '\\')
b.Append(c);
CheckNotEOF();
}
pos++; // consume closing quote
ConsumeWhitespace();
} else {
int braceTotal = 0;
while (true) {
CheckNotEOF();
switch (text[pos]) {
case '\\':
pos++;
CheckNotEOF();
b.Append(text[pos++]);
break;
case '{':
b.Append(text[pos++]);
braceTotal++;
break;
case '}':
if (braceTotal == 0) goto stop;
b.Append(text[pos++]);
braceTotal--;
break;
case ',':
case '=':
if (braceTotal == 0) goto stop;
b.Append(text[pos++]);
break;
default:
b.Append(text[pos++]);
break;
}
}
stop:;
}
CheckNotEOF();
string valueText = b.ToString();
if (text[pos] == '=') {
AddToken(MarkupExtensionTokenKind.Membername, valueText.Trim());
} else {
AddToken(MarkupExtensionTokenKind.String, valueText);
}
}
void Expect(char c)
{
CheckNotEOF();
if (text[pos] != c)
throw new MarkupExtensionParseException("Expected '" + c + "'");
pos++;
}
void ConsumeWhitespace()
{
while (pos < text.Length && char.IsWhiteSpace(text, pos))
pos++;
}
void CheckNotEOF()
{
if (pos >= text.Length)
throw new MarkupExtensionParseException("Unexpected end of markup extension");
}
}
}

6
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj

@ -60,8 +60,13 @@ @@ -60,8 +60,13 @@
<Compile Include="..\..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="MarkupExtensionInfo.cs" />
<Compile Include="MarkupExtensionParser.cs" />
<Compile Include="CompletionDataHelper.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="MarkupExtensionTokenizer.cs" />
<Compile Include="MarkupExtensionToken.cs" />
<Compile Include="MarkupExtensionTokenKind.cs" />
<Compile Include="Utils.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XamlClassReturnType.cs" />
@ -77,6 +82,7 @@ @@ -77,6 +82,7 @@
<DependentUpon>XamlExpressionContext.cs</DependentUpon>
</Compile>
<Compile Include="XamlColorizer.cs" />
<Compile Include="MarkupExtensionParseException.cs" />
<Compile Include="XamlParser.cs" />
<Compile Include="XamlResolver.cs" />
<ProjectReference Include="..\..\..\..\Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj">

18
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs

@ -109,15 +109,15 @@ namespace ICSharpCode.XamlBinding @@ -109,15 +109,15 @@ namespace ICSharpCode.XamlBinding
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
} else {
if (parser.IsInsideMarkupExtension(editor.Document.Text, editor.Caret.Offset)) {
var list = CompletionDataHelper.CreateListForElement(info, editor.Document.Text,
editor.Caret.Line, editor.Caret.Column);
var needed = list.Where(i => ((i as XamlCompletionItem).Entity as IClass).ClassInheritanceTree
.Any(item => item.FullyQualifiedName == "System.Windows.Markup.MarkupExtension"));
MarkupExtensionInfo markup = parser.ParseMarkupExtension(editor.FileName, editor.Document.Text, editor.Caret.Offset);
}
// if (parser.IsInsideMarkupExtension(editor.Document.Text, editor.Caret.Offset)) {
// var list = CompletionDataHelper.CreateListForElement(info, editor.Document.Text,
// editor.Caret.Line, editor.Caret.Column);
// var needed = list.Where(i => ((i as XamlCompletionItem).Entity as IClass).ClassInheritanceTree
// .Any(item => item.FullyQualifiedName == "System.Windows.Markup.MarkupExtension"));
//
// MarkupExtensionInfo markup = parser.ParseMarkupExtension(editor.FileName, editor.Document.Text, editor.Caret.Offset);
//
// }
}
}
break;

2
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizerServer.cs

@ -28,6 +28,8 @@ namespace ICSharpCode.XamlBinding @@ -28,6 +28,8 @@ namespace ICSharpCode.XamlBinding
static void WorkbenchSingleton_Workbench_ViewOpened(object sender, ViewContentEventArgs e)
{
if (e.Content.PrimaryFileName == null)
return;
if (!Path.GetExtension(e.Content.PrimaryFileName).Equals(".xaml", StringComparison.OrdinalIgnoreCase))
return;
ITextEditorProvider textEditor = e.Content as ITextEditorProvider;

Loading…
Cancel
Save