Skip to content

Commit

Permalink
chore: Added basic attribute gathering
Browse files Browse the repository at this point in the history
  • Loading branch information
samtrion committed Jun 18, 2024
1 parent 2e54149 commit 2f66f94
Show file tree
Hide file tree
Showing 43 changed files with 4,072 additions and 197 deletions.
224 changes: 31 additions & 193 deletions src/NetEvolve.ArchiDuct/Internals/Decompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,6 @@

internal sealed partial class Decompiler : IDisposable
{
private static readonly ConcurrentDictionary<
IModule,
IDocumentationProvider
> _documentationProviders = new ConcurrentDictionary<IModule, IDocumentationProvider>(
new ModuleEqualityComparer()
);

private static readonly string[] _ignoredElements =
[
DocumentationXmlPropertyConstants.Example,
DocumentationXmlPropertyConstants.Remarks,
DocumentationXmlPropertyConstants.Returns,
DocumentationXmlPropertyConstants.SeeAlso,
DocumentationXmlPropertyConstants.Summary
];

private readonly CSharpDecompiler _decompiler;

private readonly List<ModelNamespace> _modelNamespaces;
Expand Down Expand Up @@ -64,7 +48,7 @@ public ModelAssembly Decompile(HashSet<SourceFilter> filters)
var typeSystem = _decompiler.TypeSystem;
var mainModule = typeSystem.MainModule;

if (TryGetDocumentationProvider(mainModule, out var documentationProvider))
if (ModelFactory.TryGetDocumentationProvider(mainModule, out var documentationProvider))
{
_decompiler.DocumentationProvider = documentationProvider;
}
Expand All @@ -85,25 +69,40 @@ private ModelAssembly DecompileModule(IModule module, HashSet<SourceFilter> filt
{
_modelAssembly = new ModelAssembly(
module,
GetDocumentation($"T:{module.AssemblyName}.{AssemblyDoc}")
ModelFactory.GetDocumentation($"T:{module.AssemblyName}.{AssemblyDoc}", _resolver)
);

MapAttributes(module);
MapTypeModels(module, filters);
SetReferences();

Check warning on line 77 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L76-L77

Added lines #L76 - L77 were not covered by tests

// TODO: Add GitVersion informations
// TODO: Assembly Attributes

return _modelAssembly;

Check warning on line 81 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L81

Added line #L81 was not covered by tests
}

private void MapAttributes(IModule module)
{
var attributes = module.GetAssemblyAttributes();

foreach (var attribute in attributes)
{
if (attribute is null)
{
continue;
}

return _modelAssembly;
}
var typeDefinition = attribute.AttributeType.GetDefinition()!;

private static XElement? ConvertToDocumentation(string? documentationString) =>
string.IsNullOrWhiteSpace(documentationString)
? null
: XElement.Parse($"<doc>{documentationString}</doc>");
_ = _modelAssembly.Attributes.Add(
new ModelAttribute(
attribute,
typeDefinition,
ModelFactory.GetDocumentation(typeDefinition?.GetIdString(), _resolver)
)
);
}
}

Check warning on line 105 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L105

Added line #L105 was not covered by tests

private static bool IsDocumentationHelperClass(string name) =>
name.EndsWith(AssemblyDoc, Ordinal) || name.EndsWith(NamespaceDoc, Ordinal);
Expand Down Expand Up @@ -179,29 +178,6 @@ private static void MapModelTypeParameters(ITypeDefinition typeDefinition, Model
}
}

Check warning on line 179 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L179

Added line #L179 was not covered by tests

private static bool TryGetDocumentationProvider(
IModule module,
[NotNullWhen(true)] out IDocumentationProvider? documentationProvider
)
{
if (module?.PEFile is null)
{
documentationProvider = null;
return false;
}

documentationProvider = _documentationProviders.GetOrAdd(
module,
m =>
{
return XmlDocLoader.LoadDocumentation(m.PEFile)
?? XmlDocLoader.MscorlibDocumentation;
}
);

return true;
}

private void MapMemberModel(IMember member, ModelTypeBase parentModel)
{
if (member.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
Expand All @@ -214,7 +190,7 @@ private void MapMemberModel(IMember member, ModelTypeBase parentModel)
return;

Check warning on line 190 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L190

Added line #L190 was not covered by tests
}

if (!TryGetDocumentation(member, out var documentation))
if (!ModelFactory.TryGetDocumentation(member, _resolver, out var documentation))

Check warning on line 193 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L193

Added line #L193 was not covered by tests
{
//TODO: Include undocumented items?
}
Expand All @@ -237,7 +213,8 @@ parentModel is ModelEnum
var describedMember = ModelFactory.CreateModelMemberType(
member,
parentModel,
documentation
documentation,
_resolver
);
MapModelMemberParameters(member, describedMember);

Check warning on line 219 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L213-L219

Added lines #L213 - L219 were not covered by tests

Expand Down Expand Up @@ -269,15 +246,16 @@ private void MapTypeModel(ITypeDefinition typeDefinition, ModelEntityBase? paren
return;

Check warning on line 246 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L246

Added line #L246 was not covered by tests
}

if (TryGetDocumentation(typeDefinition, out var documentation))
if (ModelFactory.TryGetDocumentation(typeDefinition, _resolver, out var documentation))

Check warning on line 249 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L249

Added line #L249 was not covered by tests
{
//TODO: Include undocumented items?
}

var describedModel = ModelFactory.CreateModelType(
typeDefinition,
parentEntity ?? GetOrAddNamespace(typeDefinition.Namespace),
documentation
documentation,
_resolver
);

Check warning on line 259 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L255-L259

Added lines #L255 - L259 were not covered by tests

MapModelTypeParameters(typeDefinition, describedModel);
Expand Down Expand Up @@ -326,13 +304,6 @@ private void Dispose(bool disposing)
}
}

