Skip to content

Commit e319870

Browse files
committed
allow cref to select specific inherit candidate, improve logging messages
1 parent 63edf02 commit e319870

File tree

9 files changed

+174
-148
lines changed

9 files changed

+174
-148
lines changed

readme.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ How to Use It
1515

1616
This is a development-only dependency; it will not be deployed with or referenced by your compiled app/library.
1717

18-
3) There is no 3.
18+
3) Build your project as you normally would.
1919

20-
Once the package reference is added to your project, the XML docs will be processed automatically with each build.
20+
The XML docs will be post-processed automatically with each build, whether you use Visual Studio, dotnet CLI, or anything else that hosts the MSBuild engine.
2121

2222
How it Works
2323
------------
@@ -61,7 +61,7 @@ public class A : IY
6161
/// Returns value <paramref name="t" />
6262
/// of type <typeparamref name="T" />
6363
/// </returns>
64-
public virtual T M<T>(T t) { }
64+
public virtual T M<T>(T t) => t;
6565

6666
/// <summary>Overloaded Method O</summary>
6767
/// <param name="s">Param s</param>
@@ -80,7 +80,7 @@ public class B : A
8080
public override void Y() { }
8181

8282
/// <inheritdoc />
83-
public override TValue M<TValue>(TValue value) { }
83+
public override TValue M<TValue>(TValue value) => value;
8484
}
8585
```
8686

@@ -210,7 +210,7 @@ The same can be achieved by conditionally incuding the NuGet package
210210

211211
```XML
212212
<ItemGroup Condition="'$(Configuration)'!='Debug'">
213-
<PackageReference Include="SauceControl.InheritDoc" Version="0.2.0" PrivateAssets="all" />
213+
<PackageReference Include="SauceControl.InheritDoc" Version="0.3.0" PrivateAssets="all" />
214214
</ItemGroup>
215215
```
216216

@@ -240,9 +240,9 @@ Warnings can be selectively disabled with the MSBuild standard `NoWarn` property
240240
| Code | Description |
241241
|------|-------------|
242242
|IDT001| Indicates a referenced XML documentation file could not be loaded or parsed or that the file did not contain documentation in the standard schema. |
243-
|IDT002| Typically indicates incomplete XML docs for referenced assemblies. I.E. an inheritance candidate was identified but had no documentaion to inherit. |
243+
|IDT002| Indicates incomplete XML docs for the target assembly or one of its external references. i.e. an inheritance candidate was identified but had no documentaion to inherit. |
244244
|IDT003| May indicate you used `<inheritdoc />` on a type/member with no identifiable base. You may correct this warning by using the `cref` attribute to identify the base explicitly. |
245-
|IDT004| May indicate an incorrect XPATH value in a `path` attribute. |
245+
|IDT004| May indicate an incorrect XPATH value in a `path` attribute or a duplicate/superfluous `<inheritdoc />` tag. |
246246

247247
Known Issues
248248
------------

src/Directory.Build.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<Target Name="AddNonStringAssemblyInfoAttributes" AfterTargets="CoreGenerateAssemblyInfo" Outputs="$(AssemblyInfoFile)">
1717

1818
<ItemGroup>
19+
<AssemblyInfoLines Include="[assembly:System.CLSCompliant(true)]" />
1920
<AssemblyInfoLines Include="[assembly:System.Runtime.InteropServices.ComVisible(false)]" />
2021
</ItemGroup>
2122

src/InheritDoc/CecilExtensions.cs

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ internal static class CecilExtensions
1111

1212
private static readonly string[] ignoredModifiers = new[] {
1313
"System.Runtime.InteropServices.InAttribute",
14-
"System.Runtime.CompilerServices.CallConvCdecl",
14+
"System.Runtime.CompilerServices.CallConvCdecl"
1515
};
1616

1717
private static readonly string[] ignoredBaseTypes = new[] {
@@ -64,13 +64,15 @@ public static string GetDocID(this MethodDefinition m)
6464

6565
public static IEnumerable<TypeReference> GetBaseCandidates(this TypeDefinition t)
6666
{
67+
var it = t;
68+
6769
while (t.BaseType != null && !ignoredBaseTypes.Contains(t.BaseType.FullName))
6870
{
6971
yield return t.BaseType;
7072
t = t.BaseType.Resolve();
7173
}
7274

73-
foreach (var i in t.Interfaces)
75+
foreach (var i in it.Interfaces)
7476
yield return i.InterfaceType;
7577

7678
if (t.BaseType != null && ignoredBaseTypes.Contains(t.BaseType.FullName))
@@ -80,17 +82,18 @@ public static IEnumerable<TypeReference> GetBaseCandidates(this TypeDefinition t
8082
public static IEnumerable<MethodDefinition> GetBaseCandidates(this MethodDefinition m)
8183
{
8284
if ((m.IsVirtual && m.IsReuseSlot) || m.IsConstructor)
83-
yield return getBaseMethodFromType(m, m.DeclaringType.BaseType)!;
85+
foreach (var md in getBaseCandidatesFromType(m, m.DeclaringType.BaseType))
86+
yield return md;
8487

85-
foreach (var md in m.DeclaringType.Interfaces.Select(i => getBaseMethodFromType(m, i.InterfaceType)).Where(c => c != null))
86-
yield return md!;
88+
foreach (var md in m.DeclaringType.Interfaces.SelectMany(i => getBaseCandidatesFromType(m, i.InterfaceType)))
89+
yield return md;
8790
}
8891

8992
private static EventDefinition getEventForMethod(MethodDefinition method) => method.DeclaringType.Events.First(e => e.InvokeMethod == method || e.AddMethod == method || e.RemoveMethod == method);
9093

9194
private static PropertyDefinition getPropertyForMethod(MethodDefinition method) => method.DeclaringType.Properties.First(p => p.GetMethod == method || p.SetMethod == method);
9295

93-
private static MethodDefinition? getBaseMethodFromType(MethodDefinition om, TypeReference bt)
96+
private static IEnumerable<MethodDefinition> getBaseCandidatesFromType(MethodDefinition om, TypeReference bt)
9497
{
9598
var genMap = new Dictionary<TypeReference, TypeReference>();
9699

@@ -102,48 +105,41 @@ public static IEnumerable<MethodDefinition> GetBaseCandidates(this MethodDefinit
102105
{
103106
var gi = (GenericInstanceType)bt;
104107
for (int i = 0; i < gi.GenericArguments.Count; i++)
105-
genMap.Add(rbt.GenericParameters[i], gi.GenericArguments[i]);
108+
genMap[rbt.GenericParameters[i]] = gi.GenericArguments[i];
106109

107-
foreach (var ga in genMap.ToList().Where(kv => genMap.ContainsKey(kv.Value)))
110+
foreach (var ga in genMap.Where(kv => genMap.ContainsKey(kv.Value)).ToList())
108111
genMap[ga.Key] = genMap[ga.Value];
109112
}
110113

111-
foreach (var meth in rbt.Methods.Where(m => m.Name == om.Name && m.Parameters.Count == om.Parameters.Count))
114+
foreach (var bm in rbt.Methods.Where(m => m.Name == om.Name && m.Parameters.Count == om.Parameters.Count))
112115
{
113-
var mp = meth.ReturnType;
114-
var op = om.ReturnType;
115-
if (!areParamTypesEquivalent(mp, op, genMap))
116+
if (!areParamTypesEquivalent(bm.ReturnType, om.ReturnType, genMap))
116117
continue;
117118

118-
int matchedparms = 0;
119-
for (int i = 0; i < meth.Parameters.Count; i++)
119+
bool match = true;
120+
for (int i = 0; i < bm.Parameters.Count; i++)
120121
{
121-
mp = meth.Parameters[i].ParameterType;
122-
op = om.Parameters[i].ParameterType;
123-
if (!areParamTypesEquivalent(mp, op, genMap))
124-
continue;
125-
126-
matchedparms++;
122+
if (!areParamTypesEquivalent(bm.Parameters[i].ParameterType, om.Parameters[i].ParameterType, genMap))
123+
{
124+
match = false;
125+
break;
126+
}
127127
}
128128

129-
if (matchedparms != meth.Parameters.Count)
130-
continue;
131-
132-
return meth;
129+
if (match)
130+
yield return bm;
133131
}
134132

135133
bt = rbt.BaseType;
136134
}
137-
138-
return null;
139135
}
140136

141137
private static bool areParamTypesEquivalent(TypeReference mp, TypeReference op, IDictionary<TypeReference, TypeReference> genMap)
142138
{
143-
if (((mp.IsRequiredModifier && op.IsRequiredModifier) || (mp.IsOptionalModifier && op.IsOptionalModifier)) && mp is IModifierType mpm && op is IModifierType opm)
139+
if (mp is IModifierType mpm && op is IModifierType opm)
144140
return areParamTypesEquivalent(mpm.ModifierType, opm.ModifierType, genMap) && areParamTypesEquivalent(mpm.ElementType, opm.ElementType, genMap);
145141

146-
if (mp.IsArray && op.IsArray && mp is ArrayType mpa && op is ArrayType opa)
142+
if (mp is ArrayType mpa && op is ArrayType opa)
147143
return mpa.Rank == opa.Rank && areParamTypesEquivalent(mpa.ElementType, opa.ElementType, genMap);
148144

149145
if (mp is TypeSpecification mpe && op is TypeSpecification ope)
@@ -160,36 +156,20 @@ private static string encodeTypeName(TypeReference tr)
160156
{
161157
string? suffix = null;
162158

163-
while (tr.IsPointer || tr.IsByReference || tr.IsPinned || tr.IsRequiredModifier || tr.IsOptionalModifier || tr.IsArray)
159+
while (!tr.IsGenericInstance && !tr.IsFunctionPointer && tr is TypeSpecification ts)
164160
{
165161
if (tr.IsPointer)
166-
{
167-
tr = ((PointerType)tr).ElementType;
168162
suffix = "*" + suffix;
169-
}
170-
if (tr.IsByReference)
171-
{
172-
tr = ((ByReferenceType)tr).ElementType;
163+
else if (tr.IsByReference)
173164
suffix = "@" + suffix;
174-
}
175-
if (tr.IsPinned)
176-
{
177-
tr = ((PinnedType)tr).ElementType;
165+
else if (tr.IsPinned)
178166
suffix = "^" + suffix;
179-
}
180-
if (tr.IsRequiredModifier || tr.IsOptionalModifier)
181-
{
182-
var mt = (IModifierType)tr;
183-
tr = mt.ElementType;
184-
if (!ignoredModifiers.Contains(mt.ModifierType.FullName))
185-
suffix = (tr.IsRequiredModifier ? "|" : "!") + mt.ModifierType.FullName + suffix;
186-
}
187-
if (tr.IsArray)
188-
{
189-
var at = (ArrayType)tr;
190-
tr = at.ElementType;
167+
else if (tr is IModifierType mt && !ignoredModifiers.Contains(mt.ModifierType.FullName))
168+
suffix = (tr.IsRequiredModifier ? "|" : "!") + mt.ModifierType.FullName + suffix;
169+
else if (tr is ArrayType at)
191170
suffix = "[" + string.Join(",", at.Dimensions.Select(d => d.IsSized ? d.LowerBound?.ToString() + ":" + d.UpperBound?.ToString() : null)) + "]" + suffix;
192-
}
171+
172+
tr = ts.ElementType;
193173
}
194174

195175
if (tr.IsFunctionPointer)

src/InheritDoc/InheritDoc.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<VersionPrefix>0.2.0</VersionPrefix>
4+
<VersionPrefix>0.3.0</VersionPrefix>
55
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
66
</PropertyGroup>
77

0 commit comments

Comments
 (0)