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

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

@ -1,181 +0,0 @@ @@ -1,181 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.XamlBinding
{
public sealed class CompilationUnitCreatorVisitor : AbstractAXmlVisitor
{
public XamlCompilationUnit CompilationUnit { get; private set; }
AXmlDocument document;
IClass generatedClass;
IProjectContent projectContent;
Stack<NodeWrapper> nodeStack;
IAmbience currentAmbience;
/// <summary>
/// string representation of the document, used to create DOM regions.
/// </summary>
string fileContent;
string[] lexerTags;
public CompilationUnitCreatorVisitor(IProjectContent projectContent, string fileContent, string fileName, string[] lexerTags)
{
this.CompilationUnit = new XamlCompilationUnit(projectContent);
this.CompilationUnit.FileName = fileName;
this.fileContent = fileContent;
this.lexerTags = lexerTags;
this.projectContent = projectContent;
this.currentAmbience = projectContent.Language.GetAmbience();
this.nodeStack = new Stack<NodeWrapper>();
}
public override void VisitDocument(AXmlDocument document)
{
this.CompilationUnit.ErrorsDuringCompile = document.SyntaxErrors.Any();
this.document = document;
base.VisitDocument(document);
}
public override void VisitAttribute(AXmlAttribute attribute)
{
Debug.Assert(document != null);
if (attribute.ParentElement != null) {
if (attribute.ParentElement.Parent == document && attribute.LocalName == "Class" &&
attribute.Namespace == CompletionDataHelper.XamlNamespace) {
this.generatedClass = AddClass(attribute.Value, attribute.ParentElement);
} else if (generatedClass != null && attribute.LocalName == "Name") {
string name = attribute.Value;
if (!string.IsNullOrEmpty(name)) {
IReturnType type = TypeFromXmlNode(CompilationUnit, attribute.ParentElement);
DomRegion position = CreateRegion(attribute.ParentElement.StartOffset, attribute.ParentElement.StartOffset + attribute.ParentElement.Name.Length);
ModifierEnum fieldModifier = ModifierEnum.Internal;
string modifierValue = (attribute.ParentElement.GetAttributeValue(CompletionDataHelper.XamlNamespace, "FieldModifier") ?? string.Empty).Trim();
string publicString = currentAmbience.ConvertAccessibility(ModifierEnum.Public).Trim();
if (projectContent.Language.NameComparer.Compare(modifierValue, publicString) == 0)
fieldModifier = ModifierEnum.Public;
generatedClass.Fields.Add(new DefaultField(type, name, fieldModifier, position, generatedClass));
}
}
}
base.VisitAttribute(attribute);
}
public override void VisitTag(AXmlTag tag)
{
if (tag.IsComment) {
StringBuilder sb = new StringBuilder();
foreach(AXmlText text in tag.Children.OfType<AXmlText>()) {
sb.Append(text.Value);
}
string value = sb.ToString();
foreach (string commentTag in lexerTags) {
if (value.Contains(commentTag)) {
CompilationUnit.TagComments.Add(new TagComment(value, CreateRegion(tag.StartOffset, tag.EndOffset)));
break;
}
}
}
base.VisitTag(tag);
}
public override void VisitElement(AXmlElement element)
{
AXmlTag tag = element.Children.FirstOrDefault() as AXmlTag;
if (tag != null && tag.IsStartOrEmptyTag) {
NodeWrapper node = new NodeWrapper() {
ElementName = element.LocalName,
StartOffset = element.StartOffset,
EndOffset = element.EndOffset,
Name = element.GetAttributeValue("Name") ?? element.GetAttributeValue(CompletionDataHelper.XamlNamespace, "Name"),
Children = new List<NodeWrapper>()
};
if (CompilationUnit.TreeRootNode == null) {
CompilationUnit.TreeRootNode = node;
nodeStack.Push(CompilationUnit.TreeRootNode);
} else {
if (nodeStack.Count > 0)
nodeStack.Peek().Children.Add(node);
if (!tag.IsEmptyTag)
nodeStack.Push(node);
}
}
base.VisitElement(element);
if (tag != null && tag.IsStartTag)
nodeStack.PopOrDefault();
}
IClass AddClass(string className, AXmlElement element) {
if (projectContent.Language == LanguageProperties.VBNet && projectContent.Project is IProject)
className = ((IProject)projectContent.Project).RootNamespace + "." + className;
DefaultClass c = new DefaultClass(CompilationUnit, className);
string modifierValue = (element.GetAttributeValue(CompletionDataHelper.XamlNamespace, "ClassModifier") ?? string.Empty).Trim();
c.Modifiers = ModifierEnum.Partial;
string internalString = currentAmbience.ConvertAccessibility(ModifierEnum.Internal).Trim();
if (projectContent.Language.NameComparer.Compare(modifierValue, internalString) == 0)
c.Modifiers |= ModifierEnum.Internal;
else
c.Modifiers |= ModifierEnum.Public;
c.Region = CreateRegion(element.StartOffset, element.EndOffset);
var baseType = TypeFromXmlNode(CompilationUnit, element);
if (baseType != null)
c.BaseTypes.Add(baseType);
CompilationUnit.Classes.Add(c);
DefaultMethod initializeComponent = new DefaultMethod(
"InitializeComponent",
projectContent.SystemTypes.Void,
ModifierEnum.Public | ModifierEnum.Synthetic, c.Region, DomRegion.Empty,
c);
c.Methods.Add(initializeComponent);
return c;
}
DomRegion CreateRegion(int startOffset, int endOffset)
{
ICSharpCode.NRefactory.Location loc = Utils.GetLocationInfoFromOffset(fileContent, startOffset);
ICSharpCode.NRefactory.Location loc2 = Utils.GetLocationInfoFromOffset(fileContent, endOffset);
return new DomRegion(loc.Line, loc.Column, loc2.Line, loc2.Column);
}
static IReturnType TypeFromXmlNode(XamlCompilationUnit cu, AXmlElement element)
{
return cu.CreateType(element.Namespace, element.LocalName);
}
}
}

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; @@ -12,10 +12,11 @@ using System.Xml;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Xml;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.XmlEditor;
@ -161,8 +162,9 @@ namespace ICSharpCode.XamlBinding @@ -161,8 +162,9 @@ namespace ICSharpCode.XamlBinding
public static string GetWordBeforeCaretExtended(this ITextEditor editor)
{
IDocumentLine line = editor.Document.GetLine(editor.Caret.Line);
int index = Math.Min(editor.Caret.Column - 1, line.Text.Length);
string text = line.Text.Substring(0, index);
string lineText = editor.Document.GetText(line);
int index = Math.Min(editor.Caret.Column - 1, lineText.Length);
string text = lineText.Substring(0, index);
int startIndex = text.LastIndexOfAny(' ', '\t', '"', '=', '<', '\'', '>', '{', '}');
if (startIndex > -1)
return text.Substring(startIndex + 1);
@ -236,12 +238,12 @@ namespace ICSharpCode.XamlBinding @@ -236,12 +238,12 @@ namespace ICSharpCode.XamlBinding
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);
}
@ -261,41 +263,21 @@ namespace ICSharpCode.XamlBinding @@ -261,41 +263,21 @@ namespace ICSharpCode.XamlBinding
return false;
}
public static bool IsCollectionType(this IClass thisValue)
public static bool IsCollectionType(this IType thisValue)
{
if (thisValue == null)
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)
{
if (type == null)
throw new ArgumentNullException("type");
if (type.GetUnderlyingClass() != null)
return type.GetUnderlyingClass().IsCollectionType();
return false;
}
public static bool IsListType(this IClass thisValue)
public static bool IsListType(this IType thisValue)
{
if (thisValue == null)
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)
{
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)
public static bool HasAttached(this ITypeDefinition thisValue, bool lookForProperties, bool lookForEvents)
{
if (!lookForProperties && !lookForEvents)
return false;
@ -310,12 +292,12 @@ namespace ICSharpCode.XamlBinding @@ -310,12 +292,12 @@ namespace ICSharpCode.XamlBinding
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;
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)
return false;
if (!field.Name.EndsWith("Property", StringComparison.Ordinal))
@ -323,7 +305,7 @@ namespace ICSharpCode.XamlBinding @@ -323,7 +305,7 @@ namespace ICSharpCode.XamlBinding
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)
continue;
if (!method.Name.StartsWith("Get") && !method.Name.StartsWith("Set"))
@ -334,7 +316,7 @@ namespace ICSharpCode.XamlBinding @@ -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)
return false;
if (!field.Name.EndsWith("Event", StringComparison.Ordinal))
@ -347,9 +329,10 @@ namespace ICSharpCode.XamlBinding @@ -347,9 +329,10 @@ namespace ICSharpCode.XamlBinding
}
/// <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)

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

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

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

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

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

