-
Notifications
You must be signed in to change notification settings - Fork 3
/
RimworldXmlReference.cs
130 lines (108 loc) · 4.59 KB
/
RimworldXmlReference.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using System.Linq;
using JetBrains.Annotations;
using JetBrains.Metadata.Reader.API;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp.Conversions;
using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve;
using JetBrains.ReSharper.Psi.Resolve;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.Util;
namespace ReSharperPlugin.RimworldDev.TypeDeclaration;
/**
* I don't really remember what this is doing or how it works.
*
* @TODO: Re-read and document this
*/
public class RimworldXmlReference :
TreeReferenceBase<ITreeNode>,
ICompletableReference,
IReference,
IUserDataHolder
{
private readonly ISymbolFilter myExactNameFilter;
private readonly ISymbolFilter myPropertyFilter;
private readonly IDeclaredElement myTypeElement;
[CanBeNull]
private readonly string overrideName;
public RimworldXmlReference(IDeclaredElement typeElement, [NotNull] ITreeNode owner)
: base(owner)
{
myTypeElement = typeElement;
myExactNameFilter = new ExactNameFilter(myOwner.GetText());
myPropertyFilter = new PredicateFilter(FilterToApplicableProperties);
}
public RimworldXmlReference(IDeclaredElement typeElement, [NotNull] ITreeNode owner, string overrideName)
: this(typeElement, owner)
{
this.overrideName = overrideName;
}
private static bool FilterToApplicableProperties([NotNull] ISymbolInfo symbolInfo)
{
if (!(symbolInfo.GetDeclaredElement() is ITypeMember declaredElement))
return false;
var predefinedType = declaredElement.Module.GetPredefinedType();
if (!(declaredElement is IProperty property) || property.GetAccessRights() != AccessRights.PUBLIC || !property.IsStatic)
return false;
var typeConversionRule = declaredElement.Module.GetTypeConversionRule();
var typeElement = predefinedType.GenericIEnumerable.GetTypeElement();
if (typeElement == null)
return false;
var arrayType = TypeFactory.CreateArrayType(predefinedType.Object, 1, NullableAnnotation.Unknown);
var type = EmptySubstitution.INSTANCE.Extend(typeElement.TypeParameters[0], arrayType).Apply(predefinedType.GenericIEnumerable);
return property.Type.IsImplicitlyConvertibleTo(type, typeConversionRule);
}
public override string GetName() => this.overrideName ?? myOwner.GetText();
private string GetShortName() => GetName().Split('.').Last();
public override TreeTextRange GetTreeTextRange() => myOwner.GetTreeTextRange();
public override IAccessContext GetAccessContext() => new ElementAccessContext(myOwner);
public override ISymbolTable GetReferenceSymbolTable(bool useReferenceName)
{
ISymbolTable table;
if (myTypeElement is IClass @class) {
table = ResolveUtil
.GetSymbolTableByNamespace(@class.GetContainingNamespace(), @class.Module, true)
.Distinct();
}
else if (myTypeElement is IField field)
{
table = ResolveUtil
.GetSymbolTableByTypeElement(field.GetContainingType(), SymbolTableMode.FULL, field.Module)
.Distinct();
}
else if (myTypeElement is IEnum enumerator)
{
table = ResolveUtil
.GetSymbolTableByTypeElement(enumerator, SymbolTableMode.FULL, enumerator.Module)
.Distinct();
}
else
{
return EmptySymbolTable.INSTANCE;
}
if (!useReferenceName)
return table;
return table.Filter(GetShortName(), new AllFilter(GetShortName()));
}
public ISymbolTable GetCompletionSymbolTable() => GetReferenceSymbolTable(false);
public override IReference BindTo(IDeclaredElement element) => BindTo(element, EmptySubstitution.INSTANCE);
public override IReference BindTo(
IDeclaredElement element,
ISubstitution substitution)
{
return this;
}
public override ResolveResultWithInfo ResolveWithoutCache()
{
ResolveResultWithInfo resolveResult = GetReferenceSymbolTable(true).GetResolveResult(GetShortName());
return resolveResult;
}
public sealed class AllFilter : SimpleSymbolInfoFilter
{
[NotNull]
private readonly string myName;
public AllFilter([NotNull] string name) => myName = name;
public override bool Accepts(ISymbolInfo info) => true;
public override ResolveErrorType ErrorType => ResolveErrorType.WRONG_NAME_CASE;
public override FilterRunType RunType => FilterRunType.MUST_RUN_NO_CANDIDATES;
}
}