Skip to content

Commit

Permalink
Merge pull request #680 from sharwell/more-projects
Browse files Browse the repository at this point in the history
Fully support additional projects
  • Loading branch information
sharwell authored Dec 23, 2020
2 parents 0e6a64a + f20d80e commit 2bf7c28
Show file tree
Hide file tree
Showing 40 changed files with 881 additions and 638 deletions.
2 changes: 1 addition & 1 deletion RoslynSDK.ruleset
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
</Rules>
<Rules AnalyzerId="Roslyn.Diagnostics.Analyzers" RuleNamespace="Roslyn.Diagnostics.Analyzers">
<Rule Id="RS1019" Action="None" /> <!-- DiagnosticId must be unique across analyzers: Many tests use similar analyzer instances -->
<Rule Id="RS1022" Action="None" /> <!-- AD0001: https://github.com/dotnet/roslyn-analyzers/issues/1803 -->
<Rule Id="RS2008" Action="None" /> <!-- Enable analyzer release tracking: only used in this repository for testing -->
</Rules>
</RuleSet>
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<DiffPlexVersion>1.4.4</DiffPlexVersion>
<!-- Testing -->
<MicrosoftCodeAnalysis2PrimaryTestVersion>2.6.1</MicrosoftCodeAnalysis2PrimaryTestVersion>
<MicrosoftCodeAnalysis3PrimaryTestVersion>3.3.1</MicrosoftCodeAnalysis3PrimaryTestVersion>
<MicrosoftCodeAnalysis3PrimaryTestVersion>3.8.0</MicrosoftCodeAnalysis3PrimaryTestVersion>
<MicrosoftCodeAnalysisTestingVersion>1.0.1-beta1.20374.2</MicrosoftCodeAnalysisTestingVersion>
<XunitCombinatorialVersion>1.2.7</XunitCombinatorialVersion>
<VsixTestingXunitVersion>0.1.49-beta</VsixTestingXunitVersion>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ namespace Microsoft.CodeAnalysis.Testing
{
internal static class DictionaryExtensions
{
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, IEnumerable<KeyValuePair<TKey, TValue>> items)
where TKey : notnull
{
foreach (var (key, value) in items)
{
dictionary.Add(key, value);
}
}

// Copied from ConcurrentDictionary since IDictionary doesn't have this useful method
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> function)
where TKey : notnull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Testing.Model
{
/// <summary>
/// Represents an evaluated <see cref="ProjectState"/>.
/// </summary>
public sealed class EvaluatedProjectState
{
public EvaluatedProjectState(ProjectState state, ReferenceAssemblies defaultReferenceAssemblies)
: this(
state.Name,
state.AssemblyName,
state.Language,
state.ReferenceAssemblies ?? defaultReferenceAssemblies,
state.OutputKind ?? OutputKind.DynamicallyLinkedLibrary,
state.DocumentationMode ?? DocumentationMode.Diagnose,
state.Sources.ToImmutableArray(),
state.AdditionalFiles.ToImmutableArray(),
state.AdditionalProjectReferences.ToImmutableArray(),
state.AdditionalReferences.ToImmutableArray())
{
}

private EvaluatedProjectState(
string name,
string assemblyName,
string language,
ReferenceAssemblies referenceAssemblies,
OutputKind outputKind,
DocumentationMode documentationMode,
ImmutableArray<(string filename, SourceText content)> sources,
ImmutableArray<(string filename, SourceText content)> additionalFiles,
ImmutableArray<string> additionalProjectReferences,
ImmutableArray<MetadataReference> additionalReferences)
{
Name = name;
AssemblyName = assemblyName;
Language = language;
ReferenceAssemblies = referenceAssemblies;
OutputKind = outputKind;
DocumentationMode = documentationMode;
Sources = sources;
AdditionalFiles = additionalFiles;
AdditionalProjectReferences = additionalProjectReferences;
AdditionalReferences = additionalReferences;
}

public string Name { get; }

public string AssemblyName { get; }

public string Language { get; }

public ReferenceAssemblies ReferenceAssemblies { get; }

public OutputKind OutputKind { get; }

public DocumentationMode DocumentationMode { get; }

public ImmutableArray<(string filename, SourceText content)> Sources { get; }

public ImmutableArray<(string filename, SourceText content)> AdditionalFiles { get; }

public ImmutableArray<string> AdditionalProjectReferences { get; }

public ImmutableArray<MetadataReference> AdditionalReferences { get; }

public EvaluatedProjectState WithSources(ImmutableArray<(string filename, SourceText content)> sources)
{
if (sources == Sources)
{
return this;
}

return With(sources: sources);
}

private EvaluatedProjectState With(
Optional<string> name = default,
Optional<string> assemblyName = default,
Optional<string> language = default,
Optional<ReferenceAssemblies> referenceAssemblies = default,
Optional<OutputKind> outputKind = default,
Optional<DocumentationMode> documentationMode = default,
Optional<ImmutableArray<(string filename, SourceText content)>> sources = default,
Optional<ImmutableArray<(string filename, SourceText content)>> additionalFiles = default,
Optional<ImmutableArray<string>> additionalProjectReferences = default,
Optional<ImmutableArray<MetadataReference>> additionalReferences = default)
{
return new EvaluatedProjectState(
GetValueOrDefault(name, Name),
GetValueOrDefault(assemblyName, AssemblyName),
GetValueOrDefault(language, Language),
GetValueOrDefault(referenceAssemblies, ReferenceAssemblies),
GetValueOrDefault(outputKind, OutputKind),
GetValueOrDefault(documentationMode, DocumentationMode),
GetValueOrDefault(sources, Sources),
GetValueOrDefault(additionalFiles, AdditionalFiles),
GetValueOrDefault(additionalProjectReferences, AdditionalProjectReferences),
GetValueOrDefault(additionalReferences, AdditionalReferences));
}

private static T GetValueOrDefault<T>(Optional<T> optionalValue, T defaultValue)
{
return optionalValue.HasValue ? optionalValue.Value : defaultValue;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;

namespace Microsoft.CodeAnalysis.Testing
{
public class ProjectCollection : Dictionary<string, ProjectState>
{
private readonly string _defaultLanguage;
private readonly string _defaultExtension;

public ProjectCollection(string defaultLanguage, string defaultExtension)
{
_defaultLanguage = defaultLanguage;
_defaultExtension = defaultExtension;
}

public new ProjectState this[string projectName]
{
get
{
if (TryGetValue(projectName, out var project))
{
return project;
}

return this[projectName, _defaultLanguage];
}
}

public ProjectState this[string projectName, string language]
{
get
{
var project = this.GetOrAdd(projectName, () => new ProjectState(projectName, _defaultLanguage, $"/{projectName}/Test", _defaultExtension));
if (project.Language != language)
{
throw new InvalidOperationException();
}

return project;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,77 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Testing
{
public abstract class ProjectState
public class ProjectState
{
private readonly string _defaultPrefix;
private readonly string _defaultExtension;

protected ProjectState(string name, string defaultPrefix, string defaultExtension)
public ProjectState(string name, string language, string defaultPrefix, string defaultExtension)
{
Name = name;
_defaultPrefix = defaultPrefix;
_defaultExtension = defaultExtension;
Language = language;
DefaultPrefix = defaultPrefix;
DefaultExtension = defaultExtension;

Sources = new SourceFileList(defaultPrefix, defaultExtension);
}

internal ProjectState(ProjectState sourceState)
{
Name = sourceState.Name;
Language = sourceState.Language;
ReferenceAssemblies = sourceState.ReferenceAssemblies;
OutputKind = sourceState.OutputKind;
DocumentationMode = sourceState.DocumentationMode;
DefaultPrefix = sourceState.DefaultPrefix;
DefaultExtension = sourceState.DefaultExtension;
Sources = new SourceFileList(DefaultPrefix, DefaultExtension);

Sources.AddRange(sourceState.Sources);
AdditionalFiles.AddRange(sourceState.AdditionalFiles);
AdditionalFilesFactories.AddRange(sourceState.AdditionalFilesFactories);
AdditionalProjectReferences.AddRange(sourceState.AdditionalProjectReferences);
}

public string Name { get; }

public string AssemblyName => Name;

public abstract string Language { get; }
public string Language { get; }

/// <summary>
/// Gets or sets the reference assemblies to use for the project.
/// </summary>
/// <value>
/// A <see cref="Testing.ReferenceAssemblies"/> instance to use specific reference assemblies; otherwise,
/// <see langword="null"/> to inherit the reference assemblies from
/// <see cref="AnalyzerTest{TVerifier}.ReferenceAssemblies"/>.
/// </value>
public ReferenceAssemblies? ReferenceAssemblies { get; set; }

public OutputKind? OutputKind { get; set; }

public DocumentationMode? DocumentationMode { get; set; }

/// <summary>
/// Gets the set of source files for analyzer or code fix testing. Files may be added to this list using one of
/// the <see cref="SourceFileList.Add(string)"/> methods.
/// </summary>
public SourceFileList Sources { get; }

public SourceFileCollection AdditionalFiles { get; } = new SourceFileCollection();

public List<Func<IEnumerable<(string filename, SourceText content)>>> AdditionalFilesFactories { get; } = new List<Func<IEnumerable<(string filename, SourceText content)>>>();

public List<string> AdditionalProjectReferences { get; } = new List<string>();

public MetadataReferenceCollection AdditionalReferences { get; } = new MetadataReferenceCollection();

private protected string DefaultPrefix { get; }

private protected string DefaultExtension { get; }
}
}
Loading

0 comments on commit 2bf7c28

Please sign in to comment.