@ -69,12 +69,12 @@ namespace ICSharpCode.XamlBinding @@ -69,12 +69,12 @@ namespace ICSharpCode.XamlBinding
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 line = lines.LastOrDefault() ?? string.Empty;
return new Location(line.Length + 1, lines.Length);
return new TextLocation(line.Length + 1, lines.Length);
}
/// <summary>

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

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

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

@ -64,17 +64,17 @@ @@ -64,17 +64,17 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="XamlParsedFile.cs" />
<Compile Include="XamlSymbolSearch.cs" />
<None Include="XamlBinding.addin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Compile Include="..\..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="CompilationUnitCreatorVisitor.cs" />
<Compile Include="Comparers.cs" />
<Compile Include="MarkupExtensionInfo.cs" />
<Compile Include="MarkupExtensionParser.cs" />
<Compile Include="CompletionDataHelper.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="MarkupExtensionTokenizer.cs" />
<Compile Include="MarkupExtensionToken.cs">
@ -87,41 +87,6 @@ @@ -87,41 +87,6 @@
<SubType>Code</SubType>
</Compile>
<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="PropertyPathSegment.cs" />
<Compile Include="PropertyPathTokenizer.cs" />
@ -131,17 +96,11 @@ @@ -131,17 +96,11 @@
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XamlBehavior.cs" />
<Compile Include="XamlClassReturnType.cs" />
<Compile Include="XamlCodeCompletionBinding.cs" />
<Compile Include="XamlCompilationUnit.cs" />
<Compile Include="XamlCompletionItem.cs" />
<Compile Include="XamlCompletionItemList.cs" />
<Compile Include="XamlCompletionSettings.cs" />
<Compile Include="XamlContext.cs" />
<Compile Include="XamlExpressionContext.cs" />
<Compile Include="XamlExpressionFinder.cs">
</Compile>
<Compile Include="XamlColorizer.cs" />
<Compile Include="MarkupExtensionParseException.cs">
</Compile>
<Compile Include="XamlLanguageBinding.cs" />
@ -151,7 +110,16 @@ @@ -151,7 +110,16 @@
</Compile>
<Compile Include="XamlOutlineNode.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">
<Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project>
<Name>NRefactory</Name>
@ -177,11 +145,6 @@ @@ -177,11 +145,6 @@
<Name>ICSharpCode.Core.Presentation</Name>
<Private>False</Private>
</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">
<Project>{8035765F-D51F-4A0C-A746-2FD100E19419}</Project>
<Name>ICSharpCode.SharpDevelop.Widgets</Name>
@ -204,19 +167,10 @@ @@ -204,19 +167,10 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="PowerToys" />
<Folder Include="Options" />
<Folder Include="PowerToys\Commands" />
<Folder Include="PowerToys\Dialogs" />
</ItemGroup>
<ItemGroup>
<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" />
</ItemGroup>
</Project>

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

@ -1,42 +0,0 @@ @@ -1,42 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.XamlBinding
{
/// <summary>
/// IReturnType that gets created by XamlCompilationUnit.CreateType and will
/// run XamlCompilationUnit.FindType on demand.
/// </summary>
public class XamlClassReturnType : ProxyReturnType
{
XamlCompilationUnit compilationUnit;
string xmlNamespace;
string className;
public XamlClassReturnType(XamlCompilationUnit compilationUnit, string xmlNamespace, string className)
{
if (compilationUnit == null)
throw new ArgumentNullException("compilationUnit");
this.compilationUnit = compilationUnit;
this.xmlNamespace = xmlNamespace;
this.className = className ?? "";
}
public override IReturnType BaseType
{
get
{
return compilationUnit.FindType(xmlNamespace, className);
}
}
public override string Name
{
get { return className; }
}
}
}

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

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
using ICSharpCode.XmlEditor;
using System;
using System.Linq;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
@ -16,384 +16,389 @@ namespace ICSharpCode.XamlBinding @@ -16,384 +16,389 @@ namespace ICSharpCode.XamlBinding
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
{
XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ch);
XamlCompletionItemList list;
if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData)
return CodeCompletionKeyPressResult.None;
switch (ch) {
case '<':
context.Description = (context.Description == XamlContextDescription.None) ? XamlContextDescription.AtTag : context.Description;
list = CompletionDataHelper.CreateListForContext(context);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
case '>':
return CodeCompletionKeyPressResult.None;
case '\'':
case '"':
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
// count all " or ' chars before the next > char
int search = editor.Caret.Offset + 1;
int endMarkerCount = 1;
char curCh = editor.Document.GetCharAt(search);
while (search < editor.Document.TextLength - 1 && curCh != '>') {
if (curCh == ch)
endMarkerCount++;
search++;
curCh = editor.Document.GetCharAt(search);
}
// if the count is odd we need to add an additional " or ' char
if (endMarkerCount % 2 != 0) {
editor.Document.Insert(editor.Caret.Offset, ch.ToString());
editor.Caret.Offset--;
this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.Completed;
}
}
break;
case '{': // starting point for Markup Extension Completion
if (context.Attribute != null
&& XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)
&& !(context.RawAttributeValue.StartsWith("{}", StringComparison.OrdinalIgnoreCase) && context.RawAttributeValue.Length != 2)) {
if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
editor.Document.Insert(editor.Caret.Offset, "{}");
editor.Caret.Offset--;
this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey;
}
break;
case '.':
switch (context.Description) {
case XamlContextDescription.AtTag:
case XamlContextDescription.InTag:
if (context.ActiveElement != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
list = CompletionDataHelper.CreateListForContext(context);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
}
break;
case XamlContextDescription.InMarkupExtension:
if (DoMarkupExtensionCompletion(context))
return CodeCompletionKeyPressResult.Completed;
break;
case XamlContextDescription.InAttributeValue:
if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
editor.Document.Insert(editor.Caret.Offset, ".");
this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey;
}
break;
case '(':
case '[':
if (context.Description == XamlContextDescription.InAttributeValue) {
if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
if (ch == '(')
editor.Document.Insert(editor.Caret.Offset, "()");
if (ch == '[')
editor.Document.Insert(editor.Caret.Offset, "[]");
editor.Caret.Offset--;
this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey;
}
break;
case ':':
if (context.ActiveElement != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) {
if (context.Attribute != null && !context.Attribute.Name.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) {
list = CompletionDataHelper.CreateListForContext(context);
list.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
}
}
break;
case '/': // ignore '/' when trying to type '/>'
return CodeCompletionKeyPressResult.None;
case '=':
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
int searchOffset = editor.Caret.Offset;
if (editor.SelectionLength != 0)
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
while (searchOffset < editor.Document.TextLength - 1) {
searchOffset++;
if (!char.IsWhiteSpace(editor.Document.GetCharAt(searchOffset)))
break;
}
if (searchOffset >= editor.Document.TextLength || editor.Document.GetCharAt(searchOffset) != '"') {
editor.Document.Insert(editor.Caret.Offset, "=\"\"");
editor.Caret.Offset--;
} else {
editor.Document.Insert(editor.Caret.Offset, "=");
editor.Caret.Offset++;
}
this.CtrlSpace(editor);
return CodeCompletionKeyPressResult.EatKey;
} else {
DoMarkupExtensionCompletion(context);
return CodeCompletionKeyPressResult.Completed;
}
default:
if (context.Description != XamlContextDescription.None && !char.IsWhiteSpace(ch)) {
string starter = editor.GetWordBeforeCaretExtended();
if (!string.IsNullOrEmpty(starter))
return CodeCompletionKeyPressResult.None;
trackForced = false;
string attributeName = (context.Attribute != null) ? context.Attribute.Name : string.Empty;
if (!attributeName.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) {
return this.CtrlSpace(editor)
? CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion
: CodeCompletionKeyPressResult.None;
}
trackForced = true;
return CodeCompletionKeyPressResult.None;
}
break;
}
// XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ch);
// XamlCompletionItemList list;
//
// if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData)
// return CodeCompletionKeyPressResult.None;
//
// switch (ch) {
// case '<':
// context.Description = (context.Description == XamlContextDescription.None) ? XamlContextDescription.AtTag : context.Description;
// list = CompletionDataHelper.CreateListForContext(context);
// editor.ShowCompletionWindow(list);
// return CodeCompletionKeyPressResult.Completed;
// case '>':
// return CodeCompletionKeyPressResult.None;
// case '\'':
// case '"':
// if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
// // count all " or ' chars before the next > char
// int search = editor.Caret.Offset + 1;
// int endMarkerCount = 1;
// char curCh = editor.Document.GetCharAt(search);
// while (search < editor.Document.TextLength - 1 && curCh != '>') {
// if (curCh == ch)
// endMarkerCount++;
// search++;
// curCh = editor.Document.GetCharAt(search);
// }
// // if the count is odd we need to add an additional " or ' char
// if (endMarkerCount % 2 != 0) {
// editor.Document.Insert(editor.Caret.Offset, ch.ToString());
// editor.Caret.Offset--;
// this.CtrlSpace(editor);
// return CodeCompletionKeyPressResult.Completed;
// }
// }
// break;
// case '{': // starting point for Markup Extension Completion
// if (context.Attribute != null
// && XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)
// && !(context.RawAttributeValue.StartsWith("{}", StringComparison.OrdinalIgnoreCase) && context.RawAttributeValue.Length != 2)) {
//
// if (editor.SelectionLength != 0)
// editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
// editor.Document.Insert(editor.Caret.Offset, "{}");
// editor.Caret.Offset--;
//
// this.CtrlSpace(editor);
// return CodeCompletionKeyPressResult.EatKey;
// }
// break;
// case '.':
// switch (context.Description) {
// case XamlContextDescription.AtTag:
// case XamlContextDescription.InTag:
// if (context.ActiveElement != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
// list = CompletionDataHelper.CreateListForContext(context);
// editor.ShowCompletionWindow(list);
// return CodeCompletionKeyPressResult.Completed;
// }
// break;
// case XamlContextDescription.InMarkupExtension:
//// if (DoMarkupExtensionCompletion(context))
//// return CodeCompletionKeyPressResult.Completed;
// break;
// case XamlContextDescription.InAttributeValue:
// if (editor.SelectionLength != 0)
// editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
// editor.Document.Insert(editor.Caret.Offset, ".");
//
// this.CtrlSpace(editor);
// return CodeCompletionKeyPressResult.EatKey;
// }
// break;
// case '(':
// case '[':
// if (context.Description == XamlContextDescription.InAttributeValue) {
// if (editor.SelectionLength != 0)
// editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
// if (ch == '(')
// editor.Document.Insert(editor.Caret.Offset, "()");
// if (ch == '[')
// editor.Document.Insert(editor.Caret.Offset, "[]");
// editor.Caret.Offset--;
//
// this.CtrlSpace(editor);
// return CodeCompletionKeyPressResult.EatKey;
// }
// break;
// case ':':
// if (context.ActiveElement != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) {
// if (context.Attribute != null && !context.Attribute.Name.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) {
// list = CompletionDataHelper.CreateListForContext(context);
// list.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
// editor.ShowCompletionWindow(list);
// return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
// }
// }
// break;
// case '/': // ignore '/' when trying to type '/>'
// return CodeCompletionKeyPressResult.None;
// case '=':
// if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
// int searchOffset = editor.Caret.Offset;
//
// if (editor.SelectionLength != 0)
// editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
//
// while (searchOffset < editor.Document.TextLength - 1) {
// searchOffset++;
// if (!char.IsWhiteSpace(editor.Document.GetCharAt(searchOffset)))
// break;
// }
//
// if (searchOffset >= editor.Document.TextLength || editor.Document.GetCharAt(searchOffset) != '"') {
// editor.Document.Insert(editor.Caret.Offset, "=\"\"");
// editor.Caret.Offset--;
// } else {
// editor.Document.Insert(editor.Caret.Offset, "=");
// editor.Caret.Offset++;
// }
//
// this.CtrlSpace(editor);
// return CodeCompletionKeyPressResult.EatKey;
// } else {
//// DoMarkupExtensionCompletion(context);
// return CodeCompletionKeyPressResult.Completed;
// }
// default:
// if (context.Description != XamlContextDescription.None && !char.IsWhiteSpace(ch)) {
// string starter = editor.GetWordBeforeCaretExtended();
// if (!string.IsNullOrEmpty(starter))
// return CodeCompletionKeyPressResult.None;
// trackForced = false;
//
// string attributeName = (context.Attribute != null) ? context.Attribute.Name : string.Empty;
//
// if (!attributeName.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) {
// return this.CtrlSpace(editor)
// ? CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion
// : CodeCompletionKeyPressResult.None;
// }
// trackForced = true;
// return CodeCompletionKeyPressResult.None;
// }
// break;
// }
//
return CodeCompletionKeyPressResult.None;
}
public bool CtrlSpace(ITextEditor editor)
{
XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ' ');
context.Forced = trackForced;
if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData)
return false;
if (context.ActiveElement != null) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && context.Description != XamlContextDescription.InAttributeValue) {
XamlCompletionItemList list = CompletionDataHelper.CreateListForContext(context);
string starter = editor.GetWordBeforeCaretExtended().TrimStart('/');
if (context.Description != XamlContextDescription.None && !string.IsNullOrEmpty(starter)) {
if (starter.Contains("."))
list.PreselectionLength = starter.Length - starter.IndexOf('.') - 1;
else
list.PreselectionLength = starter.Length;
}
editor.ShowCompletionWindow(list);
return true;
} else {
// DO NOT USE CompletionDataHelper.CreateListForContext here!!! results in endless recursion!!!!
if (context.Attribute != null) {
if (!DoMarkupExtensionCompletion(context)) {
var completionList = new XamlCompletionItemList(context);
completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") &&
(context.Attribute.Name == "Property" || context.Attribute.Name == "Value"))
DoSetterAndEventSetterCompletion(context, completionList);
else if ((context.ActiveElement.Name.EndsWith("Trigger") || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value")
DoTriggerCompletion(context, completionList);
else {
if (context.Attribute.Name == "xml:space") {
completionList.Items.AddRange(new[] { new SpecialCompletionItem("preserve"),
new SpecialCompletionItem("default") });
}
var mrr = XamlResolver.Resolve(context.Attribute.Name, context) as MemberResolveResult;
if (mrr != null && mrr.ResolvedType != null) {
completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(context, mrr.ResolvedType, string.Empty));
editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr));
if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.PropertyPath") {
string start = editor.GetWordBeforeCaretExtended();
int index = start.LastIndexOfAny(PropertyPathTokenizer.ControlChars);
if (index + 1 < start.Length)
start = start.Substring(index + 1);
else
start = "";
completionList.PreselectionLength = start.Length;
} 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)) : "";
int lastComma = text.LastIndexOf(',');
completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset : context.ValueStartOffset - lastComma - 1;
}
}
}
completionList.SortItems();
if (context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase))
completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(context.ProjectContent));
ICompletionListWindow window = editor.ShowCompletionWindow(completionList);
if ((context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) && window != null)
window.Width = 400;
return completionList.Items.Any();
}
return true;
}
}
}
// XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ' ');
// context.Forced = trackForced;
//
// if (context.Description == XamlContextDescription.InComment || context.Description == XamlContextDescription.InCData)
// return false;
//
// if (context.ActiveElement != null) {
// if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && context.Description != XamlContextDescription.InAttributeValue) {
// XamlCompletionItemList list = CompletionDataHelper.CreateListForContext(context);
// string starter = editor.GetWordBeforeCaretExtended().TrimStart('/');
// if (context.Description != XamlContextDescription.None && !string.IsNullOrEmpty(starter)) {
// if (starter.Contains("."))
// list.PreselectionLength = starter.Length - starter.IndexOf('.') - 1;
// else
// list.PreselectionLength = starter.Length;
// }
// editor.ShowCompletionWindow(list);
// return true;
// } else {
// // DO NOT USE CompletionDataHelper.CreateListForContext here!!! results in endless recursion!!!!
// if (context.Attribute != null) {
// if (!DoMarkupExtensionCompletion(context)) {
// var completionList = new XamlCompletionItemList(context);
// completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
//
// if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") &&
// (context.Attribute.Name == "Property" || context.Attribute.Name == "Value"))
// DoSetterAndEventSetterCompletion(context, completionList);
// else if ((context.ActiveElement.Name.EndsWith("Trigger") || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value")
// DoTriggerCompletion(context, completionList);
// else {
// if (context.Attribute.Name == "xml:space") {
// completionList.Items.AddRange(new[] { new SpecialCompletionItem("preserve"),
// new SpecialCompletionItem("default") });
// }
//
// var mrr = XamlResolver.Resolve(context.Attribute.Name, context) as MemberResolveResult;
// if (mrr != null && mrr.ResolvedType != null) {
// completionList.Items.AddRange(CompletionDataHelper.MemberCompletion(context, mrr.ResolvedType, string.Empty));
// editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr));
// if (mrr.ResolvedType.FullyQualifiedName == "System.Windows.PropertyPath") {
// string start = editor.GetWordBeforeCaretExtended();
// int index = start.LastIndexOfAny(PropertyPathTokenizer.ControlChars);
// if (index + 1 < start.Length)
// start = start.Substring(index + 1);
// else
// start = "";
// completionList.PreselectionLength = start.Length;
// } 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)) : "";
// int lastComma = text.LastIndexOf(',');
// completionList.PreselectionLength = lastComma == -1 ? context.ValueStartOffset : context.ValueStartOffset - lastComma - 1;
// }
// }
// }
//
// completionList.SortItems();
//
// if (context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
// context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase))
// completionList.Items.AddRange(CompletionDataHelper.CreateListForXmlnsCompletion(context.ProjectContent));
//
// ICompletionListWindow window = editor.ShowCompletionWindow(completionList);
//
// if ((context.Attribute.Prefix.Equals("xmlns", StringComparison.OrdinalIgnoreCase) ||
// context.Attribute.Name.Equals("xmlns", StringComparison.OrdinalIgnoreCase)) && window != null)
// window.Width = 400;
//
// return completionList.Items.Any();
// }
// return true;
// }
// }
// }
return false;
}
static void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
bool isExplicit;
AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? 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;
string name = propType.StringValue;
if (!name.Contains("."))
name = typeNameString + "." + name;
context.Description = XamlContextDescription.AtTag;
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;
}
}
}
// static void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
// bool isExplicit;
// AttributeValue value = MarkupExtensionParser.ParseValue(CompletionDataHelper.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? 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;
//
// string name = propType.StringValue;
//
// if (!name.Contains("."))
// name = typeNameString + "." + name;
//
// context.Description = XamlContextDescription.AtTag;
//
// 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;
// }
// }
// }
//
// 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) {
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)
public bool HandleKeyPressed(ITextEditor editor, char ch)
{
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;
throw new NotImplementedException();
}
}
}

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

@ -1,394 +0,0 @@ @@ -1,394 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using ICSharpCode.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding
{
using Task = System.Threading.Tasks.Task;
using Tasks = System.Threading.Tasks;
public class XamlColorizer : DocumentColorizingTransformer, ILineTracker, IDisposable
{
public struct Highlight {
public IMember Member { get; set; }
public HighlightingInfo Info { get; set; }
}
public sealed class HighlightTask {
// input
readonly string fileName;
readonly string lineText;
readonly int offset;
TextView textView;
ITextBuffer snapshot;
public HighlightTask(ITextEditor editor, DocumentLine currentLine, TextView textView)
{
this.fileName = editor.FileName;
this.textView = textView;
this.snapshot = editor.Document.CreateSnapshot();
this.lineText = textView.Document.GetText(currentLine);
this.offset = currentLine.Offset;
this.task = new Task(Process);
}
public HighlightTask(ITextEditor editor, DocumentLine currentLine, TextView textView, IList<Highlight> oldHighlightData)
: this(editor, currentLine, textView)
{
this.results = oldHighlightData;
}
IList<Highlight> results;
// output
public Highlight[] GetResults()
{
lock (this) {
if (results == null)
return null;
return results.ToArray();
}
}
readonly Task task;
public void Start()
{
task.Start();
}
public bool CompletedSuccessfully {
get {
return task.IsCompleted && task.Status == Tasks.TaskStatus.RanToCompletion;
}
}
public bool Invalid { get; set; }
void Process()
{
try {
List<Highlight> results = new List<Highlight>();
foreach (HighlightingInfo info in GetInfo()) {
IMember member = null;
// Commented out because task doesn't come with cancellation support in .NET 4.0 Beta 2
// (use CancellationToken instead)
// I didn't have to remove any call to task.Cancel(), so apparently this was dead code.
//if (task.IsCancellationRequested) {
// task.AcknowledgeCancellation();
// return;
//}
// TODO: implement cancellation support
if (!info.Token.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase)) {
MemberResolveResult rr = XamlResolver.Resolve(info.Token, info.Context) as MemberResolveResult;
member = (rr != null) ? rr.ResolvedMember : null;
}
results.Add(new Highlight() { Member = member, Info = info });
}
lock (this)
this.results = results;
WorkbenchSingleton.SafeThreadAsyncCall(InvokeRedraw);
} catch (Exception e) {
WorkbenchSingleton.SafeThreadAsyncCall(() => MessageService.ShowException(e));
}
}
void InvokeRedraw()
{
task.Wait();
textView.Redraw(this.offset, this.lineText.Length, DispatcherPriority.Background);
}
IEnumerable<HighlightingInfo> GetInfo()
{
int index = -1;
XamlContext context = null;
do {
if (index + 1 >= lineText.Length)
break;
index = lineText.IndexOfAny(index + 1, '=', '.');
if (index > -1) {
context = CompletionDataHelper.ResolveContext(snapshot, fileName, offset + index);
if (context.ActiveElement == null || context.InAttributeValueOrMarkupExtension || context.InCommentOrCData)
continue;
string propertyName;
string token;
int startIndex;
switch (context.Description) {
case XamlContextDescription.AtTag:
token = context.ActiveElement.Name;
int propertyNameIndex = token.IndexOf('.');
if (propertyNameIndex == -1)
continue;
propertyName = token.Substring(propertyNameIndex + 1);
startIndex = lineText.IndexOf(propertyName, index, StringComparison.Ordinal);
break;
case XamlContextDescription.InTag:
if (lineText[index] == '.' || context.Attribute == null)
continue;
token = propertyName = context.Attribute.Name;
startIndex = lineText.LastIndexOf(propertyName, index, StringComparison.Ordinal);
break;
default:
continue;
}
if (startIndex > -1) {
yield return new HighlightingInfo(token, startIndex, startIndex + propertyName.Length, offset, context);
}
}
} while (index > -1);
}
}
Dictionary<DocumentLine, HighlightTask> highlightCache = new Dictionary<DocumentLine, HighlightTask>();
public ITextEditor Editor { get; set; }
public AvalonEdit.Rendering.TextView TextView { get; set; }
public XamlColorizer(ITextEditor editor, TextView textView)
{
this.Editor = editor;
this.TextView = textView;
this.weakLineTracker = WeakLineTracker.Register(this.Editor.Document.GetService(typeof(TextDocument)) as TextDocument, this);
ParserService.LoadSolutionProjectsThreadEnded += ParserServiceLoadSolutionProjectsThreadEnded;
colorizers.Add(this);
}
static IList<XamlColorizer> colorizers = new List<XamlColorizer>();
public static void RefreshAll()
{
foreach (XamlColorizer colorizer in colorizers) {
colorizer.RebuildDocument();
colorizer.TextView.Redraw();
}
}
void ParserServiceLoadSolutionProjectsThreadEnded(object sender, EventArgs e)
{
WorkbenchSingleton.SafeThreadAsyncCall(
() => {
highlightCache.Clear();
TextView.Redraw();
}
);
}
WeakLineTracker weakLineTracker;
bool disposed;
public void Dispose()
{
if (!disposed) {
ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded;
weakLineTracker.Deregister();
colorizers.Remove(this);
}
disposed = true;
}
protected override void ColorizeLine(DocumentLine line)
{
if (!highlightCache.ContainsKey(line)) {
HighlightTask task = new HighlightTask(this.Editor, line, this.TextView);
task.Start();
highlightCache.Add(line, task);
} else {
HighlightTask task = highlightCache[line];
var results = task.GetResults();
if (results != null) {
foreach (var result in results) {
ColorizeMember(result.Info, line, result.Member);
}
}
}
ColorizeInvalidated();
}
void ColorizeMember(HighlightingInfo info, DocumentLine line, IMember member)
{
try {
Action<VisualLineElement> handler = null;
if (info.Token.StartsWith(info.Context.XamlNamespacePrefix + ":", StringComparison.Ordinal))
handler = HighlightProperty;
else if (info.Context.IgnoredXmlns.Any(item => info.Token.StartsWith(item + ":", StringComparison.Ordinal)))
handler = HighlightIgnored;
else if (member != null) {
if (member is IEvent)
handler = HighlightEvent;
else
handler = HighlightProperty;
} else {
if (info.Token.StartsWith("xmlns", StringComparison.OrdinalIgnoreCase) || info.Token.StartsWith(Utils.GetNamespacePrefix(CompletionDataHelper.MarkupCompatibilityNamespace, info.Context) + ":", StringComparison.OrdinalIgnoreCase))
handler = HighlightNamespaceDeclaration;
else if (info.Token.StartsWith("xml:", StringComparison.OrdinalIgnoreCase))
handler = HighlightProperty;
else
Core.LoggingService.Debug(info.Token + " not highlighted; line " + line.LineNumber);
}
if (handler != null)
ChangeLinePart(line.Offset + info.StartOffset, line.Offset + info.EndOffset, handler);
} catch (ArgumentOutOfRangeException) {}
}
void ColorizeInvalidated()
{
foreach (var item in highlightCache.ToArray()) {
if (item.Key.IsDeleted) {
highlightCache.Remove(item.Key);
continue;
}
if (item.Value.Invalid) {
var newTask = new HighlightTask(this.Editor, item.Key, this.TextView, item.Value.GetResults());
newTask.Start();
highlightCache[item.Key] = newTask;
}
}
}
void InvalidateLines(DocumentLine line)
{
DocumentLine current = line;
while (current != null) {
HighlightTask task;
if (highlightCache.TryGetValue(current, out task))
task.Invalid = true;
current = current.NextLine;
}
}
#region highlight helpers
void HighlightProperty(VisualLineElement element)
{
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.PropertyForegroundColor.ToBrush());
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.PropertyBackgroundColor.ToBrush());
}
void HighlightEvent(VisualLineElement element)
{
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.EventForegroundColor.ToBrush());
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.EventBackgroundColor.ToBrush());
}
void HighlightNamespaceDeclaration(VisualLineElement element)
{
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.NamespaceDeclarationForegroundColor.ToBrush());
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.NamespaceDeclarationBackgroundColor.ToBrush());
}
void HighlightIgnored(VisualLineElement element)
{
element.TextRunProperties.SetForegroundBrush(XamlBindingOptions.IgnoredForegroundColor.ToBrush());
element.TextRunProperties.SetBackgroundBrush(XamlBindingOptions.IgnoredBackgroundColor.ToBrush());
}
#endregion
#region ILineTracker implementation
public void BeforeRemoveLine(DocumentLine line)
{
InvalidateLines(line.NextLine);
}
public void SetLineLength(DocumentLine line, int newTotalLength)
{
InvalidateLines(line);
}
public void LineInserted(DocumentLine insertionPos, DocumentLine newLine)
{
InvalidateLines(newLine);
}
public void RebuildDocument()
{
highlightCache.Clear();
}
#endregion
public struct HighlightingInfo
{
string token;
int startOffset;
int endOffset;
int lineOffset;
XamlContext context;
public HighlightingInfo(string token, int startOffset, int endOffset, int lineOffset, XamlContext context)
{
if (token == null)
throw new ArgumentNullException("token");
if (startOffset < 0)
throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be greater 0");
if (endOffset < 0)
throw new ArgumentOutOfRangeException("endOffset", endOffset, "Value must be greater 0");
if (lineOffset < 0)
throw new ArgumentOutOfRangeException("lineOffset", lineOffset, "Value must be greater 0");
if (context == null)
throw new ArgumentNullException("context");
this.token = token;
this.startOffset = startOffset;
this.endOffset = endOffset;
this.lineOffset = lineOffset;
this.context = context;
}
public string Token {
get { return token; }
}
public int StartOffset {
get { return startOffset; }
}
public int EndOffset {
get { return endOffset; }
}
public int LineOffset {
get { return lineOffset; }
}
public XamlContext Context {
get { return context; }
}
}
}
}

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

@ -1,143 +0,0 @@ @@ -1,143 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Linq;
using ICSharpCode.SharpDevelop.Dom;
using System.Collections;
using System.Collections.Generic;
namespace ICSharpCode.XamlBinding
{
/// <summary>
/// Description of XamlCompilationUnit.
/// </summary>
public class XamlCompilationUnit : DefaultCompilationUnit
{
public XamlCompilationUnit(IProjectContent projectContent)
: base(projectContent)
{
}
public NodeWrapper TreeRootNode { get; set; }
/// <summary>
/// Creates a IReturnType looking for a class referenced in XAML.
/// </summary>
/// <param name="xmlNamespace">The XML namespace</param>
/// <param name="className">The class name</param>
/// <returns>A new IReturnType that will search the referenced type on demand.</returns>
public IReturnType CreateType(string xmlNamespace, string className)
{
if (string.IsNullOrEmpty(className) || className.Contains("."))
return null;
if (xmlNamespace.StartsWith("clr-namespace:", StringComparison.OrdinalIgnoreCase)) {
return CreateClrNamespaceType(this.ProjectContent, xmlNamespace, className);
} else {
return new XamlClassReturnType(this, xmlNamespace, className);
}
}
static IReturnType CreateClrNamespaceType(IProjectContent pc, string xmlNamespace, string className)
{
string namespaceName = GetNamespaceNameFromClrNamespace(xmlNamespace);
return new GetClassReturnType(pc, namespaceName + "." + className, 0);
}
static string GetNamespaceNameFromClrNamespace(string xmlNamespace)
{
string namespaceName = xmlNamespace.Substring("clr-namespace:".Length);
int pos = namespaceName.IndexOf(';');
if (pos >= 0) {
// we expect that the target type is also a reference of the project, so we
// can ignore the assembly part after the ;
namespaceName = namespaceName.Substring(0, pos);
}
return namespaceName;
}
/// <summary>
/// Finds a type referenced in XAML.
/// </summary>
/// <param name="xmlNamespace">The XML namespace</param>
/// <param name="className">The class name</param>
/// <returns>Returns the referenced type, or null if it cannot be found.</returns>
public IReturnType FindType(string xmlNamespace, string className)
{
return FindType(this.ProjectContent, xmlNamespace, className);
}
public static IReturnType FindType(IProjectContent pc, string xmlNamespace, string className)
{
if (pc == null)
throw new ArgumentNullException("pc");
if (xmlNamespace == null || className == null)
return null;
if (xmlNamespace.StartsWith("clr-namespace:", StringComparison.OrdinalIgnoreCase)) {
return CreateClrNamespaceType(pc, xmlNamespace, className);
}
else {
IReturnType type = FindTypeInAssembly(pc, xmlNamespace, className);
if (type != null)
return type;
foreach (IProjectContent p in pc.ReferencedContents) {
type = FindTypeInAssembly(p, xmlNamespace, className);
if (type != null)
return type;
}
return null;
}
}
static IReturnType FindTypeInAssembly(IProjectContent projectContent, string xmlNamespace, string className)
{
foreach (IAttribute att in projectContent.GetAssemblyAttributes()) {
if (att.PositionalArguments.Count == 2
&& att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") {
string namespaceName = att.PositionalArguments[1] as string;
if (xmlNamespace.Equals(att.PositionalArguments[0]) && namespaceName != null) {
IClass c = projectContent.GetClass(namespaceName + "." + className, 0);
if (c != null)
return c.DefaultReturnType;
}
}
}
return null;
}
public static IEnumerable<IClass> GetNamespaceMembers(IProjectContent pc, string xmlNamespace)
{
if (pc == null)
throw new ArgumentNullException("pc");
if (!string.IsNullOrEmpty(xmlNamespace)) {
if (xmlNamespace.StartsWith("clr-namespace:", StringComparison.OrdinalIgnoreCase))
return pc.GetNamespaceContents(GetNamespaceNameFromClrNamespace(xmlNamespace)).OfType<IClass>();
else {
var list = new List<ICompletionEntry>();
AddNamespaceMembersInAssembly(pc, xmlNamespace, list);
foreach (IProjectContent p in pc.ReferencedContents) {
AddNamespaceMembersInAssembly(p, xmlNamespace, list);
}
return list.OfType<IClass>();
}
}
return Enumerable.Empty<IClass>();
}
static void AddNamespaceMembersInAssembly(IProjectContent projectContent, string xmlNamespace, List<ICompletionEntry> list)
{
foreach (IAttribute att in projectContent.GetAssemblyAttributes()) {
if (att.PositionalArguments.Count == 2
&& att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") {
string namespaceName = att.PositionalArguments[1] as string;
if (xmlNamespace.Equals(att.PositionalArguments[0]) && namespaceName != null) {
projectContent.AddNamespaceContents(list, namespaceName, projectContent.Language, false);
}
}
}
}
}
}

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

@ -1,309 +0,0 @@ @@ -1,309 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
namespace ICSharpCode.XamlBinding
{
class XamlCodeCompletionItem : CodeCompletionItem
{
public XamlCodeCompletionItem(IEntity entity, string prefix)
: base(entity)
{
if (string.IsNullOrEmpty(prefix))
this.Text = entity.Name;
else
this.Text = prefix + ":" + entity.Name;
this.Content = this.Text;
}
public XamlCodeCompletionItem(IEntity entity)
: base(entity)
{
this.Text = entity.Name;
this.Content = this.Text;
}
public XamlCodeCompletionItem(string text, IEntity entity)
: base(entity)
{
this.Text = text;
this.Content = this.Text;
}
public XamlCodeCompletionItem(IEntity entity, string prefix, string className)
: base(entity)
{
if (string.IsNullOrEmpty(prefix))
this.Text = className + "." + entity.Name;
else
this.Text = prefix + ":" + className + "." + entity.Name;
this.Content = this.Text;
}
public override string ToString()
{
return "[" + this.Text + "]";
}
}
class XamlLazyValueCompletionItem : XamlCodeCompletionItem
{
bool addType;
public XamlLazyValueCompletionItem(IEntity entity, string text, bool addType)
: base(entity)
{
this.addType = addType;
this.Text = text;
this.Content = this.Text;
}
public override void Complete(CompletionContext context)
{
if (addType) {
MarkAsUsed();
string newText = Entity.DeclaringType.Name + "." + Text;
context.Editor.Document.Replace(context.StartOffset, context.Length, newText);
context.EndOffset = context.StartOffset + newText.Length;
} else
base.Complete(context);
}
}
class XamlCompletionItem : DefaultCompletionItem
{
string prefix, @namespace, name;
public XamlCompletionItem(string prefix, string @namespace, string name)
: base(prefix + ":" + name)
{
this.prefix = prefix;
this.@namespace = @namespace;
this.name = name;
this.Image = ClassBrowserIconService.Namespace;
}
}
class SpecialCompletionItem : DefaultCompletionItem
{
public SpecialCompletionItem(string name)
: base(name)
{
this.Image = ClassBrowserIconService.Namespace;
}
}
class SpecialValueCompletionItem : DefaultCompletionItem
{
public SpecialValueCompletionItem(string name)
: base(name)
{
this.Image = ClassBrowserIconService.Const;
}
}
class XmlnsCompletionItem : DefaultCompletionItem
{
string @namespace, assembly;
bool isUrl;
public bool IsUrl {
get { return isUrl; }
}
public XmlnsCompletionItem(string @namespace, string assembly)
: base(@namespace + " (" + assembly + ")")
{
this.@namespace = @namespace;
this.assembly = assembly;
this.Image = ClassBrowserIconService.Namespace;
}
public XmlnsCompletionItem(string @namespace, bool isUrl)
: base(@namespace)
{
this.@namespace = @namespace;
this.isUrl = isUrl;
this.assembly = string.Empty;
this.Image = ClassBrowserIconService.Namespace;
}
public string Namespace {
get { return @namespace; }
}
public string Assembly {
get { return assembly; }
}
public override void Complete(CompletionContext context)
{
if (isUrl)
base.Complete(context);
else {
ITextEditor editor = context.Editor;
string newText = "clr-namespace:" + @namespace;
if (!string.IsNullOrEmpty(assembly))
newText += ";assembly=" + assembly;
editor.Document.Replace(context.StartOffset, context.Length, newText);
context.EndOffset = context.StartOffset + newText.Length;
}
}
}
class NewEventCompletionItem : DefaultCompletionItem
{
IEvent eventType;
public IEvent EventType {
get { return eventType; }
}
string targetName;
public string TargetName {
get { return targetName; }
}
public string HandlerName { get; private set; }
public NewEventCompletionItem(IEvent eventType, string targetName)
: base(StringParser.Parse("${res:AddIns.XamlBinding.NewEventHandlerItem}"))
{
this.eventType = eventType;
this.targetName = targetName;
this.HandlerName = ParseNamePattern(this.TargetName, this.EventType.Name);
this.Image = ClassBrowserIconService.Event;
}
public override void Complete(CompletionContext context)
{
context.Editor.Document.Replace(context.StartOffset, context.Length, this.HandlerName);
context.EndOffset = context.StartOffset + this.HandlerName.Length;
}
static readonly Regex namePatternRegex = new Regex("%[A-z0-9]*%", RegexOptions.Compiled);
public static string ParseNamePattern(string objectName, string eventName)
{
string name = XamlBindingOptions.EventHandlerNamePattern;
while (namePatternRegex.IsMatch(name)) {
Match match = namePatternRegex.Match(name);
switch (match.Value.ToUpperInvariant()) {
case "%OBJECT%":
if (char.IsUpper(match.Value[1]))
objectName = objectName.ToUpperInvariant()[0] + objectName.Substring(1, objectName.Length - 1);
else
objectName = objectName.ToLowerInvariant()[0] + objectName.Substring(1, objectName.Length - 1);
name = name.Replace(match.Index, match.Length, objectName);
break;
case "%EVENT%":
if (char.IsUpper(match.Value[1]))
eventName = eventName.ToUpperInvariant()[0] + eventName.Substring(1, eventName.Length - 1);
else
eventName = eventName.ToLowerInvariant()[0] + eventName.Substring(1, eventName.Length - 1);
name = name.Replace(match.Index, match.Length, eventName);
break;
case "%%":
name = name.Replace(match.Index, match.Length, "%");
break;
default:
throw new ArgumentException("Pattern identifier invalid", match.Value);
}
}
return name;
}
}
class MarkupExtensionInsightItem : IInsightItem
{
IMethod ctor;
public MarkupExtensionInsightItem(IMethod entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
this.ctor = entity;
}
string headerText;
bool descriptionCreated;
string description;
public object Header {
get {
if (headerText == null) {
IAmbience ambience = AmbienceService.GetCurrentAmbience();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
headerText = ambience.Convert(ctor);
headerText = headerText.Insert(headerText.LastIndexOf(')'), (ctor.Parameters.Count > 0 ? ", " : "") + "Named Parameters ...");
}
return headerText;
}
}
public object Content {
get {
if (!descriptionCreated) {
string entityDoc = ctor.Documentation;
if (!string.IsNullOrEmpty(entityDoc)) {
description = CodeCompletionItem.ConvertDocumentation(entityDoc);
}
descriptionCreated = true;
}
return description;
}
}
}
class MemberInsightItem : IInsightItem
{
string insightText;
string headerText;
string description;
bool descriptionCreated;
IMember member;
public MemberInsightItem(IMember member, string insightText)
{
this.member = member;
this.insightText = insightText;
}
public object Header {
get {
if (headerText == null) {
headerText = this.member.Name + "=\"" + insightText + "\"";
}
return headerText;
}
}
public object Content {
get {
if (!descriptionCreated) {
string entityDoc = member.Documentation;
if (!string.IsNullOrEmpty(entityDoc)) {
description = CodeCompletionItem.ConvertDocumentation(entityDoc);
}
descriptionCreated = true;
}
return description;
}
}
}
}

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

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

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

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

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

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

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

