25 changed files with 853 additions and 3577 deletions
@ -1,181 +0,0 @@
@@ -1,181 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
using ICSharpCode.AvalonEdit.Xml; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
public sealed class CompilationUnitCreatorVisitor : AbstractAXmlVisitor |
||||
{ |
||||
public XamlCompilationUnit CompilationUnit { get; private set; } |
||||
AXmlDocument document; |
||||
IClass generatedClass; |
||||
IProjectContent projectContent; |
||||
Stack<NodeWrapper> nodeStack; |
||||
IAmbience currentAmbience; |
||||
|
||||
/// <summary>
|
||||
/// string representation of the document, used to create DOM regions.
|
||||
/// </summary>
|
||||
string fileContent; |
||||
|
||||
string[] lexerTags; |
||||
|
||||
public CompilationUnitCreatorVisitor(IProjectContent projectContent, string fileContent, string fileName, string[] lexerTags) |
||||
{ |
||||
this.CompilationUnit = new XamlCompilationUnit(projectContent); |
||||
|
||||
this.CompilationUnit.FileName = fileName; |
||||
this.fileContent = fileContent; |
||||
this.lexerTags = lexerTags; |
||||
this.projectContent = projectContent; |
||||
this.currentAmbience = projectContent.Language.GetAmbience(); |
||||
|
||||
this.nodeStack = new Stack<NodeWrapper>(); |
||||
} |
||||
|
||||
public override void VisitDocument(AXmlDocument document) |
||||
{ |
||||
this.CompilationUnit.ErrorsDuringCompile = document.SyntaxErrors.Any(); |
||||
this.document = document; |
||||
|
||||
base.VisitDocument(document); |
||||
} |
||||
|
||||
public override void VisitAttribute(AXmlAttribute attribute) |
||||
{ |
||||
Debug.Assert(document != null); |
||||
|
||||
if (attribute.ParentElement != null) { |
||||
if (attribute.ParentElement.Parent == document && attribute.LocalName == "Class" && |
||||
attribute.Namespace == CompletionDataHelper.XamlNamespace) { |
||||
this.generatedClass = AddClass(attribute.Value, attribute.ParentElement); |
||||
} else if (generatedClass != null && attribute.LocalName == "Name") { |
||||
string name = attribute.Value; |
||||
|
||||
if (!string.IsNullOrEmpty(name)) { |
||||
IReturnType type = TypeFromXmlNode(CompilationUnit, attribute.ParentElement); |
||||
DomRegion position = CreateRegion(attribute.ParentElement.StartOffset, attribute.ParentElement.StartOffset + attribute.ParentElement.Name.Length); |
||||
|
||||
ModifierEnum fieldModifier = ModifierEnum.Internal; |
||||
|
||||
string modifierValue = (attribute.ParentElement.GetAttributeValue(CompletionDataHelper.XamlNamespace, "FieldModifier") ?? string.Empty).Trim(); |
||||
|
||||
string publicString = currentAmbience.ConvertAccessibility(ModifierEnum.Public).Trim(); |
||||
|
||||
if (projectContent.Language.NameComparer.Compare(modifierValue, publicString) == 0) |
||||
fieldModifier = ModifierEnum.Public; |
||||
|
||||
generatedClass.Fields.Add(new DefaultField(type, name, fieldModifier, position, generatedClass)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
base.VisitAttribute(attribute); |
||||
} |
||||
|
||||
public override void VisitTag(AXmlTag tag) |
||||
{ |
||||
if (tag.IsComment) { |
||||
StringBuilder sb = new StringBuilder(); |
||||
|
||||
foreach(AXmlText text in tag.Children.OfType<AXmlText>()) { |
||||
sb.Append(text.Value); |
||||
} |
||||
|
||||
string value = sb.ToString(); |
||||
|
||||
foreach (string commentTag in lexerTags) { |
||||
if (value.Contains(commentTag)) { |
||||
CompilationUnit.TagComments.Add(new TagComment(value, CreateRegion(tag.StartOffset, tag.EndOffset))); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
base.VisitTag(tag); |
||||
} |
||||
|
||||
public override void VisitElement(AXmlElement element) |
||||
{ |
||||
AXmlTag tag = element.Children.FirstOrDefault() as AXmlTag; |
||||
|
||||
if (tag != null && tag.IsStartOrEmptyTag) { |
||||
NodeWrapper node = new NodeWrapper() { |
||||
ElementName = element.LocalName, |
||||
StartOffset = element.StartOffset, |
||||
EndOffset = element.EndOffset, |
||||
Name = element.GetAttributeValue("Name") ?? element.GetAttributeValue(CompletionDataHelper.XamlNamespace, "Name"), |
||||
Children = new List<NodeWrapper>() |
||||
}; |
||||
|
||||
if (CompilationUnit.TreeRootNode == null) { |
||||
CompilationUnit.TreeRootNode = node; |
||||
nodeStack.Push(CompilationUnit.TreeRootNode); |
||||
} else { |
||||
if (nodeStack.Count > 0) |
||||
nodeStack.Peek().Children.Add(node); |
||||
if (!tag.IsEmptyTag) |
||||
nodeStack.Push(node); |
||||
} |
||||
} |
||||
|
||||
base.VisitElement(element); |
||||
|
||||
if (tag != null && tag.IsStartTag) |
||||
nodeStack.PopOrDefault(); |
||||
} |
||||
|
||||
IClass AddClass(string className, AXmlElement element) { |
||||
if (projectContent.Language == LanguageProperties.VBNet && projectContent.Project is IProject) |
||||
className = ((IProject)projectContent.Project).RootNamespace + "." + className; |
||||
|
||||
DefaultClass c = new DefaultClass(CompilationUnit, className); |
||||
string modifierValue = (element.GetAttributeValue(CompletionDataHelper.XamlNamespace, "ClassModifier") ?? string.Empty).Trim(); |
||||
|
||||
c.Modifiers = ModifierEnum.Partial; |
||||
|
||||
string internalString = currentAmbience.ConvertAccessibility(ModifierEnum.Internal).Trim(); |
||||
|
||||
if (projectContent.Language.NameComparer.Compare(modifierValue, internalString) == 0) |
||||
c.Modifiers |= ModifierEnum.Internal; |
||||
else |
||||
c.Modifiers |= ModifierEnum.Public; |
||||
|
||||
c.Region = CreateRegion(element.StartOffset, element.EndOffset); |
||||
var baseType = TypeFromXmlNode(CompilationUnit, element); |
||||
if (baseType != null) |
||||
c.BaseTypes.Add(baseType); |
||||
CompilationUnit.Classes.Add(c); |
||||
|
||||
DefaultMethod initializeComponent = new DefaultMethod( |
||||
"InitializeComponent", |
||||
projectContent.SystemTypes.Void, |
||||
ModifierEnum.Public | ModifierEnum.Synthetic, c.Region, DomRegion.Empty, |
||||
c); |
||||
c.Methods.Add(initializeComponent); |
||||
|
||||
return c; |
||||
} |
||||
|
||||
DomRegion CreateRegion(int startOffset, int endOffset) |
||||
{ |
||||
ICSharpCode.NRefactory.Location loc = Utils.GetLocationInfoFromOffset(fileContent, startOffset); |
||||
ICSharpCode.NRefactory.Location loc2 = Utils.GetLocationInfoFromOffset(fileContent, endOffset); |
||||
return new DomRegion(loc.Line, loc.Column, loc2.Line, loc2.Column); |
||||
} |
||||
|
||||
static IReturnType TypeFromXmlNode(XamlCompilationUnit cu, AXmlElement element) |
||||
{ |
||||
return cu.CreateType(element.Namespace, element.LocalName); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,42 +0,0 @@
@@ -1,42 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
/// <summary>
|
||||
/// IReturnType that gets created by XamlCompilationUnit.CreateType and will
|
||||
/// run XamlCompilationUnit.FindType on demand.
|
||||
/// </summary>
|
||||
public class XamlClassReturnType : ProxyReturnType |
||||
{ |
||||
XamlCompilationUnit compilationUnit; |
||||
string xmlNamespace; |
||||
string className; |
||||
|
||||
public XamlClassReturnType(XamlCompilationUnit compilationUnit, string xmlNamespace, string className) |
||||
{ |
||||
if (compilationUnit == null) |
||||
throw new ArgumentNullException("compilationUnit"); |
||||
|
||||
this.compilationUnit = compilationUnit; |
||||
this.xmlNamespace = xmlNamespace; |
||||
this.className = className ?? ""; |
||||
} |
||||
|
||||
public override IReturnType BaseType |
||||
{ |
||||
get |
||||
{ |
||||
return compilationUnit.FindType(xmlNamespace, className); |
||||
} |
||||
} |
||||
|
||||
public override string Name |
||||
{ |
||||
get { return className; } |
||||
} |
||||
} |
||||
} |
@ -1,394 +0,0 @@
@@ -1,394 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using ICSharpCode.Core; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
using System.Windows.Threading; |
||||
using ICSharpCode.AvalonEdit.Document; |
||||
using ICSharpCode.AvalonEdit.Rendering; |
||||
using ICSharpCode.AvalonEdit.Xml; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.XmlEditor; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
using Task = System.Threading.Tasks.Task; |
||||
using Tasks = System.Threading.Tasks; |
||||
|
||||
public class XamlColorizer : DocumentColorizingTransformer, ILineTracker, IDisposable |
||||
{ |
||||
public struct Highlight { |
||||
public IMember Member { get; set; } |
||||
public HighlightingInfo Info { get; set; } |
||||
} |
||||
|
||||
public sealed class HighlightTask { |
||||
// input
|
||||
readonly string fileName; |
||||
readonly string lineText; |
||||
readonly int offset; |
||||
|
||||
TextView textView; |
||||
ITextBuffer snapshot; |
||||
|
||||
public HighlightTask(ITextEditor editor, DocumentLine currentLine, TextView textView) |
||||
{ |
||||
this.fileName = editor.FileName; |
||||
this.textView = textView; |
||||
this.snapshot = editor.Document.CreateSnapshot(); |
||||
this.lineText = textView.Document.GetText(currentLine); |
||||
this.offset = currentLine.Offset; |
||||
this.task = new Task(Process); |
||||
} |
||||
|
||||
public HighlightTask(ITextEditor editor, DocumentLine currentLine, TextView textView, IList<Highlight> oldHighlightData) |
||||
: this(editor, currentLine, textView) |
||||
{ |
||||
this.results = oldHighlightData; |
||||
} |
||||
|
||||
IList<Highlight> results; |
||||
|
||||
// output
|
||||
public Highlight[] GetResults() |
||||
{ |
||||
lock (this) { |
||||
if (results == null) |
||||
return null; |
||||
return results.ToArray(); |
||||
} |
||||
} |
||||
|
||||
readonly Task task; |
||||
|
||||
public void Start() |
||||
{ |
||||
task.Start(); |
||||
} |
||||
|
||||
public bool CompletedSuccessfully { |
||||
get { |
||||
return task.IsCompleted && task.Status == Tasks.TaskStatus.RanToCompletion; |
||||
} |
||||
} |
||||
|
||||
public bool Invalid { get; set; } |
||||
|
||||
void Process() |
||||
{ |
||||
try { |
||||
List<Highlight> results = new List<Highlight>(); |
||||
|
||||
foreach (HighlightingInfo info in GetInfo()) { |
||||
IMember member = null; |
||||
|
||||
// Commented out because task doesn't come with cancellation support in .NET 4.0 Beta 2
|
||||
// (use CancellationToken instead)
|
||||
// I didn't have to remove any call to task.Cancel(), so apparently this was dead code.
|
||||
//if (task.IsCancellationRequested) {
|
||||
// task.AcknowledgeCancellation();
|
||||
// return;
|
||||
//}
|
||||
// TODO: implement cancellation support
|
||||
|
||||
if (!info.Token.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { |
||||
MemberResolveResult rr = XamlResolver.Resolve(info.Token, info.Context) as MemberResolveResult; |
||||
member = (rr != null) ? rr.ResolvedMember : null; |
||||
} |
||||
|
||||
results.Add(new Highlight() { Member = member, Info = info }); |
||||
} |
||||
|
||||
lock (this) |
||||
this.results = results; |
||||
|
||||
WorkbenchSingleton.SafeThreadAsyncCall(InvokeRedraw); |
||||
} catch (Exception e) { |
||||
WorkbenchSingleton.SafeThreadAsyncCall(() => MessageService.ShowException(e)); |
||||
} |
||||
} |
||||
|
||||
void InvokeRedraw() |
||||
{ |
||||
task.Wait(); |
||||
textView.Redraw(this.offset, this.lineText.Length, DispatcherPriority.Background); |
||||
} |
||||
|
||||
IEnumerable<HighlightingInfo> GetInfo() |
||||
{ |
||||
int index = -1; |
||||
XamlContext context = null; |
||||
|
||||
do { |
||||
if (index + 1 >= lineText.Length) |
||||
break; |
||||
|
||||
index = lineText.IndexOfAny(index + 1, '=', '.'); |
||||
if (index > -1) { |
||||
context = CompletionDataHelper.ResolveContext(snapshot, fileName, offset + index); |
||||
|
||||
if (context.ActiveElement == null || context.InAttributeValueOrMarkupExtension || context.InCommentOrCData) |
||||
continue; |
||||
|
||||
string propertyName; |
||||
string token; |
||||
int startIndex; |
||||
|
||||
switch (context.Description) { |
||||
case XamlContextDescription.AtTag: |
||||
token = context.ActiveElement.Name; |
||||
int propertyNameIndex = token.IndexOf('.'); |
||||
|
||||
if (propertyNameIndex == -1) |
||||
continue; |
||||
|
||||
propertyName = token.Substring(propertyNameIndex + 1); |
||||
startIndex = lineText.IndexOf(propertyName, index, StringComparison.Ordinal); |
||||
break; |
||||
case XamlContextDescription.InTag: |
||||
if (lineText[index] == '.' || context.Attribute == null) |
||||
continue; |
||||
|
||||
token = propertyName = context.Attribute.Name; |
||||
startIndex = lineText.LastIndexOf(propertyName, index, StringComparison.Ordinal); |
||||
break; |
||||
default: |
||||
continue; |
||||
} |
||||
|
||||
if (startIndex > -1) { |
||||
yield return new HighlightingInfo(token, startIndex, startIndex + propertyName.Length, offset, context); |
||||
} |
||||
} |
||||
} while (index > -1); |
||||
} |
||||
} |
||||
|
||||
Dictionary<DocumentLine, HighlightTask> highlightCache = new Dictionary<DocumentLine, HighlightTask>(); |
||||
|
||||
public ITextEditor Editor { get; set; } |
||||
|
||||
public AvalonEdit.Rendering.TextView TextView { get; set; } |
||||
|
||||
public XamlColorizer(ITextEditor editor, TextView textView) |
||||
{ |
||||
this.Editor = editor; |
||||
this.TextView = textView; |
||||
|
||||
this.weakLineTracker = WeakLineTracker.Register(this.Editor.Document.GetService(typeof(TextDocument)) as TextDocument, this); |
||||
|
||||
ParserService.LoadSolutionProjectsThreadEnded += ParserServiceLoadSolutionProjectsThreadEnded; |
||||
|
||||
colorizers.Add(this); |
||||
} |
||||
|
||||
static IList<XamlColorizer> colorizers = new List<XamlColorizer>(); |
||||
|
||||
public static void RefreshAll() |
||||
{ |
||||
foreach (XamlColorizer colorizer in colorizers) { |
||||
colorizer.RebuildDocument(); |
||||
colorizer.TextView.Redraw(); |
||||
} |
||||
} |
||||
|
||||
void ParserServiceLoadSolutionProjectsThreadEnded(object sender, EventArgs e) |
||||
{ |
||||
WorkbenchSingleton.SafeThreadAsyncCall( |
||||
() => { |
||||
highlightCache.Clear(); |
||||
TextView.Redraw(); |
||||
} |
||||
); |
||||
} |
||||
|
||||
WeakLineTracker weakLineTracker; |
||||
bool disposed; |
||||
|
||||
public void Dispose() |
||||
{ |
||||
if (!disposed) { |
||||
ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded; |
||||
weakLineTracker.Deregister(); |
||||
colorizers.Remove(this); |
||||
} |
||||
disposed = true; |
||||
} |
||||
|
||||
protected override void ColorizeLine(DocumentLine line) |
||||
{ |
||||
if (!highlightCache.ContainsKey(line)) { |
||||
HighlightTask task = new HighlightTask(this.Editor, line, this.TextView); |
||||
task.Start(); |
||||
highlightCache.Add(line, task); |
||||
} else { |
||||
HighlightTask task = highlightCache[line]; |
||||
var results = task.GetResults(); |
||||
if (results != null) { |
||||
foreach (var result in results) { |
||||
ColorizeMember(result.Info, line, result.Member); |
||||
} |
||||
} |
||||
} |
||||
ColorizeInvalidated(); |
||||
} |
||||
|
||||
void ColorizeMember(HighlightingInfo info, DocumentLine line, IMember member) |
||||
{ |
||||
try { |
||||
Action<VisualLineElement> handler = null; |
||||
|
||||
if (info.Token.StartsWith(info.Context.XamlNamespacePrefix + ":", StringComparison.Ordinal)) |
||||
handler = HighlightProperty; |
||||
else if (info.Context.IgnoredXmlns.Any(item => info.Token.StartsWith(item + ":", StringComparison.Ordinal))) |
||||
handler = HighlightIgnored; |
||||
else if (member != null) { |
||||
if (member is IEvent) |
||||
handler = HighlightEvent; |
||||
else |
||||
handler = HighlightProperty; |
||||
} else { |
||||
if (info.Token.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase) || info.Token.StartsWith(Utils.GetNamespacePrefix(CompletionDataHelper.MarkupCompatibilityNamespace, info.Context) + ":", StringComparison.OrdinalIgnoreCase)) |
||||
handler = HighlightNamespaceDeclaration; |
||||
else if (info.Token.StartsWith("xml:", StringComparison.OrdinalIgnoreCase)) |
||||
handler = HighlightProperty; |
||||
else |
||||
Core.LoggingService.Debug(info.Token + " not highlighted; line " + line.LineNumber); |
||||
} |
||||
if (handler != null) |
||||
ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, handler); |
||||
} catch (ArgumentOutOfRangeException) {} |
||||
} |
||||
|
||||
void ColorizeInvalidated() |
||||
{ |
||||
foreach (var item in highlightCache.ToArray()) { |
||||
if (item.Key.IsDeleted) { |
||||
highlightCache.Remove(item.Key); |
||||
continue; |
||||
} |
||||
if (item.Value.Invalid) { |
||||
var newTask = new HighlightTask(this.Editor, item.Key, this.TextView, item.Value.GetResults()); |
||||
newTask.Start(); |
||||
highlightCache[item.Key] = newTask; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void InvalidateLines(DocumentLine line) |
||||
{ |
||||
DocumentLine current = line; |
||||
while (current != null) { |
||||
HighlightTask task; |
||||
if (highlightCache.TryGetValue(current, out task)) |
||||
task.Invalid = true; |
||||
|
||||
current = current.NextLine; |
||||
} |
||||
} |
||||
|
||||
#region highlight helpers
|
||||
void HighlightProperty(VisualLineElement element) |
||||
{ |
||||
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.PropertyForegroundColor.ToBrush()); |
||||
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.PropertyBackgroundColor.ToBrush()); |
||||
} |
||||
|
||||
void HighlightEvent(VisualLineElement element) |
||||
{ |
||||
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.EventForegroundColor.ToBrush()); |
||||
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.EventBackgroundColor.ToBrush()); |
||||
} |
||||
|
||||
void HighlightNamespaceDeclaration(VisualLineElement element) |
||||
{ |
||||
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.NamespaceDeclarationForegroundColor.ToBrush()); |
||||
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.NamespaceDeclarationBackgroundColor.ToBrush()); |
||||
} |
||||
|
||||
void HighlightIgnored(VisualLineElement element) |
||||
{ |
||||
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.IgnoredForegroundColor.ToBrush()); |
||||
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.IgnoredBackgroundColor.ToBrush()); |
||||
} |
||||
#endregion
|
||||
|
||||
#region ILineTracker implementation
|
||||
public void BeforeRemoveLine(DocumentLine line) |
||||
{ |
||||
InvalidateLines(line.NextLine); |
||||
} |
||||
|
||||
public void SetLineLength(DocumentLine line, int newTotalLength) |
||||
{ |
||||
InvalidateLines(line); |
||||
} |
||||
|
||||
public void LineInserted(DocumentLine insertionPos, DocumentLine newLine) |
||||
{ |
||||
InvalidateLines(newLine); |
||||
} |
||||
|
||||
public void RebuildDocument() |
||||
{ |
||||
highlightCache.Clear(); |
||||
} |
||||
#endregion
|
||||
|
||||
public struct HighlightingInfo |
||||
{ |
||||
string token; |
||||
int startOffset; |
||||
int endOffset; |
||||
int lineOffset; |
||||
XamlContext context; |
||||
|
||||
public HighlightingInfo(string token, int startOffset, int endOffset, int lineOffset, XamlContext context) |
||||
{ |
||||
if (token == null) |
||||
throw new ArgumentNullException("token"); |
||||
if (startOffset < 0) |
||||
throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be greater 0"); |
||||
if (endOffset < 0) |
||||
throw new ArgumentOutOfRangeException("endOffset", endOffset, "Value must be greater 0"); |
||||
if (lineOffset < 0) |
||||
throw new ArgumentOutOfRangeException("lineOffset", lineOffset, "Value must be greater 0"); |
||||
if (context == null) |
||||
throw new ArgumentNullException("context"); |
||||
|
||||
this.token = token; |
||||
this.startOffset = startOffset; |
||||
this.endOffset = endOffset; |
||||
this.lineOffset = lineOffset; |
||||
this.context = context; |
||||
} |
||||
|
||||
public string Token { |
||||
get { return token; } |
||||
} |
||||
|
||||
public int StartOffset { |
||||
get { return startOffset; } |
||||
} |
||||
|
||||
public int EndOffset { |
||||
get { return endOffset; } |
||||
} |
||||
|
||||
public int LineOffset { |
||||
get { return lineOffset; } |
||||
} |
||||
|
||||
public XamlContext Context { |
||||
get { return context; } |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,143 +0,0 @@
@@ -1,143 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using System.Collections; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
/// <summary>
|
||||
/// Description of XamlCompilationUnit.
|
||||
/// </summary>
|
||||
public class XamlCompilationUnit : DefaultCompilationUnit |
||||
{ |
||||
public XamlCompilationUnit(IProjectContent projectContent) |
||||
: base(projectContent) |
||||
{ |
||||
} |
||||
|
||||
public NodeWrapper TreeRootNode { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Creates a IReturnType looking for a class referenced in XAML.
|
||||
/// </summary>
|
||||
/// <param name="xmlNamespace">The XML namespace</param>
|
||||
/// <param name="className">The class name</param>
|
||||
/// <returns>A new IReturnType that will search the referenced type on demand.</returns>
|
||||
public IReturnType CreateType(string xmlNamespace, string className) |
||||
{ |
||||
if (string.IsNullOrEmpty(className) || className.Contains(".")) |
||||
return null; |
||||
|
||||
if (xmlNamespace.StartsWith("clr-namespace:", StringComparison.OrdinalIgnoreCase)) { |
||||
return CreateClrNamespaceType(this.ProjectContent, xmlNamespace, className); |
||||
} else { |
||||
return new XamlClassReturnType(this, xmlNamespace, className); |
||||
} |
||||
} |
||||
|
||||
static IReturnType CreateClrNamespaceType(IProjectContent pc, string xmlNamespace, string className) |
||||
{ |
||||
string namespaceName = GetNamespaceNameFromClrNamespace(xmlNamespace); |
||||
return new GetClassReturnType(pc, namespaceName + "." + className, 0); |
||||
} |
||||
|
||||
static string GetNamespaceNameFromClrNamespace(string xmlNamespace) |
||||
{ |
||||
string namespaceName = xmlNamespace.Substring("clr-namespace:".Length); |
||||
int pos = namespaceName.IndexOf(';'); |
||||
if (pos >= 0) { |
||||
// we expect that the target type is also a reference of the project, so we
|
||||
// can ignore the assembly part after the ;
|
||||
namespaceName = namespaceName.Substring(0, pos); |
||||
} |
||||
return namespaceName; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Finds a type referenced in XAML.
|
||||
/// </summary>
|
||||
/// <param name="xmlNamespace">The XML namespace</param>
|
||||
/// <param name="className">The class name</param>
|
||||
/// <returns>Returns the referenced type, or null if it cannot be found.</returns>
|
||||
public IReturnType FindType(string xmlNamespace, string className) |
||||
{ |
||||
return FindType(this.ProjectContent, xmlNamespace, className); |
||||
} |
||||
|
||||
public static IReturnType FindType(IProjectContent pc, string xmlNamespace, string className) |
||||
{ |
||||
if (pc == null) |
||||
throw new ArgumentNullException("pc"); |
||||
if (xmlNamespace == null || className == null) |
||||
return null; |
||||
if (xmlNamespace.StartsWith("clr-namespace:", StringComparison.OrdinalIgnoreCase)) { |
||||
return CreateClrNamespaceType(pc, xmlNamespace, className); |
||||
} |
||||
else { |
||||
IReturnType type = FindTypeInAssembly(pc, xmlNamespace, className); |
||||
if (type != null) |
||||
return type; |
||||
foreach (IProjectContent p in pc.ReferencedContents) { |
||||
type = FindTypeInAssembly(p, xmlNamespace, className); |
||||
if (type != null) |
||||
return type; |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
static IReturnType FindTypeInAssembly(IProjectContent projectContent, string xmlNamespace, string className) |
||||
{ |
||||
foreach (IAttribute att in projectContent.GetAssemblyAttributes()) { |
||||
if (att.PositionalArguments.Count == 2 |
||||
&& att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") { |
||||
string namespaceName = att.PositionalArguments[1] as string; |
||||
if (xmlNamespace.Equals(att.PositionalArguments[0]) && namespaceName != null) { |
||||
IClass c = projectContent.GetClass(namespaceName + "." + className, 0); |
||||
if (c != null) |
||||
return c.DefaultReturnType; |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public static IEnumerable<IClass> GetNamespaceMembers(IProjectContent pc, string xmlNamespace) |
||||
{ |
||||
if (pc == null) |
||||
throw new ArgumentNullException("pc"); |
||||
|
||||
if (!string.IsNullOrEmpty(xmlNamespace)) { |
||||
if (xmlNamespace.StartsWith("clr-namespace:", StringComparison.OrdinalIgnoreCase)) |
||||
return pc.GetNamespaceContents(GetNamespaceNameFromClrNamespace(xmlNamespace)).OfType<IClass>(); |
||||
else { |
||||
var list = new List<ICompletionEntry>(); |
||||
AddNamespaceMembersInAssembly(pc, xmlNamespace, list); |
||||
foreach (IProjectContent p in pc.ReferencedContents) { |
||||
AddNamespaceMembersInAssembly(p, xmlNamespace, list); |
||||
} |
||||
return list.OfType<IClass>(); |
||||
} |
||||
} |
||||
|
||||
return Enumerable.Empty<IClass>(); |
||||
} |
||||
|
||||
static void AddNamespaceMembersInAssembly(IProjectContent projectContent, string xmlNamespace, List<ICompletionEntry> list) |
||||
{ |
||||
foreach (IAttribute att in projectContent.GetAssemblyAttributes()) { |
||||
if (att.PositionalArguments.Count == 2 |
||||
&& att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") { |
||||
string namespaceName = att.PositionalArguments[1] as string; |
||||
if (xmlNamespace.Equals(att.PositionalArguments[0]) && namespaceName != null) { |
||||
projectContent.AddNamespaceContents(list, namespaceName, projectContent.Language, false); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,309 +0,0 @@
@@ -1,309 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Linq; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
class XamlCodeCompletionItem : CodeCompletionItem |
||||
{ |
||||
public XamlCodeCompletionItem(IEntity entity, string prefix) |
||||
: base(entity) |
||||
{ |
||||
if (string.IsNullOrEmpty(prefix)) |
||||
this.Text = entity.Name; |
||||
else |
||||
this.Text = prefix + ":" + entity.Name; |
||||
this.Content = this.Text; |
||||
} |
||||
|
||||
public XamlCodeCompletionItem(IEntity entity) |
||||
: base(entity) |
||||
{ |
||||
this.Text = entity.Name; |
||||
this.Content = this.Text; |
||||
} |
||||
|
||||
public XamlCodeCompletionItem(string text, IEntity entity) |
||||
: base(entity) |
||||
{ |
||||
this.Text = text; |
||||
this.Content = this.Text; |
||||
} |
||||
|
||||
public XamlCodeCompletionItem(IEntity entity, string prefix, string className) |
||||
: base(entity) |
||||
{ |
||||
if (string.IsNullOrEmpty(prefix)) |
||||
this.Text = className + "." + entity.Name; |
||||
else |
||||
this.Text = prefix + ":" + className + "." + entity.Name; |
||||
this.Content = this.Text; |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return "[" + this.Text + "]"; |
||||
} |
||||
} |
||||
|
||||
class XamlLazyValueCompletionItem : XamlCodeCompletionItem |
||||
{ |
||||
bool addType; |
||||
|
||||
public XamlLazyValueCompletionItem(IEntity entity, string text, bool addType) |
||||
: base(entity) |
||||
{ |
||||
this.addType = addType; |
||||
this.Text = text; |
||||
this.Content = this.Text; |
||||
} |
||||
|
||||
public override void Complete(CompletionContext context) |
||||
{ |
||||
if (addType) { |
||||
MarkAsUsed(); |
||||
string newText = Entity.DeclaringType.Name + "." + Text; |
||||
context.Editor.Document.Replace(context.StartOffset, context.Length, newText); |
||||
context.EndOffset = context.StartOffset + newText.Length; |
||||
} else |
||||
base.Complete(context); |
||||
} |
||||
} |
||||
|
||||
class XamlCompletionItem : DefaultCompletionItem |
||||
{ |
||||
string prefix, @namespace, name; |
||||
|
||||
public XamlCompletionItem(string prefix, string @namespace, string name) |
||||
: base(prefix + ":" + name) |
||||
{ |
||||
this.prefix = prefix; |
||||
this.@namespace = @namespace; |
||||
this.name = name; |
||||
this.Image = ClassBrowserIconService.Namespace; |
||||
} |
||||
} |
||||
|
||||
class SpecialCompletionItem : DefaultCompletionItem |
||||
{ |
||||
public SpecialCompletionItem(string name) |
||||
: base(name) |
||||
{ |
||||
this.Image = ClassBrowserIconService.Namespace; |
||||
} |
||||
} |
||||
|
||||
class SpecialValueCompletionItem : DefaultCompletionItem |
||||
{ |
||||
public SpecialValueCompletionItem(string name) |
||||
: base(name) |
||||
{ |
||||
this.Image = ClassBrowserIconService.Const; |
||||
} |
||||
} |
||||
|
||||
class XmlnsCompletionItem : DefaultCompletionItem |
||||
{ |
||||
string @namespace, assembly; |
||||
bool isUrl; |
||||
|
||||
public bool IsUrl { |
||||
get { return isUrl; } |
||||
} |
||||
|
||||
public XmlnsCompletionItem(string @namespace, string assembly) |
||||
: base(@namespace + " (" + assembly + ")") |
||||
{ |
||||
this.@namespace = @namespace; |
||||
this.assembly = assembly; |
||||
this.Image = ClassBrowserIconService.Namespace; |
||||
} |
||||
|
||||
public XmlnsCompletionItem(string @namespace, bool isUrl) |
||||
: base(@namespace) |
||||
{ |
||||
this.@namespace = @namespace; |
||||
this.isUrl = isUrl; |
||||
this.assembly = string.Empty; |
||||
this.Image = ClassBrowserIconService.Namespace; |
||||
} |
||||
|
||||
public string Namespace { |
||||
get { return @namespace; } |
||||
} |
||||
|
||||
public string Assembly { |
||||
get { return assembly; } |
||||
} |
||||
|
||||
public override void Complete(CompletionContext context) |
||||
{ |
||||
if (isUrl) |
||||
base.Complete(context); |
||||
else { |
||||
ITextEditor editor = context.Editor; |
||||
string newText = "clr-namespace:" + @namespace; |
||||
if (!string.IsNullOrEmpty(assembly)) |
||||
newText += ";assembly=" + assembly; |
||||
editor.Document.Replace(context.StartOffset, context.Length, newText); |
||||
context.EndOffset = context.StartOffset + newText.Length; |
||||
} |
||||
} |
||||
} |
||||
|
||||
class NewEventCompletionItem : DefaultCompletionItem |
||||
{ |
||||
IEvent eventType; |
||||
|
||||
public IEvent EventType { |
||||
get { return eventType; } |
||||
} |
||||
|
||||
string targetName; |
||||
|
||||
public string TargetName { |
||||
get { return targetName; } |
||||
} |
||||
|
||||
public string HandlerName { get; private set; } |
||||
|
||||
public NewEventCompletionItem(IEvent eventType, string targetName) |
||||
: base(StringParser.Parse("${res:AddIns.XamlBinding.NewEventHandlerItem}")) |
||||
{ |
||||
this.eventType = eventType; |
||||
this.targetName = targetName; |
||||
this.HandlerName = ParseNamePattern(this.TargetName, this.EventType.Name); |
||||
this.Image = ClassBrowserIconService.Event; |
||||
} |
||||
|
||||
public override void Complete(CompletionContext context) |
||||
{ |
||||
context.Editor.Document.Replace(context.StartOffset, context.Length, this.HandlerName); |
||||
|
||||
context.EndOffset = context.StartOffset + this.HandlerName.Length; |
||||
} |
||||
|
||||
static readonly Regex namePatternRegex = new Regex("%[A-z0-9]*%", RegexOptions.Compiled); |
||||
|
||||
public static string ParseNamePattern(string objectName, string eventName) |
||||
{ |
||||
string name = XamlBindingOptions.EventHandlerNamePattern; |
||||
|
||||
while (namePatternRegex.IsMatch(name)) { |
||||
Match match = namePatternRegex.Match(name); |
||||
switch (match.Value.ToUpperInvariant()) { |
||||
case "%OBJECT%": |
||||
if (char.IsUpper(match.Value[1])) |
||||
objectName = objectName.ToUpperInvariant()[0] + objectName.Substring(1, objectName.Length - 1); |
||||
else |
||||
objectName = objectName.ToLowerInvariant()[0] + objectName.Substring(1, objectName.Length - 1); |
||||
name = name.Replace(match.Index, match.Length, objectName); |
||||
break; |
||||
case "%EVENT%": |
||||
if (char.IsUpper(match.Value[1])) |
||||
eventName = eventName.ToUpperInvariant()[0] + eventName.Substring(1, eventName.Length - 1); |
||||
else |
||||
eventName = eventName.ToLowerInvariant()[0] + eventName.Substring(1, eventName.Length - 1); |
||||
name = name.Replace(match.Index, match.Length, eventName); |
||||
break; |
||||
case "%%": |
||||
name = name.Replace(match.Index, match.Length, "%"); |
||||
break; |
||||
default: |
||||
throw new ArgumentException("Pattern identifier invalid", match.Value); |
||||
} |
||||
} |
||||
|
||||
return name; |
||||
} |
||||
} |
||||
|
||||
class MarkupExtensionInsightItem : IInsightItem |
||||
{ |
||||
IMethod ctor; |
||||
|
||||
public MarkupExtensionInsightItem(IMethod entity) |
||||
{ |
||||
if (entity == null) |
||||
throw new ArgumentNullException("entity"); |
||||
this.ctor = entity; |
||||
} |
||||
|
||||
string headerText; |
||||
bool descriptionCreated; |
||||
string description; |
||||
|
||||
public object Header { |
||||
get { |
||||
if (headerText == null) { |
||||
IAmbience ambience = AmbienceService.GetCurrentAmbience(); |
||||
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; |
||||
headerText = ambience.Convert(ctor); |
||||
headerText = headerText.Insert(headerText.LastIndexOf(')'), (ctor.Parameters.Count > 0 ? ", " : "") + "Named Parameters ..."); |
||||
} |
||||
return headerText; |
||||
} |
||||
} |
||||
|
||||
public object Content { |
||||
get { |
||||
if (!descriptionCreated) { |
||||
string entityDoc = ctor.Documentation; |
||||
if (!string.IsNullOrEmpty(entityDoc)) { |
||||
description = CodeCompletionItem.ConvertDocumentation(entityDoc); |
||||
} |
||||
descriptionCreated = true; |
||||
} |
||||
return description; |
||||
} |
||||
} |
||||
} |
||||
|
||||
class MemberInsightItem : IInsightItem |
||||
{ |
||||
string insightText; |
||||
string headerText; |
||||
string description; |
||||
bool descriptionCreated; |
||||
IMember member; |
||||
|
||||
public MemberInsightItem(IMember member, string insightText) |
||||
{ |
||||
this.member = member; |
||||
this.insightText = insightText; |
||||
} |
||||
|
||||
public object Header { |
||||
get { |
||||
if (headerText == null) { |
||||
headerText = this.member.Name + "=\"" + insightText + "\""; |
||||
} |
||||
|
||||
return headerText; |
||||
} |
||||
} |
||||
|
||||
public object Content { |
||||
get { |
||||
if (!descriptionCreated) { |
||||
string entityDoc = member.Documentation; |
||||
if (!string.IsNullOrEmpty(entityDoc)) { |
||||
description = CodeCompletionItem.ConvertDocumentation(entityDoc); |
||||
} |
||||
descriptionCreated = true; |
||||
} |
||||
return description; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,75 +0,0 @@
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Text; |
||||
using System.Xml; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.XmlEditor; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
/// <summary>
|
||||
/// Description of XamlExpressionFinder.
|
||||
/// </summary>
|
||||
public class XamlExpressionFinder : IExpressionFinder |
||||
{ |
||||
public static readonly XamlExpressionFinder Instance = new XamlExpressionFinder(); |
||||
|
||||
static bool IsValidChar(char c) |
||||
{ |
||||
return char.IsLetterOrDigit(c) || c == '_' || c == ':' || c == '.'; |
||||
} |
||||
|
||||
public ExpressionResult FindExpression(string text, int offset) |
||||
{ |
||||
int pos = offset - 1; |
||||
while (pos > 0 && IsValidChar(text[pos])) { |
||||
pos--; |
||||
} |
||||
pos++; |
||||
return new ExpressionResult(text.Substring(pos, offset - pos), GetContext(text, offset)); |
||||
} |
||||
|
||||
public ExpressionResult FindFullExpression(string text, int offset) |
||||
{ |
||||
int start = offset - 1; |
||||
while (start > 0 && IsValidChar(text[start])) { |
||||
start--; |
||||
} |
||||
start++; |
||||
while (offset < text.Length && IsValidChar(text[offset])) { |
||||
offset++; |
||||
} |
||||
|
||||
var startLocation = Utils.GetLocationInfoFromOffset(text, start); |
||||
var endLocation = Utils.GetLocationInfoFromOffset(text, offset); |
||||
|
||||
return new ExpressionResult(text.Substring(start, offset - start), GetContext(text, offset)) { Region = new DomRegion(startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column) }; |
||||
} |
||||
|
||||
public string RemoveLastPart(string expression) |
||||
{ |
||||
return ""; |
||||
} |
||||
|
||||
static ExpressionContext GetContext(string text, int offset) |
||||
{ |
||||
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(text, offset); |
||||
if (path == null || path.Elements.Count == 0) { |
||||
if (offset > 0 && text[offset - 1] == '<') |
||||
return XamlExpressionContext.Empty; |
||||
else |
||||
return ExpressionContext.Default; |
||||
} |
||||
string attributeName = XmlParser.GetAttributeNameAtIndex(text, offset); |
||||
if (!string.IsNullOrEmpty(attributeName)) { |
||||
return new XamlExpressionContext(path, attributeName, XmlParser.IsInsideAttributeValue(text, offset)); |
||||
} |
||||
else { |
||||
return new XamlExpressionContext(path, null, false); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
|
||||
using ICSharpCode.AvalonEdit.Document; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.NRefactory.Editor; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
using ICSharpCode.NRefactory.Xml; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
public sealed class XamlParsedFile : IParsedFile |
||||
{ |
||||
FileName fileName; |
||||
AXmlDocument document; |
||||
List<Error> errors; |
||||
ITypeDefinition xamlTypeDefinition; |
||||
|
||||
XamlParsedFile(FileName fileName, AXmlDocument document) |
||||
{ |
||||
this.fileName = fileName; |
||||
this.document = document; |
||||
this.errors = new List<Error>(); |
||||
} |
||||
|
||||
public static XamlParsedFile Create(FileName fileName, string fileContent, AXmlDocument document) |
||||
{ |
||||
XamlParsedFile file = new XamlParsedFile(fileName, document); |
||||
|
||||
file.errors.AddRange(document.SyntaxErrors.Select(err => new Error(ErrorType.Error, err.Description))); |
||||
|
||||
file.lastWriteTime = DateTime.UtcNow; |
||||
return file; |
||||
} |
||||
|
||||
public string FileName { |
||||
get { return fileName; } |
||||
} |
||||
|
||||
DateTime lastWriteTime = DateTime.UtcNow; |
||||
|
||||
public DateTime LastWriteTime { |
||||
get { return lastWriteTime; } |
||||
} |
||||
|
||||
public IList<IUnresolvedTypeDefinition> TopLevelTypeDefinitions { |
||||
get { |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public IList<IUnresolvedAttribute> AssemblyAttributes { |
||||
get { return EmptyList<IUnresolvedAttribute>.Instance; } |
||||
} |
||||
|
||||
public IList<IUnresolvedAttribute> ModuleAttributes { |
||||
get { return EmptyList<IUnresolvedAttribute>.Instance; } |
||||
} |
||||
|
||||
public IList<Error> Errors { |
||||
get { return errors; } |
||||
} |
||||
|
||||
public IUnresolvedTypeDefinition GetTopLevelTypeDefinition(TextLocation location) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public IUnresolvedTypeDefinition GetInnermostTypeDefinition(TextLocation location) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public IUnresolvedMember GetMember(TextLocation location) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public ITypeResolveContext GetTypeResolveContext(ICompilation compilation, TextLocation loc) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
@ -1,271 +0,0 @@
@@ -1,271 +0,0 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Xml; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.XmlEditor; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
/// <summary>
|
||||
/// Description of XamlResolver.
|
||||
/// </summary>
|
||||
public class XamlResolver : IResolver |
||||
{ |
||||
IClass callingClass; |
||||
string resolveExpression; |
||||
int caretLine, caretColumn; |
||||
XamlContext context; |
||||
|
||||
public ResolveResult Resolve(ExpressionResult expressionResult, ParseInformation parseInfo, string fileContent) |
||||
{ |
||||
if (parseInfo == null || (string.IsNullOrEmpty(fileContent) && !(expressionResult.Context is XamlContext))) |
||||
return null; |
||||
|
||||
this.resolveExpression = expressionResult.Expression; |
||||
this.caretLine = expressionResult.Region.BeginLine; |
||||
this.caretColumn = expressionResult.Region.BeginColumn; |
||||
this.callingClass = parseInfo.CompilationUnit.GetInnermostClass(caretLine, caretColumn); |
||||
this.context = expressionResult.Context as XamlContext ?? CompletionDataHelper.ResolveContext(fileContent, parseInfo.CompilationUnit.FileName, Utils.GetOffsetFromFilePos(fileContent, caretLine, caretColumn)); |
||||
|
||||
switch (this.context.Description) { |
||||
case XamlContextDescription.AtTag: |
||||
case XamlContextDescription.None: |
||||
return ResolveElementName(resolveExpression); |
||||
case XamlContextDescription.InTag: |
||||
return ResolveAttribute(resolveExpression) ?? ResolveElementName(resolveExpression); |
||||
case XamlContextDescription.InAttributeValue: |
||||
MemberResolveResult mrr = ResolveAttribute(context.Attribute.Name); |
||||
if (mrr != null) { |
||||
var rr = ResolveAttributeValue(mrr.ResolvedMember, resolveExpression) ?? mrr; |
||||
return rr; |
||||
} |
||||
break; |
||||
case XamlContextDescription.InMarkupExtension: |
||||
return ResolveMarkupExtension(resolveExpression); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
ResolveResult ResolveMarkupExtension(string expression) |
||||
{ |
||||
if (context.AttributeValue.IsString) |
||||
return null; |
||||
|
||||
object data = Utils.GetMarkupDataAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset); |
||||
|
||||
// resolve markup extension type
|
||||
if ((data as string) == expression) { |
||||
return ResolveElementName(expression + "Extension") ?? ResolveElementName(expression); |
||||
} else { |
||||
MarkupExtensionInfo info = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset); |
||||
TypeResolveResult extensionType = (ResolveElementName(info.ExtensionType + "Extension") ?? ResolveElementName(info.ExtensionType)) as TypeResolveResult; |
||||
if (extensionType != null && extensionType.ResolvedType != null) { |
||||
var value = data as AttributeValue; |
||||
|
||||
switch (extensionType.ResolvedType.FullyQualifiedName) { |
||||
case "System.Windows.Markup.StaticExtension": |
||||
case "System.Windows.Markup.TypeExtension": |
||||
if (value != null && value.IsString) { |
||||
return ResolveElementName(expression) ?? ResolveAttribute(expression); |
||||
} |
||||
goto default; // "fall through"
|
||||
default: |
||||
if (data is KeyValuePair<string, AttributeValue>) { |
||||
var pair = (KeyValuePair<string, AttributeValue>)data; |
||||
var member = ResolveNamedAttribute(pair.Key); |
||||
if (pair.Value.StartOffset + pair.Key.Length >= context.ValueStartOffset) { |
||||
return member; |
||||
} else { |
||||
if (pair.Value.IsString && member != null) |
||||
return ResolveAttributeValue(member.ResolvedMember, expression) ?? ResolveElementName(expression); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
||||
|
||||
MemberResolveResult ResolveNamedAttribute(string expression) |
||||
{ |
||||
MarkupExtensionInfo info = Utils.GetMarkupExtensionAtPosition(context.AttributeValue.ExtensionValue, context.ValueStartOffset); |
||||
TypeResolveResult extensionType = (ResolveElementName(info.ExtensionType + "Extension") ?? ResolveElementName(info.ExtensionType)) as TypeResolveResult; |
||||
|
||||
if (extensionType != null && extensionType.ResolvedType != null) { |
||||
return ResolvePropertyName(extensionType.ResolvedType, expression, false); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
ResolveResult ResolveElementName(string exp) |
||||
{ |
||||
string xmlNamespace; |
||||
string name; |
||||
|
||||
this.resolveExpression = exp; |
||||
if (resolveExpression.Contains(":")) { |
||||
string prefix = resolveExpression.Substring(0, resolveExpression.IndexOf(':')); |
||||
name = resolveExpression.Substring(resolveExpression.IndexOf(':') + 1); |
||||
if (!context.XmlnsDefinitions.TryGetValue(prefix, out xmlNamespace)) |
||||
xmlNamespace = null; |
||||
} |
||||
else { |
||||
if (!context.XmlnsDefinitions.TryGetValue("", out xmlNamespace)) |
||||
xmlNamespace = null; |
||||
name = resolveExpression; |
||||
} |
||||
if (name.Contains(".")) { |
||||
string propertyName = name.Substring(name.IndexOf('.') + 1); |
||||
name = name.Substring(0, name.IndexOf('.')); |
||||
return ResolveProperty(xmlNamespace, name, propertyName, true); |
||||
} |
||||
else { |
||||
IProjectContent pc = context.ProjectContent; |
||||
IReturnType resolvedType = XamlCompilationUnit.FindType(pc, xmlNamespace, name); |
||||
IClass resolvedClass = resolvedType != null ? resolvedType.GetUnderlyingClass() : null; |
||||
if (resolvedClass != null) { |
||||
return new TypeResolveResult(callingClass, null, resolvedClass); |
||||
} |
||||
else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
MemberResolveResult ResolveProperty(string xmlNamespace, string className, string propertyName, bool allowAttached) |
||||
{ |
||||
IProjectContent pc = context.ProjectContent; |
||||
IReturnType resolvedType = XamlCompilationUnit.FindType(pc, xmlNamespace, className); |
||||
if (resolvedType != null && resolvedType.GetUnderlyingClass() != null) { |
||||
return ResolvePropertyName(resolvedType, propertyName, allowAttached); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
MemberResolveResult ResolvePropertyName(IReturnType resolvedType, string propertyName, bool allowAttached) |
||||
{ |
||||
IMember member = resolvedType.GetProperties().Find(delegate(IProperty p) { return p.Name == propertyName; }); |
||||
if (member == null) { |
||||
member = resolvedType.GetEvents().Find(delegate(IEvent p) { return p.Name == propertyName; }); |
||||
} |
||||
if (member == null && allowAttached) { |
||||
IMethod method = resolvedType.GetMethods().Find( |
||||
delegate(IMethod p) { |
||||
return p.IsStatic && p.Parameters.Count == 1 && p.Name == "Get" + propertyName; |
||||
}); |
||||
member = method; |
||||
if (member != null) { |
||||
member = new DefaultProperty(resolvedType.GetUnderlyingClass(), propertyName) { ReturnType = method.ReturnType }; |
||||
} else { |
||||
IMethod m = resolvedType.GetMethods().Find( |
||||
delegate(IMethod p) { |
||||
return p.IsPublic && p.IsStatic && p.Parameters.Count == 2 && (p.Name == "Add" + propertyName + "Handler" || p.Name == "Remove" + propertyName + "Handler"); |
||||
}); |
||||
member = m; |
||||
if (member != null) |
||||
member = new DefaultEvent(resolvedType.GetUnderlyingClass(), propertyName) { ReturnType = m.Parameters[1].ReturnType }; |
||||
} |
||||
} |
||||
if (member != null) |
||||
return new MemberResolveResult(callingClass, null, member); |
||||
return null; |
||||
} |
||||
|
||||
MemberResolveResult ResolveAttribute(string attributeName) |
||||
{ |
||||
if (context.ActiveElement == null) { |
||||
return null; |
||||
} |
||||
string attributeXmlNamespace; |
||||
if (attributeName.Contains(":")) { |
||||
string prefix = attributeName.Substring(0, attributeName.IndexOf(':')); |
||||
if (!context.XmlnsDefinitions.TryGetValue(prefix, out attributeXmlNamespace)) |
||||
attributeXmlNamespace = null; |
||||
attributeName = attributeName.Substring(attributeName.IndexOf(':') + 1); |
||||
} |
||||
else { |
||||
if (!context.XmlnsDefinitions.TryGetValue("", out attributeXmlNamespace)) |
||||
attributeXmlNamespace = null; |
||||
} |
||||
if (attributeName.Contains(".")) { |
||||
string className = attributeName.Substring(0, attributeName.IndexOf('.')); |
||||
attributeName = attributeName.Substring(attributeName.IndexOf('.') + 1); |
||||
return ResolveProperty(attributeXmlNamespace, className, attributeName, true); |
||||
} |
||||
else { |
||||
var lastElement = context.ActiveElement; |
||||
return ResolveProperty(lastElement.Namespace, lastElement.LocalName, attributeName, false); |
||||
} |
||||
} |
||||
|
||||
ResolveResult ResolveAttributeValue(IMember propertyOrEvent, string expression) |
||||
{ |
||||
if (propertyOrEvent == null) |
||||
return null; |
||||
if (propertyOrEvent is IEvent && callingClass != null) { |
||||
return new MethodGroupResolveResult(callingClass, null, callingClass.DefaultReturnType, expression); |
||||
} else if (propertyOrEvent is IProperty && callingClass != null) { |
||||
if (propertyOrEvent.Name == "Name") { |
||||
foreach (IField f in callingClass.Fields) { |
||||
if (f.Name == expression) |
||||
return new MemberResolveResult(callingClass, null, f); |
||||
} |
||||
} |
||||
return ResolveElementName(expression); |
||||
} |
||||
|
||||
IReturnType type = propertyOrEvent.ReturnType; |
||||
if (type == null) return null; |
||||
IClass c = type.GetUnderlyingClass(); |
||||
if (c == null) return null; |
||||
|
||||
if (c.ClassType == ClassType.Enum) { |
||||
foreach (IField f in c.Fields) { |
||||
if (f.Name == expression) |
||||
return new MemberResolveResult(callingClass, null, f); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public static ResolveResult Resolve(string expression, XamlCompletionContext context) |
||||
{ |
||||
return new XamlResolver().Resolve(new ExpressionResult(expression, context), context.ParseInformation, null); |
||||
} |
||||
|
||||
public static ResolveResult Resolve(string expression, XamlContext context) |
||||
{ |
||||
return new XamlResolver().Resolve(new ExpressionResult(expression, context), context.ParseInformation, null); |
||||
} |
||||
|
||||
public static MemberResolveResult ResolveMember(string expression, XamlCompletionContext context) |
||||
{ |
||||
if (context.ParseInformation == null || string.IsNullOrEmpty(context.Editor.Document.Text)) |
||||
return null; |
||||
|
||||
var expressionResult = new ExpressionResult(expression, context); |
||||
|
||||
XamlResolver resolver = new XamlResolver(); |
||||
resolver.resolveExpression = expression; |
||||
resolver.caretLine = expressionResult.Region.BeginLine; |
||||
resolver.caretColumn = expressionResult.Region.BeginColumn; |
||||
resolver.callingClass = context.ParseInformation.CompilationUnit.GetInnermostClass(resolver.caretLine, resolver.caretColumn); |
||||
resolver.context = context; |
||||
|
||||
return resolver.ResolveNamedAttribute(expression); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop.Editor.Search; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace ICSharpCode.XamlBinding |
||||
{ |
||||
/// <summary>
|
||||
/// Description of XamlSymbolSearch.
|
||||
/// </summary>
|
||||
public class XamlSymbolSearch : ISymbolSearch |
||||
{ |
||||
public XamlSymbolSearch(IEntity entity) |
||||
{ |
||||
} |
||||
|
||||
public double WorkAmount { |
||||
get { |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
|
||||
public Task FindReferencesAsync(SymbolSearchArgs searchArguments, Action<SearchedFile> callback) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue