Browse Source

WIP on XamlBinding

newNRvisualizers
Siegfried Pammer 14 years ago
parent
commit
c8af97298b
  1. 5
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Comparers.cs
  2. 181
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompilationUnitCreatorVisitor.cs
  3. 1389
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs
  4. 59
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs
  5. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionInfo.cs
  6. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/CodeCompletion.xaml.cs
  7. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
  8. 9
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBehavior.cs
  9. 70
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj
  10. 42
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlClassReturnType.cs
  11. 743
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs
  12. 394
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs
  13. 143
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompilationUnit.cs
  14. 309
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItem.cs
  15. 334
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs
  16. 35
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs
  17. 9
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlExpressionContext.cs
  18. 75
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlExpressionFinder.cs
  19. 21
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlLanguageBinding.cs
  20. 13
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineContentHost.xaml.cs
  21. 1
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineNode.cs
  22. 97
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParsedFile.cs
  23. 190
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs
  24. 271
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs
  25. 32
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs

5
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Comparers.cs

@ -2,12 +2,11 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using ICSharpCode.SharpDevelop.Dom;
using System.Collections.Generic; using System.Collections.Generic;
namespace ICSharpCode.XamlBinding namespace ICSharpCode.XamlBinding
{ {
sealed class ParameterComparer : IEqualityComparer<IParameter> { /*sealed class ParameterComparer : IEqualityComparer<IParameter> {
public bool Equals(IParameter x, IParameter y) public bool Equals(IParameter x, IParameter y)
{ {
return x.Compare(y); return x.Compare(y);
@ -45,5 +44,5 @@ namespace ICSharpCode.XamlBinding
else else
return string.CompareOrdinal(x.Assembly, y.Assembly); return string.CompareOrdinal(x.Assembly, y.Assembly);
} }
} }*/
} }

181
src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompilationUnitCreatorVisitor.cs

@ -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);
}
}
}

1389
src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs

File diff suppressed because it is too large Load Diff

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

@ -12,10 +12,11 @@ using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Xml;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.XmlEditor; using ICSharpCode.XmlEditor;
@ -161,8 +162,9 @@ namespace ICSharpCode.XamlBinding
public static string GetWordBeforeCaretExtended(this ITextEditor editor) public static string GetWordBeforeCaretExtended(this ITextEditor editor)
{ {
IDocumentLine line = editor.Document.GetLine(editor.Caret.Line); IDocumentLine line = editor.Document.GetLine(editor.Caret.Line);
int index = Math.Min(editor.Caret.Column - 1, line.Text.Length); string lineText = editor.Document.GetText(line);
string text = line.Text.Substring(0, index); int index = Math.Min(editor.Caret.Column - 1, lineText.Length);
string text = lineText.Substring(0, index);
int startIndex = text.LastIndexOfAny(' ', '\t', '"', '=', '<', '\'', '>', '{', '}'); int startIndex = text.LastIndexOfAny(' ', '\t', '"', '=', '<', '\'', '>', '{', '}');
if (startIndex > -1) if (startIndex > -1)
return text.Substring(startIndex + 1); return text.Substring(startIndex + 1);
@ -236,12 +238,12 @@ namespace ICSharpCode.XamlBinding
return thisValue.LinePosition; return thisValue.LinePosition;
} }
public static Location GetLocation(this IXmlLineInfo thisValue) public static TextLocation GetLocation(this IXmlLineInfo thisValue)
{ {
return new Location(thisValue.GetLinePosition(), thisValue.GetLineNumber()); return new TextLocation(thisValue.GetLinePosition(), thisValue.GetLineNumber());
} }
public static bool IsInRange(this IXmlLineInfo item, Location begin, Location end) public static bool IsInRange(this IXmlLineInfo item, TextLocation begin, TextLocation end)
{ {
return IsInRange(item, begin.Line, begin.Column, end.Line, end.Column); return IsInRange(item, begin.Line, begin.Column, end.Line, end.Column);
} }
@ -261,41 +263,21 @@ namespace ICSharpCode.XamlBinding
return false; return false;
} }
public static bool IsCollectionType(this IClass thisValue) public static bool IsCollectionType(this IType thisValue)
{ {
if (thisValue == null) if (thisValue == null)
throw new ArgumentNullException("thisValue"); throw new ArgumentNullException("thisValue");
return thisValue.ClassInheritanceTree.Any(cla => cla.FullyQualifiedName == "System.Collections.ICollection"); return thisValue.GetAllBaseTypeDefinitions().Any(t => t.FullName == "System.Collections.ICollection");
} }
public static bool IsCollectionReturnType(this IReturnType type) public static bool IsListType(this IType thisValue)
{
if (type == null)
throw new ArgumentNullException("type");
if (type.GetUnderlyingClass() != null)
return type.GetUnderlyingClass().IsCollectionType();
return false;
}
public static bool IsListType(this IClass thisValue)
{ {
if (thisValue == null) if (thisValue == null)
throw new ArgumentNullException("thisValue"); throw new ArgumentNullException("thisValue");
return thisValue.ClassInheritanceTree.Any(cla => cla.FullyQualifiedName == "System.Collections.IList"); return thisValue.GetAllBaseTypeDefinitions().Any(t => t.FullName == "System.Collections.IList");
} }
public static bool IsListReturnType(this IReturnType type) public static bool HasAttached(this ITypeDefinition thisValue, bool lookForProperties, bool lookForEvents)
{
if (type == null)
throw new ArgumentNullException("type");
if (type.GetUnderlyingClass() != null)
return type.GetUnderlyingClass().IsListType();
return false;
}
public static bool HasAttached(this IClass thisValue, bool lookForProperties, bool lookForEvents)
{ {
if (!lookForProperties && !lookForEvents) if (!lookForProperties && !lookForEvents)
return false; return false;
@ -310,12 +292,12 @@ namespace ICSharpCode.XamlBinding
public static bool IsAttached(this IField field, bool lookForProperties, bool lookForEvents) public static bool IsAttached(this IField field, bool lookForProperties, bool lookForEvents)
{ {
if (!field.IsPublic || !field.IsStatic || !field.IsReadonly || field.ReturnType == null) if (!field.IsPublic || !field.IsStatic || !field.IsReadOnly || field.ReturnType == null)
return false; return false;
bool foundMethod = false; bool foundMethod = false;
if (lookForProperties && field.ReturnType.FullyQualifiedName == "System.Windows.DependencyProperty") { if (lookForProperties && field.ReturnType.FullName == "System.Windows.DependencyProperty") {
if (field.Name.Length <= "Property".Length) if (field.Name.Length <= "Property".Length)
return false; return false;
if (!field.Name.EndsWith("Property", StringComparison.Ordinal)) if (!field.Name.EndsWith("Property", StringComparison.Ordinal))
@ -323,7 +305,7 @@ namespace ICSharpCode.XamlBinding
string fieldName = field.Name.Remove(field.Name.Length - "Property".Length); string fieldName = field.Name.Remove(field.Name.Length - "Property".Length);
foreach (IMethod method in field.DeclaringType.Methods) { foreach (IMethod method in field.DeclaringTypeDefinition.Methods) {
if (!method.IsPublic || !method.IsStatic || method.Name.Length <= 3) if (!method.IsPublic || !method.IsStatic || method.Name.Length <= 3)
continue; continue;
if (!method.Name.StartsWith("Get") && !method.Name.StartsWith("Set")) if (!method.Name.StartsWith("Get") && !method.Name.StartsWith("Set"))
@ -334,7 +316,7 @@ namespace ICSharpCode.XamlBinding
} }
} }
if (lookForEvents && !foundMethod && field.ReturnType.FullyQualifiedName == "System.Windows.RoutedEvent") { if (lookForEvents && !foundMethod && field.ReturnType.FullName == "System.Windows.RoutedEvent") {
if (field.Name.Length <= "Event".Length) if (field.Name.Length <= "Event".Length)
return false; return false;
if (!field.Name.EndsWith("Event", StringComparison.Ordinal)) if (!field.Name.EndsWith("Event", StringComparison.Ordinal))
@ -347,9 +329,10 @@ namespace ICSharpCode.XamlBinding
} }
/// <remarks>Works only if fullyQualifiedClassName is the name of a class!</remarks> /// <remarks>Works only if fullyQualifiedClassName is the name of a class!</remarks>
public static bool DerivesFrom(this IClass myClass, string fullyQualifiedClassName) public static bool DerivesFrom(this ITypeDefinition myClass, string fullyQualifiedClassName)
{ {
return myClass.ClassInheritanceTreeClassesOnly.Any(c => c.FullyQualifiedName == fullyQualifiedClassName); // return myClass.ClassInheritanceTreeClassesOnly.Any(c => c.FullyQualifiedName == fullyQualifiedClassName);
return false;
} }
public static T PopOrDefault<T>(this Stack<T> stack) public static T PopOrDefault<T>(this Stack<T> stack)

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

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.XmlEditor; using ICSharpCode.XmlEditor;
using System.Text; using System.Text;

2
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/CodeCompletion.xaml.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.XamlBinding.Options
public override bool SaveOptions() public override bool SaveOptions()
{ {
if (base.SaveOptions()) { if (base.SaveOptions()) {
XamlColorizer.RefreshAll(); // XamlColorizer.RefreshAll();
return true; return true;
} }

4
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs

@ -69,12 +69,12 @@ namespace ICSharpCode.XamlBinding
return offset + col; return offset + col;
} }
public static Location GetLocationInfoFromOffset(string text, int offset) public static TextLocation GetLocationInfoFromOffset(string text, int offset)
{ {
string[] lines = text.Substring(0, MinMax(offset, 0, text.Length)).Split('\n'); string[] lines = text.Substring(0, MinMax(offset, 0, text.Length)).Split('\n');
string line = lines.LastOrDefault() ?? string.Empty; string line = lines.LastOrDefault() ?? string.Empty;
return new Location(line.Length + 1, lines.Length); return new TextLocation(line.Length + 1, lines.Length);
} }
/// <summary> /// <summary>

9
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBehavior.cs

@ -7,11 +7,11 @@ using System.IO;
using System.Linq; using System.Linq;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.XamlBinding namespace ICSharpCode.XamlBinding
{ {
@ -24,6 +24,11 @@ namespace ICSharpCode.XamlBinding
return base.GetDefaultItemType(fileName); return base.GetDefaultItemType(fileName);
} }
public override ISymbolSearch PrepareSymbolSearch(IEntity entity)
{
return new XamlSymbolSearch(entity);
}
} }
public class SilverlightBehavior : ProjectBehavior public class SilverlightBehavior : ProjectBehavior

70
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj

@ -64,17 +64,17 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="XamlParsedFile.cs" />
<Compile Include="XamlSymbolSearch.cs" />
<None Include="XamlBinding.addin"> <None Include="XamlBinding.addin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<Compile Include="..\..\..\..\Main\GlobalAssemblyInfo.cs"> <Compile Include="..\..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link> <Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="CompilationUnitCreatorVisitor.cs" />
<Compile Include="Comparers.cs" /> <Compile Include="Comparers.cs" />
<Compile Include="MarkupExtensionInfo.cs" /> <Compile Include="MarkupExtensionInfo.cs" />
<Compile Include="MarkupExtensionParser.cs" /> <Compile Include="MarkupExtensionParser.cs" />
<Compile Include="CompletionDataHelper.cs" />
<Compile Include="Extensions.cs" /> <Compile Include="Extensions.cs" />
<Compile Include="MarkupExtensionTokenizer.cs" /> <Compile Include="MarkupExtensionTokenizer.cs" />
<Compile Include="MarkupExtensionToken.cs"> <Compile Include="MarkupExtensionToken.cs">
@ -87,41 +87,6 @@
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Options\XamlBindingOptions.cs" /> <Compile Include="Options\XamlBindingOptions.cs" />
<Compile Include="PowerToys\Commands\CreateBusinessFormCommand.cs" />
<Compile Include="PowerToys\Commands\CreateBusinessFormFromClassCommand.cs" />
<Compile Include="PowerToys\Commands\EditGridColumnsAndRowsCommand.cs" />
<Compile Include="PowerToys\Commands\ExtractPropertiesAsStyleCommand.cs" />
<Compile Include="PowerToys\Commands\GroupIntoRefactorings.cs" />
<Compile Include="PowerToys\Commands\PropertyEntry.cs" />
<Compile Include="PowerToys\Commands\RemoveMarginCommand.cs" />
<Compile Include="PowerToys\Commands\RemoveUnnecessaryAttributesCommand.cs" />
<Compile Include="PowerToys\Dialogs\DragDropMarkerAdorner.cs" />
<Compile Include="PowerToys\Dialogs\EditGridColumnsAndRowsDialog.xaml.cs">
<DependentUpon>EditGridColumnsAndRowsDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="PowerToys\Dialogs\ExtractPropertiesAsStyleDialog.xaml.cs">
<DependentUpon>ExtractPropertiesAsStyleDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="PowerToys\Dialogs\FieldEditor.xaml.cs">
<DependentUpon>FieldEditor.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="PowerToys\Dialogs\GridLengthEditor.xaml.cs">
<DependentUpon>GridLengthEditor.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="PowerToys\Dialogs\SelectSourceClassDialog.xaml.cs">
<DependentUpon>SelectSourceClassDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="PowerToys\Dialogs\SourceClassFormEditor.xaml.cs">
<DependentUpon>SourceClassFormEditor.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="PowerToys\Dialogs\UndoStep.cs" />
<Compile Include="PowerToys\XamlMenuCommand.cs" />
<Compile Include="PropertyPathParser.cs" /> <Compile Include="PropertyPathParser.cs" />
<Compile Include="PropertyPathSegment.cs" /> <Compile Include="PropertyPathSegment.cs" />
<Compile Include="PropertyPathTokenizer.cs" /> <Compile Include="PropertyPathTokenizer.cs" />
@ -131,17 +96,11 @@
</Compile> </Compile>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XamlBehavior.cs" /> <Compile Include="XamlBehavior.cs" />
<Compile Include="XamlClassReturnType.cs" />
<Compile Include="XamlCodeCompletionBinding.cs" /> <Compile Include="XamlCodeCompletionBinding.cs" />
<Compile Include="XamlCompilationUnit.cs" />
<Compile Include="XamlCompletionItem.cs" />
<Compile Include="XamlCompletionItemList.cs" /> <Compile Include="XamlCompletionItemList.cs" />
<Compile Include="XamlCompletionSettings.cs" /> <Compile Include="XamlCompletionSettings.cs" />
<Compile Include="XamlContext.cs" /> <Compile Include="XamlContext.cs" />
<Compile Include="XamlExpressionContext.cs" /> <Compile Include="XamlExpressionContext.cs" />
<Compile Include="XamlExpressionFinder.cs">
</Compile>
<Compile Include="XamlColorizer.cs" />
<Compile Include="MarkupExtensionParseException.cs"> <Compile Include="MarkupExtensionParseException.cs">
</Compile> </Compile>
<Compile Include="XamlLanguageBinding.cs" /> <Compile Include="XamlLanguageBinding.cs" />
@ -151,7 +110,16 @@
</Compile> </Compile>
<Compile Include="XamlOutlineNode.cs" /> <Compile Include="XamlOutlineNode.cs" />
<Compile Include="XamlParser.cs" /> <Compile Include="XamlParser.cs" />
<Compile Include="XamlResolver.cs" /> <ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.Xml\ICSharpCode.NRefactory.Xml.csproj">
<Project>{DC393B66-92ED-4CAD-AB25-CFEF23F3D7C6}</Project>
<Name>ICSharpCode.NRefactory.Xml</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\Project\NRefactory.csproj"> <ProjectReference Include="..\..\..\..\Libraries\NRefactory\Project\NRefactory.csproj">
<Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project> <Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project>
<Name>NRefactory</Name> <Name>NRefactory</Name>
@ -177,11 +145,6 @@
<Name>ICSharpCode.Core.Presentation</Name> <Name>ICSharpCode.Core.Presentation</Name>
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj">
<Project>{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}</Project>
<Name>ICSharpCode.SharpDevelop.Dom</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj"> <ProjectReference Include="..\..\..\..\Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj">
<Project>{8035765F-D51F-4A0C-A746-2FD100E19419}</Project> <Project>{8035765F-D51F-4A0C-A746-2FD100E19419}</Project>
<Name>ICSharpCode.SharpDevelop.Widgets</Name> <Name>ICSharpCode.SharpDevelop.Widgets</Name>
@ -204,19 +167,10 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="PowerToys" />
<Folder Include="Options" /> <Folder Include="Options" />
<Folder Include="PowerToys\Commands" />
<Folder Include="PowerToys\Dialogs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Options\CodeCompletion.xaml" /> <Page Include="Options\CodeCompletion.xaml" />
<Page Include="PowerToys\Dialogs\EditGridColumnsAndRowsDialog.xaml" />
<Page Include="PowerToys\Dialogs\ExtractPropertiesAsStyleDialog.xaml" />
<Page Include="PowerToys\Dialogs\FieldEditor.xaml" />
<Page Include="PowerToys\Dialogs\GridLengthEditor.xaml" />
<Page Include="PowerToys\Dialogs\SelectSourceClassDialog.xaml" />
<Page Include="PowerToys\Dialogs\SourceClassFormEditor.xaml" />
<Page Include="XamlOutlineContentHost.xaml" /> <Page Include="XamlOutlineContentHost.xaml" />
</ItemGroup> </ItemGroup>
</Project> </Project>

42
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlClassReturnType.cs

@ -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; }
}
}
}

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

@ -4,7 +4,7 @@
using ICSharpCode.XmlEditor; using ICSharpCode.XmlEditor;
using System; using System;
using System.Linq; using System.Linq;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
@ -16,384 +16,389 @@ namespace ICSharpCode.XamlBinding
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
{ {
XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ch); // XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ch);
XamlCompletionItemList list; // XamlCompletionItemList list;
//
if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData) // if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData)
return CodeCompletionKeyPressResult.None; // return CodeCompletionKeyPressResult.None;
//
switch (ch) { // switch (ch) {
case '<': // case '<':
context.Description = (context.Description == XamlContextDescription.None) ? XamlContextDescription.AtTag : context.Description; // context.Description = (context.Description == XamlContextDescription.None) ? XamlContextDescription.AtTag : context.Description;
list = CompletionDataHelper.CreateListForContext(context); // list = CompletionDataHelper.CreateListForContext(context);
editor.ShowCompletionWindow(list); // editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed; // return CodeCompletionKeyPressResult.Completed;
case '>': // case '>':
return CodeCompletionKeyPressResult.None; // return CodeCompletionKeyPressResult.None;
case '\'': // case '\'':
case '"': // case '"':
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { // if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
// count all " or ' chars before the next > char // // count all " or ' chars before the next > char
int search = editor.Caret.Offset + 1; // int search = editor.Caret.Offset + 1;
int endMarkerCount = 1; // int endMarkerCount = 1;
char curCh = editor.Document.GetCharAt(search); // char curCh = editor.Document.GetCharAt(search);
while (search < editor.Document.TextLength - 1 && curCh != '>') { // while (search < editor.Document.TextLength - 1 && curCh != '>') {
if (curCh == ch) // if (curCh == ch)
endMarkerCount++; // endMarkerCount++;
search++; // search++;
curCh = editor.Document.GetCharAt(search); // curCh = editor.Document.GetCharAt(search);
} // }
// if the count is odd we need to add an additional " or ' char // // if the count is odd we need to add an additional " or ' char
if (endMarkerCount % 2 != 0) { // if (endMarkerCount % 2 != 0) {
editor.Document.Insert(editor.Caret.Offset, ch.ToString()); // editor.Document.Insert(editor.Caret.Offset, ch.ToString());
editor.Caret.Offset--; // editor.Caret.Offset--;
this.CtrlSpace(editor); // this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.Completed; // return CodeCompletionKeyPressResult.Completed;
} // }
} // }
break; // break;
case '{': // starting point for Markup Extension Completion // case '{': // starting point for Markup Extension Completion
if (context.Attribute != null // if (context.Attribute != null
&& XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) // && XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)
&& !(context.RawAttributeValue.StartsWith("{}", StringComparison.OrdinalIgnoreCase) && context.RawAttributeValue.Length != 2)) { // && !(context.RawAttributeValue.StartsWith("{}", StringComparison.OrdinalIgnoreCase) && context.RawAttributeValue.Length != 2)) {
//
if (editor.SelectionLength != 0) // if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); // editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
editor.Document.Insert(editor.Caret.Offset, "{}"); // editor.Document.Insert(editor.Caret.Offset, "{}");
editor.Caret.Offset--; // editor.Caret.Offset--;
//
this.CtrlSpace(editor); // this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey; // return CodeCompletionKeyPressResult.EatKey;
} // }
break; // break;
case '.': // case '.':
switch (context.Description) { // switch (context.Description) {
case XamlContextDescription.AtTag: // case XamlContextDescription.AtTag:
case XamlContextDescription.InTag: // case XamlContextDescription.InTag:
if (context.ActiveElement != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { // if (context.ActiveElement != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
list = CompletionDataHelper.CreateListForContext(context); // list = CompletionDataHelper.CreateListForContext(context);
editor.ShowCompletionWindow(list); // editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed; // return CodeCompletionKeyPressResult.Completed;
} // }
break; // break;
case XamlContextDescription.InMarkupExtension: // case XamlContextDescription.InMarkupExtension:
if (DoMarkupExtensionCompletion(context)) //// if (DoMarkupExtensionCompletion(context))
return CodeCompletionKeyPressResult.Completed; //// return CodeCompletionKeyPressResult.Completed;
break; // break;
case XamlContextDescription.InAttributeValue: // case XamlContextDescription.InAttributeValue:
if (editor.SelectionLength != 0) // if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); // editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
editor.Document.Insert(editor.Caret.Offset, "."); // editor.Document.Insert(editor.Caret.Offset, ".");
//
this.CtrlSpace(editor); // this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey; // return CodeCompletionKeyPressResult.EatKey;
} // }
break; // break;
case '(': // case '(':
case '[': // case '[':
if (context.Description == XamlContextDescription.InAttributeValue) { // if (context.Description == XamlContextDescription.InAttributeValue) {
if (editor.SelectionLength != 0) // if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); // editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
if (ch == '(') // if (ch == '(')
editor.Document.Insert(editor.Caret.Offset, "()"); // editor.Document.Insert(editor.Caret.Offset, "()");
if (ch == '[') // if (ch == '[')
editor.Document.Insert(editor.Caret.Offset, "[]"); // editor.Document.Insert(editor.Caret.Offset, "[]");
editor.Caret.Offset--; // editor.Caret.Offset--;
//
this.CtrlSpace(editor); // this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey; // return CodeCompletionKeyPressResult.EatKey;
} // }
break; // break;
case ':': // case ':':
if (context.ActiveElement != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) { // if (context.ActiveElement != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) {
if (context.Attribute != null && !context.Attribute.Name.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { // if (context.Attribute != null && !context.Attribute.Name.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) {
list = CompletionDataHelper.CreateListForContext(context); // list = CompletionDataHelper.CreateListForContext(context);
list.PreselectionLength = editor.GetWordBeforeCaretExtended().Length; // list.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
editor.ShowCompletionWindow(list); // editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion; // return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
} // }
} // }
break; // break;
case '/': // ignore '/' when trying to type '/>' // case '/': // ignore '/' when trying to type '/>'
return CodeCompletionKeyPressResult.None; // return CodeCompletionKeyPressResult.None;
case '=': // case '=':
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { // if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
int searchOffset = editor.Caret.Offset; // int searchOffset = editor.Caret.Offset;
//
if (editor.SelectionLength != 0) // if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength); // editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
while (searchOffset < editor.Document.TextLength - 1) { // while (searchOffset < editor.Document.TextLength - 1) {
searchOffset++; // searchOffset++;
if (!char.IsWhiteSpace(editor.Document.GetCharAt(searchOffset))) // if (!char.IsWhiteSpace(editor.Document.GetCharAt(searchOffset)))
break; // break;
} // }
//
if (searchOffset >= editor.Document.TextLength || editor.Document.GetCharAt(searchOffset) != '"') { // if (searchOffset >= editor.Document.TextLength || editor.Document.GetCharAt(searchOffset) != '"') {
editor.Document.Insert(editor.Caret.Offset, "=\"\""); // editor.Document.Insert(editor.Caret.Offset, "=\"\"");
editor.Caret.Offset--; // editor.Caret.Offset--;
} else { // } else {
editor.Document.Insert(editor.Caret.Offset, "="); // editor.Document.Insert(editor.Caret.Offset, "=");
editor.Caret.Offset++; // editor.Caret.Offset++;
} // }
//
this.CtrlSpace(editor); // this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey; // return CodeCompletionKeyPressResult.EatKey;
} else { // } else {
DoMarkupExtensionCompletion(context); //// DoMarkupExtensionCompletion(context);
return CodeCompletionKeyPressResult.Completed; // return CodeCompletionKeyPressResult.Completed;
} // }
default: // default:
if (context.Description != XamlContextDescription.None && !char.IsWhiteSpace(ch)) { // if (context.Description != XamlContextDescription.None && !char.IsWhiteSpace(ch)) {
string starter = editor.GetWordBeforeCaretExtended(); // string starter = editor.GetWordBeforeCaretExtended();
if (!string.IsNullOrEmpty(starter)) // if (!string.IsNullOrEmpty(starter))
return CodeCompletionKeyPressResult.None; // return CodeCompletionKeyPressResult.None;
trackForced = false; // trackForced = false;
//
string attributeName = (context.Attribute != null) ? context.Attribute.Name : string.Empty; // string attributeName = (context.Attribute != null) ? context.Attribute.Name : string.Empty;
//
if (!attributeName.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) { // if (!attributeName.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) {
return this.CtrlSpace(editor) // return this.CtrlSpace(editor)
? CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion // ? CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion
: CodeCompletionKeyPressResult.None; // : CodeCompletionKeyPressResult.None;
} // }
trackForced = true; // trackForced = true;
return CodeCompletionKeyPressResult.None; // return CodeCompletionKeyPressResult.None;
} // }
break; // break;
} // }
//
return CodeCompletionKeyPressResult.None; return CodeCompletionKeyPressResult.None;
} }
public bool CtrlSpace(ITextEditor editor) public bool CtrlSpace(ITextEditor editor)
{ {
XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ' '); // XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ' ');
context.Forced = trackForced; // context.Forced = trackForced;
//
if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData) // if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData)
return false; // return false;
//
if (context.ActiveElement != null) { // if (context.ActiveElement != null) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && context.Description != XamlContextDescription.InAttributeValue) { // if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && context.Description != XamlContextDescription.InAttributeValue) {
XamlCompletionItemList list = CompletionDataHelper.CreateListForContext(context); // XamlCompletionItemList list = CompletionDataHelper.CreateListForContext(context);
string starter = editor.GetWordBeforeCaretExtended().TrimStart('/'); // string starter = editor.GetWordBeforeCaretExtended().TrimStart('/');
if (context.Description != XamlContextDescription.None && !string.IsNullOrEmpty(starter)) { // if (context.Description != XamlContextDescription.None && !string.IsNullOrEmpty(starter)) {
if (starter.Contains(".")) // if (starter.Contains("."))
list.PreselectionLength = starter.Length - starter.IndexOf('.') - 1; // list.PreselectionLength = starter.Length - starter.IndexOf('.') - 1;
else // else
list.PreselectionLength = starter.Length; // list.PreselectionLength = starter.Length;
} // }
editor.ShowCompletionWindow(list); // editor.ShowCompletionWindow(list);
return true; // return true;
} else { // } else {
// DO NOT USE CompletionDataHelper.CreateListForContext here!!! results in endless recursion!!!! // // DO NOT USE CompletionDataHelper.CreateListForContext here!!! results in endless recursion!!!!
if (context.Attribute != null) { // if (context.Attribute != null) {
if (!DoMarkupExtensionCompletion(context)) { // if (!DoMarkupExtensionCompletion(context)) {
var completionList = new XamlCompletionItemList(context); // var completionList = new XamlCompletionItemList(context);
completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length; // completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
//
if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") && // if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") &&
(context.Attribute.Name == "Property" || context.Attribute.Name == "Value")) // (context.Attribute.Name == "Property" || context.Attribute.Name == "Value"))
DoSetterAndEventSetterCompletion(context, completionList); // DoSetterAndEventSetterCompletion(context, completionList);
else if ((context.ActiveElement.Name.EndsWith("Trigger") || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value") // else if ((context.ActiveElement.Name.EndsWith("Trigger") || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value")
DoTriggerCompletion(context, completionList); // DoTriggerCompletion(context, completionList);
else { // else {
if (context.Attribute.Name == "xml:space") { // if (context.Attribute.Name == "xml:space") {
completionList.Items.AddRange(new[] { new SpecialCompletionItem("preserve"), // completionList.Items.AddRange(new[] { new SpecialCompletionItem("preserve"),
new SpecialCompletionItem("default") }); // new SpecialCompletionItem("default") });
} // }
//
var mrr = XamlResolver.Resolve(context.Attribute.Name, context) as MemberResolveResult; // var mrr = XamlResolver.Resolve(context.Attribute.Name, context) as MemberResolveResult;
if (mrr != null && mrr.ResolvedType != null) { // if (mrr != null && mrr.ResolvedType != null) {
completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(context, mrr.ResolvedType, string.Empty)); // completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(context, mrr.ResolvedType, string.Empty));
editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr)); // editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr));
if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.PropertyPath") { // if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.PropertyPath") {
string start = editor.GetWordBeforeCaretExtended(); // string start = editor.GetWordBeforeCaretExtended();
int index = start.LastIndexOfAny(PropertyPathTokenizer.ControlChars); // int index = start.LastIndexOfAny(PropertyPathTokenizer.ControlChars);
if (index + 1 < start.Length) // if (index + 1 < start.Length)
start = start.Substring(index + 1); // start = start.Substring(index + 1);
else // else
start = ""; // start = "";
completionList.PreselectionLength = start.Length; // completionList.PreselectionLength = start.Length;
} else if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.Media.FontFamily") { // } else if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.Media.FontFamily") {
string text = context.ValueStartOffset > -1 ? context.RawAttributeValue.Substring(0, Math.Min(context.ValueStartOffset, context.RawAttributeValue.Length)) : ""; // string text = context.ValueStartOffset > -1 ? context.RawAttributeValue.Substring(0, Math.Min(context.ValueStartOffset, context.RawAttributeValue.Length)) : "";
int lastComma = text.LastIndexOf(','); // int lastComma = text.LastIndexOf(',');
completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset : context.ValueStartOffset - lastComma - 1; // completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset : context.ValueStartOffset - lastComma - 1;
} // }
} // }
} // }
//
completionList.SortItems(); // completionList.SortItems();
//
if (context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) || // if (context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) // context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase))
completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(context.ProjectContent)); // completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(context.ProjectContent));
//
ICompletionListWindow window = editor.ShowCompletionWindow(completionList); // ICompletionListWindow window = editor.ShowCompletionWindow(completionList);
//
if ((context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) || // if ((context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) && window != null) // context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) && window != null)
window.Width = 400; // window.Width = 400;
//
return completionList.Items.Any(); // return completionList.Items.Any();
} // }
return true; // return true;
} // }
} // }
} // }
return false; return false;
} }
static void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { // static void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
bool isExplicit; // bool isExplicit;
AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? string.Empty); // AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? string.Empty);
//
IReturnType typeName = null; // IType typeName = null;
string typeNameString = null; // string typeNameString = null;
//
if (!value.IsString) { // if (!value.IsString) {
typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context); // typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context);
typeName = CompletionDataHelper.ResolveType(typeNameString, context); // typeName = CompletionDataHelper.ResolveType(typeNameString, context);
} else { // } else {
typeNameString = value.StringValue; // typeNameString = value.StringValue;
typeName = CompletionDataHelper.ResolveType(value.StringValue, context); // typeName = CompletionDataHelper.ResolveType(value.StringValue, context);
} // }
//
if (typeName != null) { // if (typeName != null) {
switch (context.Attribute.Name) { // switch (context.Attribute.Name) {
case "Value": // case "Value":
AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? ""); // AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? "");
if (!propType.IsString) // if (!propType.IsString)
break; // break;
//
string name = propType.StringValue; // string name = propType.StringValue;
//
if (!name.Contains(".")) // if (!name.Contains("."))
name = typeNameString + "." + name; // name = typeNameString + "." + name;
//
context.Description = XamlContextDescription.AtTag; // context.Description = XamlContextDescription.AtTag;
//
var member = XamlResolver.Resolve(name, context) as MemberResolveResult; // var member = XamlResolver.Resolve(name, context) as MemberResolveResult;
//
if (member == null || member.ResolvedMember == null) // if (member == null || member.ResolvedMember == null)
break; // break;
//
completionList.Items.AddRange( // completionList.Items.AddRange(
CompletionDataHelper.MemberCompletion(context, member.ResolvedMember.ReturnType, string.Empty) // CompletionDataHelper.MemberCompletion(context, member.ResolvedMember.ReturnType, string.Empty)
); // );
break; // break;
} // }
} // }
} // }
//
// static void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
// bool isExplicit;
// string element = context.ParentElement.Name.EndsWith("Trigger") ? "Trigger" : context.ParentElement.Name;
// AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, element) ?? string.Empty);
//
// IType typeName = null;
// string typeNameString = null;
//
// if (!value.IsString) {
// typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context);
// typeName = CompletionDataHelper.ResolveType(typeNameString, context);
// } else {
// typeNameString = value.StringValue;
// typeName = CompletionDataHelper.ResolveType(value.StringValue, context);
// }
//
// if (typeName != null) {
// switch (context.Attribute.Name) {
// case "Value":
// AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? "");
//
// if (!propType.IsString)
// break;
//
// context.Description = XamlContextDescription.AtTag;
//
// string name = propType.StringValue;
//
// if (!name.Contains("."))
// name = typeNameString + "." + name;
//
// var member = XamlResolver.Resolve(name, context) as MemberResolveResult;
//
// if (member == null || member.ResolvedMember == null)
// break;
//
// completionList.Items.AddRange(
// CompletionDataHelper.MemberCompletion(context, member.ResolvedMember.ReturnType, string.Empty)
// );
// break;
// case "Property":
// completionList.Items.AddRange(
// typeName.GetProperties()
// .Where(p => p.IsPublic && p.CanSet)
// .Select(prop => new XamlCodeCompletionItem(prop))
// );
// break;
// case "Event":
// completionList.Items.AddRange(
// typeName.GetEvents()
// .Where(e => e.IsPublic)
// .Select(evt => new XamlCodeCompletionItem(evt))
// );
// break;
// case "Handler":
// var loc3 = context.Editor.Document.OffsetToPosition(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset));
// AttributeValue evtType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Event") ?? "");
// if (!evtType.IsString)
// break;
//
// string evtName = evtType.StringValue;
//
// if (!evtName.Contains("."))
// evtName = typeNameString + "." + evtName;
//
// var evtMember = XamlResolver.Resolve(evtName, context) as MemberResolveResult;
//
// if (evtMember == null || evtMember.ResolvedMember == null || !(evtMember.ResolvedMember is IEvent) || evtMember.ResolvedMember.ReturnType == null)
// break;
//
// IClass c = (evtMember.ResolvedMember as IEvent).ReturnType.GetUnderlyingClass();
//
// if (c == null)
// break;
//
// IMethod invoker = c.Methods.FirstOrDefault(m => m.Name == "Invoke");
//
// if (invoker == null)
// break;
//
// completionList.Items.AddRange(
// CompletionDataHelper.AddMatchingEventHandlers(context, invoker).Add(new NewEventCompletionItem(evtMember.ResolvedMember as IEvent, typeName.Name))
// );
// break;
// }
// }
// }
//
// static bool DoMarkupExtensionCompletion(XamlCompletionContext context)
// {
// if (context.Description == XamlContextDescription.InMarkupExtension && context.AttributeValue != null && !context.AttributeValue.IsString) {
// if (!XamlBindingOptions.UseExtensionCompletion)
// return false;
// XamlCompletionItemList completionList = CompletionDataHelper.CreateMarkupExtensionCompletion(context) as XamlCompletionItemList;
// string word = context.Editor.GetWordBeforeCaretExtended();
// if (context.PressedKey != '.' && context.PressedKey != '=' && !word.EndsWith(".") && completionList.PreselectionLength == 0)
// completionList.PreselectionLength = word.Length;
// var insightList = CompletionDataHelper.CreateMarkupExtensionInsight(context);
// context.Editor.ShowInsightWindow(insightList);
// context.Editor.ShowCompletionWindow(completionList);
// return completionList.Items.Any() || insightList.Any();
// }
//
// return false;
// }
static void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) { public bool HandleKeyPressed(ITextEditor editor, char ch)
bool isExplicit;
string element = context.ParentElement.Name.EndsWith("Trigger") ? "Trigger" : context.ParentElement.Name;
AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, element) ?? string.Empty);
IReturnType typeName = null;
string typeNameString = null;
if (!value.IsString) {
typeNameString = CompletionDataHelper.GetTypeNameFromTypeExtension(value.ExtensionValue, context);
typeName = CompletionDataHelper.ResolveType(typeNameString, context);
} else {
typeNameString = value.StringValue;
typeName = CompletionDataHelper.ResolveType(value.StringValue, context);
}
if (typeName != null) {
switch (context.Attribute.Name) {
case "Value":
AttributeValue propType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Property") ?? "");
if (!propType.IsString)
break;
context.Description = XamlContextDescription.AtTag;
string name = propType.StringValue;
if (!name.Contains("."))
name = typeNameString + "." + name;
var member = XamlResolver.Resolve(name, context) as MemberResolveResult;
if (member == null || member.ResolvedMember == null)
break;
completionList.Items.AddRange(
CompletionDataHelper.MemberCompletion(context, member.ResolvedMember.ReturnType, string.Empty)
);
break;
case "Property":
completionList.Items.AddRange(
typeName.GetProperties()
.Where(p => p.IsPublic && p.CanSet)
.Select(prop => new XamlCodeCompletionItem(prop))
);
break;
case "Event":
completionList.Items.AddRange(
typeName.GetEvents()
.Where(e => e.IsPublic)
.Select(evt => new XamlCodeCompletionItem(evt))
);
break;
case "Handler":
var loc3 = context.Editor.Document.OffsetToPosition(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset));
AttributeValue evtType = MarkupExtensionParser.ParseValue(context.ActiveElement.GetAttributeValue("Event") ?? "");
if (!evtType.IsString)
break;
string evtName = evtType.StringValue;
if (!evtName.Contains("."))
evtName = typeNameString + "." + evtName;
var evtMember = XamlResolver.Resolve(evtName, context) as MemberResolveResult;
if (evtMember == null || evtMember.ResolvedMember == null || !(evtMember.ResolvedMember is IEvent) || evtMember.ResolvedMember.ReturnType == null)
break;
IClass c = (evtMember.ResolvedMember as IEvent).ReturnType.GetUnderlyingClass();
if (c == null)
break;
IMethod invoker = c.Methods.FirstOrDefault(m => m.Name == "Invoke");
if (invoker == null)
break;
completionList.Items.AddRange(
CompletionDataHelper.AddMatchingEventHandlers(context, invoker).Add(new NewEventCompletionItem(evtMember.ResolvedMember as IEvent, typeName.Name))
);
break;
}
}
}
static bool DoMarkupExtensionCompletion(XamlCompletionContext context)
{ {
if (context.Description == XamlContextDescription.InMarkupExtension && context.AttributeValue != null && !context.AttributeValue.IsString) { throw new NotImplementedException();
if (!XamlBindingOptions.UseExtensionCompletion)
return false;
XamlCompletionItemList completionList = CompletionDataHelper.CreateMarkupExtensionCompletion(context) as XamlCompletionItemList;
string word = context.Editor.GetWordBeforeCaretExtended();
if (context.PressedKey != '.' && context.PressedKey != '=' && !word.EndsWith(".") && completionList.PreselectionLength == 0)
completionList.PreselectionLength = word.Length;
var insightList = CompletionDataHelper.CreateMarkupExtensionInsight(context);
context.Editor.ShowInsightWindow(insightList);
context.Editor.ShowCompletionWindow(completionList);
return completionList.Items.Any() || insightList.Any();
}
return false;
} }
} }
} }

394
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlColorizer.cs

@ -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; }
}
}
}
}

143
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompilationUnit.cs

@ -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);
}
}
}
}
}
}

309
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItem.cs

@ -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;
}
}
}
}

334
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs

@ -5,10 +5,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
@ -52,170 +50,170 @@ namespace ICSharpCode.XamlBinding
return text.Length - i - 1; return text.Length - i - 1;
} }
public override void Complete(CompletionContext context, ICompletionItem item) // public override void Complete(CompletionContext context, ICompletionItem item)
{ // {
using (context.Editor.Document.OpenUndoGroup()) { // using (context.Editor.Document.OpenUndoGroup()) {
base.Complete(context, item); // base.Complete(context, item);
//
XamlCompletionContext xamlContext = CompletionDataHelper.ResolveCompletionContext(context.Editor, context.CompletionChar); // XamlCompletionContext xamlContext = CompletionDataHelper.ResolveCompletionContext(context.Editor, context.CompletionChar);
//
if (xamlContext.Description == XamlContextDescription.None && (context.StartOffset <= 0 || context.Editor.Document.GetCharAt(context.StartOffset - 1) != '<')) { // if (xamlContext.Description == XamlContextDescription.None && (context.StartOffset <= 0 || context.Editor.Document.GetCharAt(context.StartOffset - 1) != '<')) {
context.Editor.Document.Insert(context.StartOffset, "<"); // context.Editor.Document.Insert(context.StartOffset, "<");
context.EndOffset++; // context.EndOffset++;
} // }
//
if (item is XamlCodeCompletionItem) { // if (item is XamlCodeCompletionItem) {
XamlCodeCompletionItem cItem = item as XamlCodeCompletionItem; // XamlCodeCompletionItem cItem = item as XamlCodeCompletionItem;
//
if (cItem.Entity is IProperty || cItem.Entity is IEvent) { // if (cItem.Entity is IProperty || cItem.Entity is IEvent) {
if (xamlContext.Description == XamlContextDescription.InTag) { // if (xamlContext.Description == XamlContextDescription.InTag) {
context.Editor.Document.Insert(context.EndOffset, "=\"\""); // context.Editor.Document.Insert(context.EndOffset, "=\"\"");
context.CompletionCharHandled = context.CompletionChar == '='; // context.CompletionCharHandled = context.CompletionChar == '=';
context.Editor.Caret.Offset--; // context.Editor.Caret.Offset--;
new XamlCodeCompletionBinding().CtrlSpace(context.Editor); // new XamlCodeCompletionBinding().CtrlSpace(context.Editor);
} else if (xamlContext.Description == XamlContextDescription.InMarkupExtension && !string.IsNullOrEmpty(xamlContext.RawAttributeValue)) { // } else if (xamlContext.Description == XamlContextDescription.InMarkupExtension && !string.IsNullOrEmpty(xamlContext.RawAttributeValue)) {
string valuePart = xamlContext.RawAttributeValue.Substring(0, xamlContext.ValueStartOffset); // string valuePart = xamlContext.RawAttributeValue.Substring(0, xamlContext.ValueStartOffset);
AttributeValue value = MarkupExtensionParser.ParseValue(valuePart); // AttributeValue value = MarkupExtensionParser.ParseValue(valuePart);
//
if (value != null && !value.IsString) { // if (value != null && !value.IsString) {
var markup = Utils.GetMarkupExtensionAtPosition(value.ExtensionValue, context.Editor.Caret.Offset); // var markup = Utils.GetMarkupExtensionAtPosition(value.ExtensionValue, context.Editor.Caret.Offset);
if (markup.NamedArguments.Count > 0 || markup.PositionalArguments.Count > 0) { // if (markup.NamedArguments.Count > 0 || markup.PositionalArguments.Count > 0) {
int oldOffset = context.Editor.Caret.Offset; // int oldOffset = context.Editor.Caret.Offset;
context.Editor.Caret.Offset = context.StartOffset; // context.Editor.Caret.Offset = context.StartOffset;
string word = context.Editor.GetWordBeforeCaret().TrimEnd(); // string word = context.Editor.GetWordBeforeCaret().TrimEnd();
int spaces = CountWhiteSpacesAtEnd(context.Editor.GetWordBeforeCaret()); // int spaces = CountWhiteSpacesAtEnd(context.Editor.GetWordBeforeCaret());
int typeNameStart = markup.ExtensionType.IndexOf(':') + 1; // int typeNameStart = markup.ExtensionType.IndexOf(':') + 1;
//
if (!(word == "." || word == "," || word == ":") && markup.ExtensionType.Substring(typeNameStart, markup.ExtensionType.Length - typeNameStart) != word) { // if (!(word == "." || word == "," || word == ":") && markup.ExtensionType.Substring(typeNameStart, markup.ExtensionType.Length - typeNameStart) != word) {
context.Editor.Document.Replace(context.Editor.Caret.Offset - spaces, spaces, ", "); // context.Editor.Document.Replace(context.Editor.Caret.Offset - spaces, spaces, ", ");
oldOffset += (2 - spaces); // oldOffset += (2 - spaces);
} // }
//
context.Editor.Caret.Offset = oldOffset; // context.Editor.Caret.Offset = oldOffset;
} // }
} // }
//
if (cItem.Text.EndsWith("=", StringComparison.OrdinalIgnoreCase)) // if (cItem.Text.EndsWith("=", StringComparison.OrdinalIgnoreCase))
new XamlCodeCompletionBinding().CtrlSpace(context.Editor); // new XamlCodeCompletionBinding().CtrlSpace(context.Editor);
} // }
} // }
} // }
//
if (item is NewEventCompletionItem) { // if (item is NewEventCompletionItem) {
NewEventCompletionItem eventItem = item as NewEventCompletionItem; // NewEventCompletionItem eventItem = item as NewEventCompletionItem;
int discriminator; // int discriminator;
if (CreateEventHandlerCode(context, eventItem, out discriminator)) { // if (CreateEventHandlerCode(context, eventItem, out discriminator)) {
if (discriminator > 0) // if (discriminator > 0)
context.Editor.Document.Insert(context.EndOffset, discriminator.ToString()); // context.Editor.Document.Insert(context.EndOffset, discriminator.ToString());
} // }
} // }
//
if (item is XmlnsCompletionItem) { // if (item is XmlnsCompletionItem) {
context.Editor.Caret.Offset++; // context.Editor.Caret.Offset++;
} // }
//
if (item is XamlCompletionItem && xamlContext.Description == XamlContextDescription.InTag) { // if (item is XamlCompletionItem && xamlContext.Description == XamlContextDescription.InTag) {
context.Editor.Document.Insert(context.EndOffset, "=\"\""); // context.Editor.Document.Insert(context.EndOffset, "=\"\"");
context.Editor.Caret.Offset--; // context.Editor.Caret.Offset--;
new XamlCodeCompletionBinding().CtrlSpace(context.Editor); // new XamlCodeCompletionBinding().CtrlSpace(context.Editor);
} // }
//
switch (item.Text) { // switch (item.Text) {
case "![CDATA[": // case "![CDATA[":
context.Editor.Document.Insert(context.Editor.Caret.Offset, "]]>"); // context.Editor.Document.Insert(context.Editor.Caret.Offset, "]]>");
context.Editor.Caret.Offset -= 3; // context.Editor.Caret.Offset -= 3;
break; // break;
case "?": // case "?":
context.Editor.Document.Insert(context.Editor.Caret.Offset, "?>"); // context.Editor.Document.Insert(context.Editor.Caret.Offset, "?>");
context.Editor.Caret.Offset -= 2; // context.Editor.Caret.Offset -= 2;
break; // break;
case "!--": // case "!--":
context.Editor.Document.Insert(context.Editor.Caret.Offset, " -->"); // context.Editor.Document.Insert(context.Editor.Caret.Offset, " -->");
context.Editor.Caret.Offset -= 4; // context.Editor.Caret.Offset -= 4;
break; // break;
} // }
//
if (item.Text.StartsWith("/", StringComparison.OrdinalIgnoreCase)) { // if (item.Text.StartsWith("/", StringComparison.OrdinalIgnoreCase)) {
context.Editor.Document.Insert(context.EndOffset, ">"); // context.Editor.Document.Insert(context.EndOffset, ">");
context.CompletionCharHandled = context.CompletionChar == '>'; // context.CompletionCharHandled = context.CompletionChar == '>';
context.Editor.Caret.Offset++; // context.Editor.Caret.Offset++;
} // }
} // }
} // }
//
static bool CreateEventHandlerCode(CompletionContext context, NewEventCompletionItem completionItem, out int discriminator) // static bool CreateEventHandlerCode(CompletionContext context, NewEventCompletionItem completionItem, out int discriminator)
{ // {
ParseInformation p = ParserService.GetParseInformation(context.Editor.FileName); // ParseInformation p = ParserService.GetParseInformation(context.Editor.FileName);
var unit = p.CompilationUnit; // var unit = p.CompilationUnit;
var loc = context.Editor.Document.OffsetToPosition(context.StartOffset); // var loc = context.Editor.Document.OffsetToPosition(context.StartOffset);
IClass c = unit.GetInnermostClass(loc.Line, loc.Column); // IClass c = unit.GetInnermostClass(loc.Line, loc.Column);
//
discriminator = 1; // discriminator = 1;
//
if (c == null) // if (c == null)
return false; // return false;
IMethod initializeComponent = c.Methods[0]; // IMethod initializeComponent = c.Methods[0];
CompoundClass compound = c.GetCompoundClass() as CompoundClass; // CompoundClass compound = c.GetCompoundClass() as CompoundClass;
//
IMethod invokeMethod = completionItem.EventType.ReturnType.GetMethods().FirstOrDefault(m => m.Name == "Invoke"); // IMethod invokeMethod = completionItem.EventType.ReturnType.GetMethods().FirstOrDefault(m => m.Name == "Invoke");
//
string handlerName = completionItem.HandlerName; // string handlerName = completionItem.HandlerName;
//
if (invokeMethod == null) // if (invokeMethod == null)
throw new ArgumentException("delegateType is not a valid delegate!"); // throw new ArgumentException("delegateType is not a valid delegate!");
//
if (compound != null) { // if (compound != null) {
foreach (IClass part in compound.Parts) { // foreach (IClass part in compound.Parts) {
IMember lastMember = part.Methods.LastOrDefault(); // IMember lastMember = part.Methods.LastOrDefault();
//
if (lastMember != null && lastMember.ToString() == initializeComponent.ToString()) // if (lastMember != null && lastMember.ToString() == initializeComponent.ToString())
continue; // continue;
//
if (completionItem.EventType.ReturnType == null) // if (completionItem.EventType.ReturnType == null)
return false; // return false;
//
while (part.Methods.Any(m => m.Name == handlerName && // while (part.Methods.Any(m => m.Name == handlerName &&
m.Parameters.Count == invokeMethod.Parameters.Count && // m.Parameters.Count == invokeMethod.Parameters.Count &&
m.Parameters.SequenceEqual(invokeMethod.Parameters, new ParameterComparer()) // m.Parameters.SequenceEqual(invokeMethod.Parameters, new ParameterComparer())
)) { // )) {
handlerName = completionItem.HandlerName + discriminator; // handlerName = completionItem.HandlerName + discriminator;
discriminator++; // discriminator++;
} // }
//
discriminator--; // discriminator--;
//
ParametrizedNode node = (ParametrizedNode)CodeGenerator.ConvertMember(invokeMethod, new ClassFinder(part, context.Editor.Caret.Line, context.Editor.Caret.Column)); // ParametrizedNode node = (ParametrizedNode)CodeGenerator.ConvertMember(invokeMethod, new ClassFinder(part, context.Editor.Caret.Line, context.Editor.Caret.Column));
//
node.Name = handlerName; // node.Name = handlerName;
//
node.Modifier = Modifiers.None; // node.Modifier = Modifiers.None;
//
IViewContent viewContent = FileService.OpenFile(part.CompilationUnit.FileName, XamlBindingOptions.SwitchToCodeViewAfterInsertion); // IViewContent viewContent = FileService.OpenFile(part.CompilationUnit.FileName, XamlBindingOptions.SwitchToCodeViewAfterInsertion);
IFileDocumentProvider document = viewContent as IFileDocumentProvider; // IFileDocumentProvider document = viewContent as IFileDocumentProvider;
//
if (viewContent != null && document != null) { // if (viewContent != null && document != null) {
DomRegion domRegion; // DomRegion domRegion;
//
if (lastMember != null) { // if (lastMember != null) {
unit.ProjectContent.Language.CodeGenerator.InsertCodeAfter(lastMember, new RefactoringDocumentAdapter(document.GetDocumentForFile(viewContent.PrimaryFile)), node); // unit.ProjectContent.Language.CodeGenerator.InsertCodeAfter(lastMember, new RefactoringDocumentAdapter(document.GetDocumentForFile(viewContent.PrimaryFile)), node);
domRegion = lastMember.BodyRegion; // domRegion = lastMember.BodyRegion;
} // }
else { // else {
unit.ProjectContent.Language.CodeGenerator.InsertCodeAtEnd(part.Region, new RefactoringDocumentAdapter(document.GetDocumentForFile(viewContent.PrimaryFile)), node); // unit.ProjectContent.Language.CodeGenerator.InsertCodeAtEnd(part.Region, new RefactoringDocumentAdapter(document.GetDocumentForFile(viewContent.PrimaryFile)), node);
domRegion = part.Region; // domRegion = part.Region;
} // }
//
// move caret to generated code // // move caret to generated code
ITextEditorProvider provider = viewContent as ITextEditorProvider; // ITextEditorProvider provider = viewContent as ITextEditorProvider;
if (provider != null) { // if (provider != null) {
provider.TextEditor.JumpTo(domRegion.EndLine + 2, domRegion.EndColumn - 1); // provider.TextEditor.JumpTo(domRegion.EndLine + 2, domRegion.EndColumn - 1);
} // }
} // }
return true; // return true;
} // }
} // }
//
return false; // return false;
} // }
} }
} }