@ -1,75 +0,0 @@ @@ -1,75 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Text;
using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding
{
/// <summary>
/// Description of XamlExpressionFinder.
/// </summary>
public class XamlExpressionFinder : IExpressionFinder
{
public static readonly XamlExpressionFinder Instance = new XamlExpressionFinder();
static bool IsValidChar(char c)
{
return char.IsLetterOrDigit(c) || c == '_' || c == ':' || c == '.';
}
public ExpressionResult FindExpression(string text, int offset)
{
int pos = offset - 1;
while (pos > 0 && IsValidChar(text[pos])) {
pos--;
}
pos++;
return new ExpressionResult(text.Substring(pos, offset - pos), GetContext(text, offset));
}
public ExpressionResult FindFullExpression(string text, int offset)
{
int start = offset - 1;
while (start > 0 && IsValidChar(text[start])) {
start--;
}
start++;
while (offset < text.Length && IsValidChar(text[offset])) {
offset++;
}
var startLocation = Utils.GetLocationInfoFromOffset(text, start);
var endLocation = Utils.GetLocationInfoFromOffset(text, offset);
return new ExpressionResult(text.Substring(start, offset - start), GetContext(text, offset)) { Region = new DomRegion(startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column) };
}
public string RemoveLastPart(string expression)
{
return "";
}
static ExpressionContext GetContext(string text, int offset)
{
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(text, offset);
if (path == null || path.Elements.Count == 0) {
if (offset > 0 && text[offset - 1] == '<')
return XamlExpressionContext.Empty;
else
return ExpressionContext.Default;
}
string attributeName = XmlParser.GetAttributeNameAtIndex(text, offset);
if (!string.IsNullOrEmpty(attributeName)) {
return new XamlExpressionContext(path, attributeName, XmlParser.IsInsideAttributeValue(text, offset));
}
else {
return new XamlExpressionContext(path, null, false);
}
}
}
}

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

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

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

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

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

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

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

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Xml;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.XamlBinding
{
public sealed class XamlParsedFile : IParsedFile
{
FileName fileName;
AXmlDocument document;
List<Error> errors;
ITypeDefinition xamlTypeDefinition;
XamlParsedFile(FileName fileName, AXmlDocument document)
{
this.fileName = fileName;
this.document = document;
this.errors = new List<Error>();
}
public static XamlParsedFile Create(FileName fileName, string fileContent, AXmlDocument document)
{
XamlParsedFile file = new XamlParsedFile(fileName, document);
file.errors.AddRange(document.SyntaxErrors.Select(err => new Error(ErrorType.Error, err.Description)));
file.lastWriteTime = DateTime.UtcNow;
return file;
}
public string FileName {
get { return fileName; }
}
DateTime lastWriteTime = DateTime.UtcNow;
public DateTime LastWriteTime {
get { return lastWriteTime; }
}
public IList<IUnresolvedTypeDefinition> TopLevelTypeDefinitions {
get {
throw new NotImplementedException();
}
}
public IList<IUnresolvedAttribute> AssemblyAttributes {
get { return EmptyList<IUnresolvedAttribute>.Instance; }
}
public IList<IUnresolvedAttribute> ModuleAttributes {
get { return EmptyList<IUnresolvedAttribute>.Instance; }
}
public IList<Error> Errors {
get { return errors; }
}
public IUnresolvedTypeDefinition GetTopLevelTypeDefinition(TextLocation location)
{
throw new NotImplementedException();
}
public IUnresolvedTypeDefinition GetInnermostTypeDefinition(TextLocation location)
{
throw new NotImplementedException();
}
public IUnresolvedMember GetMember(TextLocation location)
{
throw new NotImplementedException();
}
public ITypeResolveContext GetTypeResolveContext(ICompilation compilation, TextLocation loc)
{
throw new NotImplementedException();
}
}
}

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

