Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit ee249e0

Browse files
Merge branch 'master' of github.com:icsharpcode/SharpDevelop
2 parents 2966668 + 4d8c808 commit ee249e0

10 files changed

Lines changed: 167 additions & 58 deletions

File tree

src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
127127
if ((e.PropertyName == "Parent") || (e.PropertyName == null)) {
128128
// All properties might have changed -> update everything
129129
cachedOptions = CreateCachedOptions();
130-
OnPropertyChanged(e.PropertyName);
131130
} else {
132131
// Some other property has changed, check if we have our own value for it
133132
if (!activeOptions.Contains(e.PropertyName)) {
@@ -136,7 +135,6 @@ private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
136135
if (propertyInfo != null) {
137136
var val = GetEffectiveOption(e.PropertyName);
138137
propertyInfo.SetValue(cachedOptions, val);
139-
OnPropertyChanged(e.PropertyName);
140138
}
141139
}
142140
}
@@ -265,14 +263,16 @@ public void Load(Properties parentProperties)
265263
if (parentProperties == null)
266264
throw new ArgumentNullException("parentProperties");
267265

268-
Properties formatProperties = parentProperties.NestedProperties("CSharpFormatting");
269-
if (formatProperties != null) {
270-
foreach (var key in formatProperties.Keys) {
271-
try {
272-
object val = formatProperties.Get(key, (object) null);
273-
SetOption(key, val);
274-
} catch (Exception) {
275-
// Silently ignore loading error, then this property will be "as parent" automatically
266+
if (parentProperties.Contains("CSharpFormatting")) {
267+
Properties formatProperties = parentProperties.NestedProperties("CSharpFormatting");
268+
if (formatProperties != null) {
269+
foreach (var key in formatProperties.Keys) {
270+
try {
271+
object val = formatProperties.Get(key, (object)null);
272+
SetOption(key, val);
273+
} catch (Exception) {
274+
// Silently ignore loading error, then this property will be "as parent" automatically
275+
}
276276
}
277277
}
278278
}

src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,15 @@ public CSharpSolutionFormattingOptionPanel()
6464
internal partial class CSharpFormattingOptionPanel : OptionPanel
6565
{
6666
readonly CSharpFormattingOptionsPersistence persistenceHelper;
67+
bool isDirty;
6768

6869
public CSharpFormattingOptionPanel(CSharpFormattingOptionsPersistence persistenceHelper, bool allowPresets)
6970
{
7071
if (persistenceHelper == null)
7172
throw new ArgumentNullException("persistenceHelper");
7273

7374
this.persistenceHelper = persistenceHelper;
75+
this.isDirty = false;
7476
InitializeComponent();
7577

7678
formattingEditor.AllowPresets = allowPresets;
@@ -79,12 +81,20 @@ public CSharpFormattingOptionPanel(CSharpFormattingOptionsPersistence persistenc
7981
public override void LoadOptions()
8082
{
8183
base.LoadOptions();
82-
formattingEditor.OptionsContainer = persistenceHelper.StartEditing();
84+
formattingEditor.OptionsContainer = persistenceHelper.StartEditing();
85+
formattingEditor.OptionsContainer.PropertyChanged += ContainerPropertyChanged;
86+
}
87+
88+
void ContainerPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
89+
{
90+
isDirty = true;
8391
}
8492

8593
public override bool SaveOptions()
8694
{
87-
return persistenceHelper.Save() && base.SaveOptions();
95+
// Only save container, if some option really has changed
96+
formattingEditor.OptionsContainer.PropertyChanged -= ContainerPropertyChanged;
97+
return (!isDirty || persistenceHelper.Save()) && base.SaveOptions();
8898
}
8999
}
90100
}

src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataGenerator.cs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,26 @@ public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, b
122122
{
123123
if (context.ParseInformation == null)
124124
return EmptyList<ICompletionItem>.Instance;
125+
125126
List<ICompletionItem> result = new List<ICompletionItem>();
126127
AXmlElement last = context.ParentElement;
127128
ITextEditor editor = context.Editor;
128129
compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
129130
IUnresolvedFile file = context.ParseInformation.UnresolvedFile;
130-
var items = GetClassesFromContext(context);
131+
132+
foreach (string item in XamlConst.GetAllowedItems(context)) {
133+
result.Add(new XamlCompletionItem(item));
134+
}
135+
131136
IType rt = null;
132137

133138
if (last != null) {
139+
if (string.Equals(last.Prefix, context.XamlNamespacePrefix, StringComparison.OrdinalIgnoreCase)) {
140+
if (string.Equals(last.LocalName, "Members", StringComparison.OrdinalIgnoreCase))
141+
return result;
142+
if (string.Equals(last.LocalName, "Code", StringComparison.OrdinalIgnoreCase))
143+
return result;
144+
}
134145
// If we have an element that is not a property or an incomplete
135146
// definition => interpret element as a type.
136147
XamlResolver resolver = new XamlResolver(compilation);
@@ -172,6 +183,8 @@ public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, b
172183
.ToList();
173184
}
174185

186+
var items = GetClassesFromContext(context);
187+
175188
foreach (var ns in items) {
176189
foreach (ITypeDefinition td in ns.Value) {
177190
if (td.Kind != TypeKind.Class && (!includeAbstract || td.Kind != TypeKind.Interface))
@@ -198,15 +211,6 @@ public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, b
198211
// result.Add(new XamlCodeCompletionItem(itemClass, last.Prefix));
199212
// }
200213

201-
var xamlItems = XamlConst.XamlNamespaceAttributes.AsEnumerable();
202-
203-
if (XamlConst.EnableXaml2009)
204-
xamlItems = XamlConst.XamlBuiltInTypes.Concat(xamlItems);
205-
206-
foreach (string item in xamlItems) {
207-
result.Add(new XamlCompletionItem(context.XamlNamespacePrefix + ":" + item));
208-
}
209-
210214
return result;
211215
}
212216

@@ -266,8 +270,11 @@ IList<ICompletionItem> CreateAttributeList(XamlCompletionContext context, bool i
266270
string xamlPrefix = context.XamlNamespacePrefix;
267271
string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":";
268272

269-
if (lastElement.Prefix == context.XamlNamespacePrefix && XamlConst.IsBuiltin(lastElement.LocalName))
270-
return EmptyList<ICompletionItem>.Instance;
273+
if (context.Description == XamlContextDescription.InTag)
274+
list.AddRange(XamlConst.GetAllowedItems(context).Select(item => new XamlCompletionItem(item)));
275+
276+
if (string.Equals(lastElement.Prefix, context.XamlNamespacePrefix, StringComparison.OrdinalIgnoreCase) && XamlConst.IsBuiltin(lastElement.LocalName))
277+
return list;
271278

272279
if (lastElement.LocalName.EndsWith(".", StringComparison.OrdinalIgnoreCase) || context.PressedKey == '.') {
273280
if (type.Kind == TypeKind.Unknown)
@@ -279,16 +286,9 @@ IList<ICompletionItem> CreateAttributeList(XamlCompletionContext context, bool i
279286
}
280287
AddAttachedProperties(type.GetDefinition(), list);
281288
} else {
282-
if (type.Kind == TypeKind.Unknown) {
283-
list.Add(new XamlCompletionItem(xKey + "Uid"));
284-
} else {
289+
if (type.Kind != TypeKind.Unknown) {
285290
AddAttributes(type, list, includeEvents);
286291
list.AddRange(GetListOfAttached(context, null, includeEvents, true));
287-
list.AddRange(
288-
XamlConst.XamlNamespaceAttributes
289-
.Where(localName => XamlConst.IsAttributeAllowed(context.InRoot, localName))
290-
.Select(item => new XamlCompletionItem(xKey + item))
291-
);
292292
}
293293
}
294294

@@ -384,11 +384,11 @@ public IEnumerable<ICompletionItem> MemberCompletion(XamlCompletionContext conte
384384
ITextEditor editor = context.Editor;
385385
compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
386386

387+
string xamlPrefix = context.XamlNamespacePrefix;
388+
string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":";
389+
387390
if (type.Name == typeof(System.Nullable<>).Name) {
388-
string nullExtensionName = "Null";
389-
if (!string.IsNullOrEmpty(context.XamlNamespacePrefix))
390-
nullExtensionName = context.XamlNamespacePrefix + ":" + nullExtensionName;
391-
yield return new XamlCompletionItem("{" + nullExtensionName + "}");
391+
yield return new XamlCompletionItem("{" + xKey + "Null}");
392392
type = type.TypeArguments.FirstOrDefault();
393393
if (type == null) yield break;
394394
}
@@ -397,6 +397,18 @@ public IEnumerable<ICompletionItem> MemberCompletion(XamlCompletionContext conte
397397

398398
if (definition == null) yield break;
399399

400+
definition.IsCollectionType();
401+
402+
switch (definition.KnownTypeCode) {
403+
case KnownTypeCode.Array:
404+
case KnownTypeCode.ICollection:
405+
case KnownTypeCode.ICollectionOfT:
406+
case KnownTypeCode.IEnumerable:
407+
case KnownTypeCode.IEnumerableOfT:
408+
yield return new XamlCompletionItem("{" + xKey + "Array}");
409+
break;
410+
}
411+
400412
switch (definition.Kind) {
401413
case TypeKind.Class:
402414
IType typeName;

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,17 @@ public static bool IsListType(this IType thisValue)
398398
return thisValue.GetAllBaseTypeDefinitions().Any(t => t.FullName == "System.Collections.IList");
399399
}
400400

401+
public static bool Implements(this IType thisValue, IType interfaceType)
402+
{
403+
if (thisValue == null)
404+
throw new ArgumentNullException("thisValue");
405+
if (interfaceType == null)
406+
throw new ArgumentNullException("interfaceType");
407+
if (interfaceType.Kind != TypeKind.Interface)
408+
throw new ArgumentException("must be TypeKind.Interface", "interfaceType");
409+
return thisValue.GetAllBaseTypes().Any(t => t.Equals(interfaceType));
410+
}
411+
401412
public static bool HasAttached(this ITypeDefinition thisValue, bool lookForProperties, bool lookForEvents)
402413
{
403414
if (!lookForProperties && !lookForEvents)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public override void Complete(CompletionContext context, ICompletionItem item)
8383
XamlCompletionItem cItem = item as XamlCompletionItem;
8484

8585
if (xamlContext.Description == XamlContextDescription.InTag) {
86-
if (cItem.Entity.SymbolKind == SymbolKind.Property || cItem.Entity.SymbolKind == SymbolKind.Event) {
86+
if (cItem.Entity == null || cItem.Entity.SymbolKind == SymbolKind.Property || cItem.Entity.SymbolKind == SymbolKind.Event) {
8787
context.Editor.Document.Insert(context.EndOffset, "=\"\"");
8888
context.CompletionCharHandled = context.CompletionChar == '=';
8989
context.Editor.Caret.Offset--;

src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlConst.cs

Lines changed: 85 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
using System.Collections.Generic;
2121
using System.Collections.ObjectModel;
2222
using System.Linq;
23+
using System.Windows;
24+
using System.Xml.Serialization;
25+
using ICSharpCode.NRefactory.TypeSystem;
26+
using ICSharpCode.NRefactory.Semantics;
27+
using ICSharpCode.SharpDevelop;
2328

2429
namespace ICSharpCode.XamlBinding
2530
{
@@ -28,33 +33,22 @@ namespace ICSharpCode.XamlBinding
2833
/// </summary>
2934
public static class XamlConst
3035
{
31-
public const bool EnableXaml2009 = true;
32-
3336
// [XAML 2009]
3437
public static readonly List<string> XamlBuiltInTypes = new List<string> {
3538
"Object", "Boolean", "Char", "String", "Decimal", "Single", "Double",
3639
"Int16", "Int32", "Int64", "TimeSpan", "Uri", "Byte", "Array", "List", "Dictionary",
37-
// This is no built in type, but a markup extension
3840
"Reference"
3941
};
4042

4143
public static readonly ReadOnlyCollection<string> XamlNamespaceAttributes = new List<string> {
42-
"Class", "ClassModifier", "FieldModifier", "Name", "Subclass", "TypeArguments", "Uid", "Key"
43-
}.AsReadOnly();
44-
45-
public static readonly ReadOnlyCollection<string> RootOnlyElements = new List<string> {
46-
"Class", "ClassModifier", "Subclass"
47-
}.AsReadOnly();
48-
49-
public static readonly ReadOnlyCollection<string> ChildOnlyElements = new List<string> {
50-
"FieldModifier"
44+
"Class", "ClassModifier", "FieldModifier", "Name", "Subclass", "TypeArguments", "Uid", "Key", "Shared"
5145
}.AsReadOnly();
5246

5347
/// <summary>
5448
/// values: http://schemas.microsoft.com/winfx/2006/xaml/presentation,
5549
/// http://schemas.microsoft.com/netfx/2007/xaml/presentation
5650
/// </summary>
57-
public static readonly string[] WpfXamlNamespaces = new[] {
51+
public static readonly string[] WpfXamlNamespaces = {
5852
"http://schemas.microsoft.com/winfx/2006/xaml/presentation",
5953
"http://schemas.microsoft.com/netfx/2007/xaml/presentation"
6054
};
@@ -88,11 +82,86 @@ public static bool IsBuiltin(string localName)
8882
}
8983

9084
/// <summary>
91-
/// Returns true if the given attribute is allowed in the current element.
85+
/// Returns the list of allow XAML2009 completion items.
9286
/// </summary>
93-
public static bool IsAttributeAllowed(bool inRoot, string localName)
87+
public static IEnumerable<string> GetAllowedItems(XamlCompletionContext context)
9488
{
95-
return inRoot ? !ChildOnlyElements.Contains(localName) : !RootOnlyElements.Contains(localName);
89+
string xamlPrefix = context.XamlNamespacePrefix;
90+
string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":";
91+
var compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName);
92+
var resolver = new XamlAstResolver(compilation, context.ParseInformation);
93+
// TODO : add support for x:Key as attribute element (XAML 2009 only)
94+
95+
switch (context.Description) {
96+
case XamlContextDescription.AtTag:
97+
if (context.ParentElement != null && string.Equals(context.ParentElement.Name, xKey + "Members", StringComparison.OrdinalIgnoreCase)) {
98+
yield return xKey + "Member";
99+
yield return xKey + "Property";
100+
} else if (context.ParentElement == context.RootElement && context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase))) {
101+
yield return xKey + "Code";
102+
yield return xKey + "Members";
103+
} else {
104+
if (context.ParentElement != null && string.Equals(context.ParentElement.Name, xKey + "Code", StringComparison.OrdinalIgnoreCase))
105+
yield break;
106+
yield return xKey + "Array";
107+
yield return xKey + "Boolean";
108+
yield return xKey + "Byte";
109+
yield return xKey + "Char";
110+
yield return xKey + "Decimal";
111+
yield return xKey + "Dictionary";
112+
yield return xKey + "Double";
113+
yield return xKey + "Int16";
114+
yield return xKey + "Int32";
115+
yield return xKey + "Int64";
116+
yield return xKey + "List";
117+
yield return xKey + "Object";
118+
yield return xKey + "Reference";
119+
yield return xKey + "Single";
120+
yield return xKey + "String";
121+
yield return xKey + "TimeSpan";
122+
yield return xKey + "Uri";
123+
if (context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase)))
124+
yield return xKey + "Members";
125+
}
126+
break;
127+
case XamlContextDescription.InTag:
128+
yield return xKey + "Uid";
129+
if (context.InRoot) {
130+
yield return xKey + "Class";
131+
yield return xKey + "ClassModifier";
132+
yield return xKey + "Subclass";
133+
yield return xKey + "Name";
134+
} else {
135+
var resourceDictionaryType = compilation.FindType(typeof(ResourceDictionary));
136+
if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Array", StringComparison.OrdinalIgnoreCase)) {
137+
yield return "Type";
138+
} else if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Member", StringComparison.OrdinalIgnoreCase)) {
139+
yield return "Name";
140+
} else if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Property", StringComparison.OrdinalIgnoreCase)) {
141+
yield return "Name";
142+
yield return "Type";
143+
} else if (context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase))) {
144+
yield return xKey + "FieldModifier";
145+
yield return xKey + "Name";
146+
} else {
147+
yield return xKey + "Name";
148+
}
149+
150+
if (context.ParentElement != null) {
151+
var rr = resolver.ResolveElement(context.ParentElement);
152+
if (rr != null) {
153+
if (rr.Type.Equals(resourceDictionaryType)) {
154+
yield return xKey + "Key";
155+
yield return xKey + "Shared";
156+
} else if (rr.Type.TypeParameterCount > 0) {
157+
yield return xKey + "TypeArguments";
158+
}
159+
}
160+
}
161+
}
162+
break;
163+
}
164+
yield break;
96165
}
97166
}
98167
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public class XamlContext
9494
{
9595
public AXmlElement ActiveElement { get; set; }
9696
public AXmlElement ParentElement { get; set; }
97+
public AXmlElement RootElement { get; set; }
9798
public ReadOnlyCollection<AXmlElement> Ancestors { get; set; }
9899
public AXmlAttribute Attribute { get; set; }
99100
public AttributeValue AttributeValue { get; set; }
@@ -131,6 +132,7 @@ public XamlCompletionContext(XamlContext context)
131132
this.AttributeValue = context.AttributeValue;
132133
this.Description = context.Description;
133134
this.ParentElement = context.ParentElement;
135+
this.RootElement = context.RootElement;
134136
this.ParseInformation = context.ParseInformation;
135137
this.RawAttributeValue = context.RawAttributeValue;
136138
this.ValueStartOffset = context.ValueStartOffset;

0 commit comments

Comments
 (0)