35
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs

@ -1,23 +1,26 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // 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) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using ICSharpCode.AvalonEdit.Xml;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Xml; using System.Xml;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Xml;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.XmlEditor; using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding namespace ICSharpCode.XamlBinding
{ {
// Fetch a copy of all relevant values of the AXmlDocument so that XamlContext can be used // Fetch a copy of all relevant values of the AXmlDocument so that XamlContext can be used
// without having to acquire the reader lock. // without having to acquire the reader lock.
public class ElementWrapper { public class ElementWrapper
{
public ElementWrapper(AXmlElement element) public ElementWrapper(AXmlElement element)
{ {
this.LocalName = element.LocalName; this.LocalName = element.LocalName;
@ -63,7 +66,8 @@ namespace ICSharpCode.XamlBinding
} }
} }
public class AttributeWrapper { public class AttributeWrapper
{
public string LocalName { get; set; } public string LocalName { get; set; }
public string Namespace { get; set; } public string Namespace { get; set; }
public string Prefix { get; set; } public string Prefix { get; set; }
@ -94,7 +98,8 @@ namespace ICSharpCode.XamlBinding
} }
} }
public class XamlContext : ExpressionContext { public class XamlContext
{
public ElementWrapper ActiveElement { get; set; } public ElementWrapper ActiveElement { get; set; }
public ElementWrapper ParentElement { get; set; } public ElementWrapper ParentElement { get; set; }
public List<ElementWrapper> Ancestors { get; set; } public List<ElementWrapper> Ancestors { get; set; }
@ -109,15 +114,6 @@ namespace ICSharpCode.XamlBinding
public ReadOnlyCollection<string> IgnoredXmlns { get; set; } public ReadOnlyCollection<string> IgnoredXmlns { get; set; }
public string XamlNamespacePrefix { get; set; } public string XamlNamespacePrefix { get; set; }
public IProjectContent ProjectContent {
get {
if (ParseInformation != null)
return ParseInformation.CompilationUnit.ProjectContent;
else
return null;
}
}
public XamlContext() {} public XamlContext() {}
public bool InAttributeValueOrMarkupExtension { public bool InAttributeValueOrMarkupExtension {
@ -129,14 +125,10 @@ namespace ICSharpCode.XamlBinding
get { return Description == XamlContextDescription.InComment || get { return Description == XamlContextDescription.InComment ||
Description == XamlContextDescription.InCData; } Description == XamlContextDescription.InCData; }
} }
public override bool ShowEntry(ICompletionEntry o)
{
return true;
}
} }
public class XamlCompletionContext : XamlContext { public class XamlCompletionContext : XamlContext
{
public XamlCompletionContext() { } public XamlCompletionContext() { }
public XamlCompletionContext(XamlContext context) public XamlCompletionContext(XamlContext context)
@ -161,7 +153,8 @@ namespace ICSharpCode.XamlBinding
public ITextEditor Editor { get; set; } public ITextEditor Editor { get; set; }
} }
public enum XamlContextDescription { public enum XamlContextDescription
{
/// <summary> /// <summary>
/// Outside any tag /// Outside any tag
/// </summary> /// </summary>

9
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlExpressionContext.cs

@ -3,7 +3,7 @@
using System; using System;
using System.Text; using System.Text;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.XmlEditor; using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding namespace ICSharpCode.XamlBinding
@ -11,7 +11,7 @@ namespace ICSharpCode.XamlBinding
/// <summary> /// <summary>
/// Represents the context of a location in a XAML document. /// Represents the context of a location in a XAML document.
/// </summary> /// </summary>
public sealed class XamlExpressionContext : ExpressionContext public sealed class XamlExpressionContext
{ {
public static readonly XamlExpressionContext Empty = new XamlExpressionContext(new XmlElementPath(), null, false); public static readonly XamlExpressionContext Empty = new XamlExpressionContext(new XmlElementPath(), null, false);
@ -28,11 +28,6 @@ namespace ICSharpCode.XamlBinding
this.InAttributeValue = inAttributeValue; this.InAttributeValue = inAttributeValue;
} }
public override bool ShowEntry(ICompletionEntry o)
{
return true;
}
public override string ToString() public override string ToString()
{ {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();

75
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlExpressionFinder.cs

@ -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);
}
}
}
}

