Skip to content

Commit

Permalink
Add CLI command list-references
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Dec 27, 2020
1 parent aa18260 commit 62786df
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 1 deletion.
115 changes: 115 additions & 0 deletions src/CommandLine/Commands/ListReferencesCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using static Roslynator.Logger;

namespace Roslynator.CommandLine
{
internal class ListReferencesCommand : MSBuildWorkspaceCommand
{
public ListReferencesCommand(
ListReferencesCommandLineOptions options,
MetadataReferenceDisplay display,
MetadataReferenceFilter filter,
in ProjectFilter projectFilter) : base(projectFilter)
{
Options = options;
Display = display;
Filter = filter;
}

public ListReferencesCommandLineOptions Options { get; }

public MetadataReferenceDisplay Display { get; }

public MetadataReferenceFilter Filter { get; }

public override async Task<CommandResult> ExecuteAsync(ProjectOrSolution projectOrSolution, CancellationToken cancellationToken = default)
{
AssemblyResolver.Register();

ImmutableArray<Compilation> compilations = await GetCompilationsAsync(projectOrSolution, cancellationToken);

int count = 0;

foreach (string display in compilations
.SelectMany(compilation => compilation.ExternalReferences.Select(reference => (compilation, reference)))
.Select(f => GetDisplay(f.compilation, f.reference))
.Where(f => f != null)
.Distinct()
.OrderBy(f => f, StringComparer.InvariantCulture))
{
WriteLine(display);
count++;
}

if (ShouldWrite(Verbosity.Normal))
{
WriteLine(Verbosity.Normal);
WriteLine($"{count} assembl{((count == 1) ? "y" : "ies")} found", ConsoleColor.Green, Verbosity.Normal);
}

return CommandResult.Success;

string GetDisplay(Compilation compilation, MetadataReference reference)
{
switch (reference)
{
case PortableExecutableReference portableReference:
{
if ((Filter & MetadataReferenceFilter.Dll) == 0)
return null;

string path = portableReference.FilePath;

switch (Display)
{
case MetadataReferenceDisplay.Path:
{
return path;
}
case MetadataReferenceDisplay.FileName:
{
return Path.GetFileName(path);
}
case MetadataReferenceDisplay.FileNameWithoutExtension:
{
return Path.GetFileNameWithoutExtension(path);
}
case MetadataReferenceDisplay.AssemblyName:
{
var assembly = (IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(reference);

return assembly.Identity.ToString();
}
default:
{
throw new InvalidOperationException();
}
}
}
case CompilationReference compilationReference:
{
if ((Filter & MetadataReferenceFilter.Project) == 0)
return null;

return compilationReference.Display;
}
default:
{
#if DEBUG
WriteLine(reference.GetType().FullName, ConsoleColor.Yellow);
#endif
return reference.Display;
}
}
}
}
}
}
12 changes: 12 additions & 0 deletions src/CommandLine/MetadataReferenceDisplay.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Roslynator.CommandLine
{
internal enum MetadataReferenceDisplay
{
Path = 0,
FileName = 1,
FileNameWithoutExtension = 2,
AssemblyName = 3,
}
}
14 changes: 14 additions & 0 deletions src/CommandLine/MetadataReferenceFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;

namespace Roslynator.CommandLine
{
[Flags]
internal enum MetadataReferenceFilter
{
None = 0,
Dll = 1,
Project = 1 << 1,
}
}
23 changes: 23 additions & 0 deletions src/CommandLine/Options/ListReferencesCommandLineOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using CommandLine;

namespace Roslynator.CommandLine
{
#if DEBUG
[Verb("list-references", HelpText = "Lists assembly references from the specified project or solution.")]
#endif
public class ListReferencesCommandLineOptions : MSBuildCommandLineOptions
{
[Option(
longName: "display",
HelpText = "Defines how the assembly is displayed. Allowed values are path (default), file-name, file-name-without-extension or assembly-name.")]
public string Display { get; set; }

[Option(
longName: ParameterNames.Type,
HelpText = "Defines a type of a reference. Allowed values are dll and project.")]
public IEnumerable<string> Type { get; set; }
}
}
4 changes: 3 additions & 1 deletion src/CommandLine/ParameterNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Roslynator.CommandLine
internal static class ParameterNames
{
public const string Depth = "depth";
public const string Display = "display";
public const string FixScope = "fix-scope";
public const string WrapList = "wrap-list";
public const string IgnoredMemberParts = "ignored-member-parts";
public const string IgnoredNamespaceParts = "ignored-namespace-parts";
public const string IgnoredParts = "ignored-parts";
Expand All @@ -23,8 +23,10 @@ internal static class ParameterNames
public const string SeverityLevel = "severity-level";
public const string SymbolGroups = "symbol-groups";
public const string TargetVersion = "target-version";
public const string Type = "type";
public const string Visibility = "visibility";
public const string WithFlags = "with-flags";
public const string WithoutFlags = "without-flags";
public const string WrapList = "wrap-list";
}
}
24 changes: 24 additions & 0 deletions src/CommandLine/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ private static int Main(string[] args)
SlnListCommandLineOptions,
ListVisualStudioCommandLineOptions,
GenerateSourceReferencesCommandLineOptions,
ListReferencesCommandLineOptions,
#endif
FixCommandLineOptions,
AnalyzeCommandLineOptions,
Expand Down Expand Up @@ -92,6 +93,7 @@ private static int Main(string[] args)
(SlnListCommandLineOptions options) => SlnListAsync(options).Result,
(ListVisualStudioCommandLineOptions options) => ListVisualStudio(options),
(GenerateSourceReferencesCommandLineOptions options) => GenerateSourceReferencesAsync(options).Result,
(ListReferencesCommandLineOptions options) => ListReferencesAsync(options).Result,
#endif
(FixCommandLineOptions options) => FixAsync(options).Result,
(AnalyzeCommandLineOptions options) => AnalyzeAsync(options).Result,
Expand Down Expand Up @@ -524,5 +526,27 @@ private static int Migrate(MigrateCommandLineOptions options)

return (result == CommandResult.Success) ? 0 : 1;
}

private static async Task<int> ListReferencesAsync(ListReferencesCommandLineOptions options)
{
if (!TryParseOptionValueAsEnum(options.Display, ParameterNames.Display, out MetadataReferenceDisplay display, MetadataReferenceDisplay.Path))
return 1;

if (!TryParseOptionValueAsEnumFlags(options.Type, ParameterNames.Type, out MetadataReferenceFilter metadataReferenceFilter, MetadataReferenceFilter.Dll | MetadataReferenceFilter.Project))
return 1;

if (!options.TryGetProjectFilter(out ProjectFilter projectFilter))
return 1;

var command = new ListReferencesCommand(
options,
display,
metadataReferenceFilter,
projectFilter);

CommandResult result = await command.ExecuteAsync(options.Path, options.MSBuildPath, options.Properties);

return (result == CommandResult.Success) ? 0 : 1;
}
}
}

0 comments on commit 62786df

Please sign in to comment.