@ -2,15 +2,23 @@ @@ -2,15 +2,23 @@
// 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.AvalonEdit.Xml;
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.Dom;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.XamlBinding
{
@ -27,10 +35,10 @@ namespace ICSharpCode.XamlBinding @@ -27,10 +35,10 @@ namespace ICSharpCode.XamlBinding
set { lexerTags = value; }
}
public LanguageProperties Language
{
get { return LanguageProperties.CSharp; }
}
// public LanguageProperties Language
// {
// get { return LanguageProperties.CSharp; }
// }
public XamlParser()
{
@ -47,98 +55,110 @@ namespace ICSharpCode.XamlBinding @@ -47,98 +55,110 @@ namespace ICSharpCode.XamlBinding
}
AXmlParser parser = new AXmlParser();
volatile ITextBufferVersion lastParsedVersion;
volatile ITextSourceVersion lastParsedVersion;
/// <summary>
/// Parse the given text and enter read lock.
/// No parsing is done if the text is older than seen before.
/// </summary>
public IDisposable ParseAndLock(ITextBuffer fileContent)
{
// Copy to ensure thread-safety
var lastVer = this.lastParsedVersion;
if (lastVer == null || // First parse
fileContent.Version == null || // Versioning not supported
!fileContent.Version.BelongsToSameDocumentAs(lastVer) || // Different document instance? Can happen after closing and reopening of file.
fileContent.Version.CompareAge(lastVer) > 0) // Is fileContent newer?
{
parser.Lock.EnterWriteLock();
// Double check, now that we are thread-safe
lastVer = this.lastParsedVersion;
if (lastVer == null || fileContent.Version == null || !fileContent.Version.BelongsToSameDocumentAs(lastVer)) {
// First parse or versioning not supported
using (DebugTimer.Time("normal parse"))
parser.Parse(fileContent.Text, null);
this.lastParsedVersion = fileContent.Version;
} else if (fileContent.Version.CompareAge(lastParsedVersion) > 0) {
// Incremental parse
var changes = lastParsedVersion.GetChangesTo(fileContent.Version).
Select(c => new DocumentChangeEventArgs(c.Offset, c.RemovedText, c.InsertedText));
using (DebugTimer.Time("incremental parse"))
parser.Parse(fileContent.Text, changes);
this.lastParsedVersion = fileContent.Version;
} else {
// fileContent is older - no need to parse
}
parser.Lock.EnterReadLock();
parser.Lock.ExitWriteLock();
} else {
// fileContent is older - no need to parse
parser.Lock.EnterReadLock();
}
return new CallbackOnDispose(() => parser.Lock.ExitReadLock());
}
public ICompilationUnit Parse(IProjectContent projectContent, string fileName, ITextBuffer fileContent)
// public IDisposable ParseAndLock(ITextSource fileContent)
// {
// // Copy to ensure thread-safety
// var lastVer = this.lastParsedVersion;
// if (lastVer == null || // First parse
// fileContent.Version == null || // Versioning not supported
// !fileContent.Version.BelongsToSameDocumentAs(lastVer) || // Different document instance? Can happen after closing and reopening of file.
// fileContent.Version.CompareAge(lastVer) > 0) // Is fileContent newer?
// {
// parser.Lock.EnterWriteLock();
// // Double check, now that we are thread-safe
// lastVer = this.lastParsedVersion;
// if (lastVer == null || fileContent.Version == null || !fileContent.Version.BelongsToSameDocumentAs(lastVer)) {
// // First parse or versioning not supported
// using (DebugTimer.Time("normal parse"))
// parser.Parse(fileContent.Text, null);
// this.lastParsedVersion = fileContent.Version;
// } else if (fileContent.Version.CompareAge(lastParsedVersion) > 0) {
// // Incremental parse
// var changes = lastParsedVersion.GetChangesTo(fileContent.Version).
// Select(c => new DocumentChangeEventArgs(c.Offset, c.RemovedText, c.InsertedText));
// using (DebugTimer.Time("incremental parse"))
// parser.Parse(fileContent.Text, changes);
// this.lastParsedVersion = fileContent.Version;
// } else {
// // fileContent is older - no need to parse
// }
// parser.Lock.EnterReadLock();
// parser.Lock.ExitWriteLock();
// } else {
// // fileContent is older - no need to parse
// parser.Lock.EnterReadLock();
// }
// return new CallbackOnDispose(() => parser.Lock.ExitReadLock());
// }
//
// 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;
using (ParseAndLock(fileContent)) {
var document = parser.LastDocument;
CompilationUnitCreatorVisitor visitor =
new CompilationUnitCreatorVisitor(projectContent, fileContent.Text, fileName, lexerTags);
document.AcceptVisitor(visitor);
compilationUnit = visitor.CompilationUnit;
AXmlParser parser = new AXmlParser();
AXmlDocument document;
try {
document = parser.ParseIncremental(parserState, fileContent, out parserState);
} catch (Exception ex) {
LoggingService.Error(ex);
document = null; // TODO empty document?
}
XamlParsedFile parsedFile = XamlParsedFile.Create(fileName, fileContent.Text, document);
// 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;
// TODO if (fullParseInformationRequested)
return new ParseInformation(parsedFile, false);
}
/// <summary>
/// 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)
public ResolveResult Resolve(ParseInformation parseInfo, TextLocation location, ICompilation compilation, CancellationToken cancellationToken)
{
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 @@ @@ -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 @@ @@ -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