21
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlLanguageBinding.cs

@ -4,7 +4,6 @@
using System; using System;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering; using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
@ -15,7 +14,7 @@ namespace ICSharpCode.XamlBinding
/// </summary> /// </summary>
public class XamlLanguageBinding : XmlEditor.XmlLanguageBinding public class XamlLanguageBinding : XmlEditor.XmlLanguageBinding
{ {
XamlColorizer colorizer; // XamlColorizer colorizer;
TextView textView; TextView textView;
XamlOutlineContentHost contentHost; XamlOutlineContentHost contentHost;
@ -31,11 +30,11 @@ namespace ICSharpCode.XamlBinding
// GetService returns null // GetService returns null
if (textView != null) { if (textView != null) {
if (WorkbenchSingleton.Workbench != null) { if (WorkbenchSingleton.Workbench != null) {
if (XamlBindingOptions.UseAdvancedHighlighting) { // if (XamlBindingOptions.UseAdvancedHighlighting) {
colorizer = new XamlColorizer(editor, textView); // colorizer = new XamlColorizer(editor, textView);
// attach the colorizer // // attach the colorizer
textView.LineTransformers.Add(colorizer); // textView.LineTransformers.Add(colorizer);
} // }
// add the XamlOutlineContentHost, which manages the tree view // add the XamlOutlineContentHost, which manages the tree view
contentHost = new XamlOutlineContentHost(editor); contentHost = new XamlOutlineContentHost(editor);
textView.Services.AddService(typeof(IOutlineContentHost), contentHost); textView.Services.AddService(typeof(IOutlineContentHost), contentHost);
@ -52,10 +51,10 @@ namespace ICSharpCode.XamlBinding
// if we added something before // if we added something before
if (textView != null) { if (textView != null) {
// remove and dispose everything we added // remove and dispose everything we added
if (colorizer != null) { // if (colorizer != null) {
textView.LineTransformers.Remove(colorizer); // textView.LineTransformers.Remove(colorizer);
colorizer.Dispose(); // colorizer.Dispose();
} // }
if (contentHost != null) { if (contentHost != null) {
textView.Services.RemoveService(typeof(IOutlineContentHost)); textView.Services.RemoveService(typeof(IOutlineContentHost));
contentHost.Dispose(); contentHost.Dispose();

13
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineContentHost.xaml.cs

@ -5,11 +5,12 @@ using System;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.XamlBinding namespace ICSharpCode.XamlBinding
{ {
@ -33,13 +34,11 @@ namespace ICSharpCode.XamlBinding
{ {
if (this.editor == null || !FileUtility.IsEqualFileName(this.editor.FileName, e.FileName)) if (this.editor == null || !FileUtility.IsEqualFileName(this.editor.FileName, e.FileName))
return; return;
if (!e.IsPrimaryParseInfoForFile)
return;
var cu = e.NewCompilationUnit as XamlCompilationUnit;
if (cu != null && cu.TreeRootNode != null) // var cu = e.NewCompilationUnit as XamlCompilationUnit;
UpdateTree(cu.TreeRootNode); //
// if (cu != null && cu.TreeRootNode != null)
// UpdateTree(cu.TreeRootNode);
} }
void UpdateTree(NodeWrapper root) void UpdateTree(NodeWrapper root)

1
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineNode.cs

@ -7,6 +7,7 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;

97
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParsedFile.cs

@ -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();
}
}
}

190
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs

@ -2,15 +2,23 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.Core; 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;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.XamlBinding namespace ICSharpCode.XamlBinding
{ {
@ -27,10 +35,10 @@ namespace ICSharpCode.XamlBinding
set { lexerTags = value; } set { lexerTags = value; }
} }
public LanguageProperties Language // public LanguageProperties Language
{ // {
get { return LanguageProperties.CSharp; } // get { return LanguageProperties.CSharp; }
} // }
public XamlParser() public XamlParser()
{ {
@ -47,98 +55,110 @@ namespace ICSharpCode.XamlBinding
} }
AXmlParser parser = new AXmlParser(); AXmlParser parser = new AXmlParser();
volatile ITextBufferVersion lastParsedVersion; volatile ITextSourceVersion lastParsedVersion;
/// <summary> /// <summary>
/// Parse the given text and enter read lock. /// Parse the given text and enter read lock.
/// No parsing is done if the text is older than seen before. /// No parsing is done if the text is older than seen before.
/// </summary> /// </summary>
public IDisposable ParseAndLock(ITextBuffer fileContent) // public IDisposable ParseAndLock(ITextSource fileContent)
{ // {
// Copy to ensure thread-safety // // Copy to ensure thread-safety
var lastVer = this.lastParsedVersion; // var lastVer = this.lastParsedVersion;
if (lastVer == null || // First parse // if (lastVer == null || // First parse
fileContent.Version == null || // Versioning not supported // fileContent.Version == null || // Versioning not supported
!fileContent.Version.BelongsToSameDocumentAs(lastVer) || // Different document instance? Can happen after closing and reopening of file. // !fileContent.Version.BelongsToSameDocumentAs(lastVer) || // Different document instance? Can happen after closing and reopening of file.
fileContent.Version.CompareAge(lastVer) > 0) // Is fileContent newer? // fileContent.Version.CompareAge(lastVer) > 0) // Is fileContent newer?
{ // {
parser.Lock.EnterWriteLock(); // parser.Lock.EnterWriteLock();
// Double check, now that we are thread-safe // // Double check, now that we are thread-safe
lastVer = this.lastParsedVersion; // lastVer = this.lastParsedVersion;
if (lastVer == null || fileContent.Version == null || !fileContent.Version.BelongsToSameDocumentAs(lastVer)) { // if (lastVer == null || fileContent.Version == null || !fileContent.Version.BelongsToSameDocumentAs(lastVer)) {
// First parse or versioning not supported // // First parse or versioning not supported
using (DebugTimer.Time("normal parse")) // using (DebugTimer.Time("normal parse"))
parser.Parse(fileContent.Text, null); // parser.Parse(fileContent.Text, null);
this.lastParsedVersion = fileContent.Version; // this.lastParsedVersion = fileContent.Version;
} else if (fileContent.Version.CompareAge(lastParsedVersion) > 0) { // } else if (fileContent.Version.CompareAge(lastParsedVersion) > 0) {
// Incremental parse // // Incremental parse
var changes = lastParsedVersion.GetChangesTo(fileContent.Version). // var changes = lastParsedVersion.GetChangesTo(fileContent.Version).
Select(c => new DocumentChangeEventArgs(c.Offset, c.RemovedText, c.InsertedText)); // Select(c => new DocumentChangeEventArgs(c.Offset, c.RemovedText, c.InsertedText));
using (DebugTimer.Time("incremental parse")) // using (DebugTimer.Time("incremental parse"))
parser.Parse(fileContent.Text, changes); // parser.Parse(fileContent.Text, changes);
this.lastParsedVersion = fileContent.Version; // this.lastParsedVersion = fileContent.Version;
} else { // } else {
// fileContent is older - no need to parse // // fileContent is older - no need to parse
} // }
parser.Lock.EnterReadLock(); // parser.Lock.EnterReadLock();
parser.Lock.ExitWriteLock(); // parser.Lock.ExitWriteLock();
} else { // } else {
// fileContent is older - no need to parse // // fileContent is older - no need to parse
parser.Lock.EnterReadLock(); // parser.Lock.EnterReadLock();
} // }
return new CallbackOnDispose(() => parser.Lock.ExitReadLock()); // return new CallbackOnDispose(() => parser.Lock.ExitReadLock());
} // }
//
public ICompilationUnit Parse(IProjectContent projectContent, string fileName, ITextBuffer fileContent) // public ICompilationUnit Parse(IProjectContent projectContent, string fileName, ITextSource fileContent)
// {
// ICompilationUnit compilationUnit;
//
// using (ParseAndLock(fileContent)) {
// var document = parser.LastDocument;
//
// CompilationUnitCreatorVisitor visitor =
// new CompilationUnitCreatorVisitor(projectContent, fileContent.Text, fileName, lexerTags);
//
// document.AcceptVisitor(visitor);
//
// compilationUnit = visitor.CompilationUnit;
// }
//
// // During project load all XAML files are parsed
// // most of them are not opened, thus fileContent.Version is null.
// // We can clear the parser data, because the file will be reparsed
// // as soon as it is opened by the user.
//
// // This will save us some memory, because we only use the
// // compilation unit created by the visitor above for code completion.
// if (fileContent.Version == null) {
// parser.Lock.EnterWriteLock();
// // double-checked locking (other threads might parse the document in the meantime)
// if (lastParsedVersion == null) {
// parser.Clear();
// }
// parser.Lock.ExitWriteLock();
// }
//
// return compilationUnit;
// }
volatile IncrementalParserState parserState = null;
public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested)
{ {
ICompilationUnit compilationUnit; AXmlParser parser = new AXmlParser();
AXmlDocument document;
using (ParseAndLock(fileContent)) { try {
var document = parser.LastDocument; document = parser.ParseIncremental(parserState, fileContent, out parserState);
} catch (Exception ex) {
CompilationUnitCreatorVisitor visitor = LoggingService.Error(ex);
new CompilationUnitCreatorVisitor(projectContent, fileContent.Text, fileName, lexerTags); document = null; // TODO empty document?
document.AcceptVisitor(visitor);
compilationUnit = visitor.CompilationUnit;
} }
XamlParsedFile parsedFile = XamlParsedFile.Create(fileName, fileContent.Text, document);
// During project load all XAML files are parsed // TODO if (fullParseInformationRequested)
// most of them are not opened, thus fileContent.Version is null. return new ParseInformation(parsedFile, false);
// We can clear the parser data, because the file will be reparsed
// as soon as it is opened by the user.
// This will save us some memory, because we only use the
// compilation unit created by the visitor above for code completion.
if (fileContent.Version == null) {
parser.Lock.EnterWriteLock();
// double-checked locking (other threads might parse the document in the meantime)
if (lastParsedVersion == null) {
parser.Clear();
}
parser.Lock.ExitWriteLock();
}
return compilationUnit;
} }
/// <summary> public ResolveResult Resolve(ParseInformation parseInfo, TextLocation location, ICompilation compilation, CancellationToken cancellationToken)
/// Wraps AXmlParser.LastDocument. Returns the last cached version of the document.
/// </summary>
/// <exception cref="InvalidOperationException">No read lock is held by the current thread.</exception>
public AXmlDocument LastDocument {
get { return parser.LastDocument; }
}
public IExpressionFinder CreateExpressionFinder(string fileName)
{ {
return XamlExpressionFinder.Instance; throw new NotImplementedException();
} }
public IResolver CreateResolver() public void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action<Reference> callback, CancellationToken cancellationToken)
{ {
return new XamlResolver(); throw new NotImplementedException();
} }
} }
} }

271
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs

@ -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);
}
}
}

32
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs

@ -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…
Cancel
Save