private XElement? GetDocumentation(string id)
{
var entity = IdStringProvider.FindEntity(id, _resolver);

return TryGetDocumentation(entity, out var documentation) ? documentation : null;
}

private ModelNamespace GetOrAddNamespace(string fullNamespace)
{
var @namespace = _modelNamespaces.Find(x => x.FullName.Equals(fullNamespace, Ordinal));

Check warning on line 309 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L309

Added line #L309 was not covered by tests
Expand All @@ -342,7 +313,7 @@ private ModelNamespace GetOrAddNamespace(string fullNamespace)
@namespace = new ModelNamespace(
fullNamespace,
_modelAssembly,
GetDocumentation($"T:{fullNamespace}.{NamespaceDoc}")
ModelFactory.GetDocumentation($"T:{fullNamespace}.{NamespaceDoc}", _resolver)
);

Check warning on line 317 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L313-L317

Added lines #L313 - L317 were not covered by tests

_modelNamespaces.Add(@namespace);

Check warning on line 319 in src/NetEvolve.ArchiDuct/Internals/Decompiler.cs

View check run for this annotation

Codecov / codecov/patch

src/NetEvolve.ArchiDuct/Internals/Decompiler.cs#L319

Added line #L319 was not covered by tests
Expand Down Expand Up @@ -381,137 +352,4 @@ private void SetReferences()

private static bool ShouldNotBeDescribedAccessModifier(IMember entity) =>
entity is IMethod method && method.IsExplicitInterfaceImplementation;

private bool TryGetDocFromBaseClass(
IEntity entity,
[NotNullWhen(true)] out XElement? baseDocumentation
)
{
XElement? resultDocumentation = null;
var result =
entity is ITypeDefinition typeDefinition
&& typeDefinition
.EnumerateBaseTypeDefinitions()
.Any(type => TryGetDocumentation(type, out resultDocumentation));
baseDocumentation = resultDocumentation;
return result;
}

private bool TryGetDocFromExplicit(
IEntity entity,
[NotNullWhen(true)] out XElement? baseDocumentation
)
{
XElement? resultDocumentation = null;
var result =
entity is IMember member
&& member.IsExplicitInterfaceImplementation
&& member.ExplicitlyImplementedInterfaceMembers.Any(type =>
TryGetDocumentation(type, out resultDocumentation)
);
baseDocumentation = resultDocumentation;
return result;
}

private bool TryGetDocFromInterface(
IEntity entity,
[NotNullWhen(true)] out XElement? baseDocumentation
)
{
XElement? resultDocumentation = null;
var result = false;
if (entity is IMember member)
{
var parentName = member.DeclaringTypeDefinition!.FullName;
var entityId = member.GetIdString();

result =
member.DeclaringTypeDefinition is not null
&& member
.DeclaringTypeDefinition.EnumerateBaseTypeDefinitions()
.Any(type =>
{
if (type.Kind != TypeKind.Interface)
{
return false;
}

_ = TryGetDocumentationProvider(type.ParentModule!, out _);

var lookupId = entityId.Replace(
parentName,
type.FullName
#if !NETSTANDARD2_0
,
OrdinalIgnoreCase
#endif
);
resultDocumentation = GetDocumentation(lookupId);
return resultDocumentation is not null;
});
}

baseDocumentation = resultDocumentation;
return result;
}

private bool TryGetDocFromReference(
string? reference,
[NotNullWhen(true)] out XElement? baseDocumentation
)
{
baseDocumentation = null;

if (reference is not null)
{
baseDocumentation = GetDocumentation(reference);
}

return baseDocumentation is not null;
}

private bool TryGetDocumentation(
IEntity? entity,
[NotNullWhen(true)] out XElement? documentation
)
{
documentation = null;

if (entity is null || entity.ParentModule is null)
{
return false;
}

if (!TryGetDocumentationProvider(entity.ParentModule, out var documentationProvider))
{
return false;
}

var result = ConvertToDocumentation(documentationProvider.GetDocumentation(entity));

if (result is null)
{
return false;
}

if (result.HasInheritDoc(out var inheritedDocumentation))
{
var reference = inheritedDocumentation.GetCRefAttribute();
inheritedDocumentation.Remove();

if (
TryGetDocFromReference(reference, out var baseDocumentation)
|| TryGetDocFromExplicit(entity, out baseDocumentation)
|| TryGetDocFromBaseClass(entity, out baseDocumentation)
|| TryGetDocFromInterface(entity, out baseDocumentation)
)
{
result = baseDocumentation.Merge(result, _ignoredElements);
}
}

documentation = result;

return documentation is not null;
}
}
Loading

0 comments on commit 2f66f94

Please sign in to comment.