Skip to content

Commit

Permalink
Merge pull request #8096 from jasonmalinowski/find-references-with-mu…
Browse files Browse the repository at this point in the history
…ltiple-projects-with-same-assembly-name

Find references with multiple projects with same assembly name
  • Loading branch information
jasonmalinowski committed Jan 28, 2016
2 parents 964c910 + 4c49bf2 commit 2423300
Show file tree
Hide file tree
Showing 11 changed files with 309 additions and 127 deletions.
6 changes: 3 additions & 3 deletions src/EditorFeatures/Test/Workspaces/TestHostProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,13 @@ internal TestHostProject(
: this(languageServices, compilationOptions, parseOptions, "Test", references)
{
}

internal TestHostProject(
HostLanguageServices languageServices,
CompilationOptions compilationOptions,
ParseOptions parseOptions,
string assemblyName,
params MetadataReference[] references)
: this(languageServices, compilationOptions, parseOptions, assemblyName, references, SpecializedCollections.EmptyArray<TestHostDocument>())
: this(languageServices, compilationOptions, parseOptions, assemblyName: assemblyName, projectName: assemblyName, references: references, documents: SpecializedCollections.EmptyArray<TestHostDocument>())
{
}

Expand All @@ -159,6 +158,7 @@ internal TestHostProject(
CompilationOptions compilationOptions,
ParseOptions parseOptions,
string assemblyName,
string projectName,
IList<MetadataReference> references,
IList<TestHostDocument> documents,
IList<TestHostDocument> additionalDocuments = null,
Expand All @@ -168,7 +168,7 @@ internal TestHostProject(
IList<AnalyzerReference> analyzerReferences = null)
{
_assemblyName = assemblyName;
_name = assemblyName;
_name = projectName;
_id = ProjectId.CreateNewId(debugName: this.AssemblyName);
_languageServices = languageServices;
_compilationOptions = compilationOptions;
Expand Down
2 changes: 2 additions & 0 deletions src/EditorFeatures/Test/Workspaces/TestWorkspace_Create.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ public partial class TestWorkspace
private const string IncludeXmlDocCommentsAttributeName = "IncludeXmlDocComments";
private const string IsLinkFileAttributeName = "IsLinkFile";
private const string LinkAssemblyNameAttributeName = "LinkAssemblyName";
private const string LinkProjectNameAttributeName = "LinkProjectName";
private const string LinkFilePathAttributeName = "LinkFilePath";
private const string PreprocessorSymbolsAttributeName = "PreprocessorSymbols";
private const string AnalyzerDisplayAttributeName = "Name";
private const string AnalyzerFullPathAttributeName = "FullPath";
private const string AliasAttributeName = "Alias";
private const string ProjectNameAttribute = "Name";

/// <summary>
/// Creates a single buffer in a workspace.
Expand Down
93 changes: 53 additions & 40 deletions src/EditorFeatures/Test/Workspaces/TestWorkspace_XmlConsumption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ public static Task<TestWorkspace> CreateAsync(

var workspace = new TestWorkspace(exportProvider, workspaceKind);

var projectMap = new Dictionary<string, TestHostProject>();
var projectNameToTestHostProject = new Dictionary<string, TestHostProject>();
var documentElementToFilePath = new Dictionary<XElement, string>();
var projectElementToAssemblyName = new Dictionary<XElement, string>();
var projectElementToProjectName = new Dictionary<XElement, string>();
var filePathToTextBufferMap = new Dictionary<string, ITextBuffer>();
int projectIdentifier = 0;
int documentIdentifier = 0;
Expand All @@ -105,18 +105,18 @@ public static Task<TestWorkspace> CreateAsync(
projectElement,
exportProvider,
workspace,
projectElementToAssemblyName,
documentElementToFilePath,
filePathToTextBufferMap,
ref projectIdentifier,
ref documentIdentifier);
Assert.False(projectMap.ContainsKey(project.AssemblyName));
projectMap.Add(project.AssemblyName, project);
Assert.False(projectNameToTestHostProject.ContainsKey(project.Name), $"The workspace XML already contains a project with name {project.Name}");
projectNameToTestHostProject.Add(project.Name, project);
projectElementToProjectName.Add(projectElement, project.Name);
workspace.Projects.Add(project);
}

var documentFilePaths = new HashSet<string>();
foreach (var project in projectMap.Values)
foreach (var project in projectNameToTestHostProject.Values)
{
foreach (var document in project.Documents)
{
Expand All @@ -128,21 +128,21 @@ public static Task<TestWorkspace> CreateAsync(

foreach (var submission in submissions)
{
projectMap.Add(submission.AssemblyName, submission);
projectNameToTestHostProject.Add(submission.Name, submission);
}

var solution = new TestHostSolution(projectMap.Values.ToArray());
var solution = new TestHostSolution(projectNameToTestHostProject.Values.ToArray());
workspace.AddTestSolution(solution);

foreach (var projectElement in workspaceElement.Elements(ProjectElementName))
{
foreach (var projectReference in projectElement.Elements(ProjectReferenceElementName))
{
var fromName = projectElementToAssemblyName[projectElement];
var fromName = projectElementToProjectName[projectElement];
var toName = projectReference.Value;

var fromProject = projectMap[fromName];
var toProject = projectMap[toName];
var fromProject = projectNameToTestHostProject[fromName];
var toProject = projectNameToTestHostProject[toName];

var aliases = projectReference.Attributes(AliasAttributeName).Select(a => a.Value).ToImmutableArray();

Expand All @@ -167,7 +167,7 @@ public static Task<TestWorkspace> CreateAsync(
}
}

foreach (var project in projectMap.Values)
foreach (var project in projectNameToTestHostProject.Values)
{
foreach (var document in project.Documents)
{
Expand Down Expand Up @@ -223,6 +223,7 @@ private static IList<TestHostProject> CreateSubmissions(
compilationOptions: null,
parseOptions: null,
assemblyName: submissionName,
projectName: submissionName,
references: null,
documents: documents,
isSubmission: true));
Expand All @@ -242,6 +243,7 @@ private static IList<TestHostProject> CreateSubmissions(
compilationOptions,
parseOptions,
submissionName,
submissionName,
references,
documents,
isSubmission: true);
Expand All @@ -257,7 +259,6 @@ private static TestHostProject CreateProject(
XElement projectElement,
ExportProvider exportProvider,
TestWorkspace workspace,
Dictionary<XElement, string> projectElementToAssemblyName,
Dictionary<XElement, string> documentElementToFilePath,
Dictionary<string, ITextBuffer> filePathToTextBufferMap,
ref int projectId,
Expand All @@ -266,10 +267,11 @@ private static TestHostProject CreateProject(
var language = GetLanguage(workspace, projectElement);

var assemblyName = GetAssemblyName(workspace, projectElement, ref projectId);
projectElementToAssemblyName.Add(projectElement, assemblyName);

string filePath;

string projectName = projectElement.Attribute(ProjectNameAttribute)?.Value ?? assemblyName;

if (projectElement.Attribute(FilePathAttributeName) != null)
{
filePath = projectElement.Attribute(FilePathAttributeName).Value;
Expand All @@ -281,7 +283,7 @@ private static TestHostProject CreateProject(
}
else
{
filePath = assemblyName +
filePath = projectName +
(language == LanguageNames.CSharp ? ".csproj" :
language == LanguageNames.VisualBasic ? ".vbproj" : ("." + language));
}
Expand Down Expand Up @@ -313,7 +315,7 @@ private static TestHostProject CreateProject(
documentElementToFilePath.Add(documentElement, document.FilePath);
}

return new TestHostProject(languageServices, compilationOptions, parseOptions, assemblyName, references, documents, filePath: filePath, analyzerReferences: analyzers);
return new TestHostProject(languageServices, compilationOptions, parseOptions, assemblyName, projectName, references, documents, filePath: filePath, analyzerReferences: analyzers);
}

private static ParseOptions GetParseOptions(XElement projectElement, string language, HostLanguageServices languageServices)
Expand Down Expand Up @@ -521,48 +523,59 @@ private static TestHostDocument CreateDocument(
{
// This is a linked file. Use the filePath and markup from the referenced document.

var originalProjectName = documentElement.Attribute(LinkAssemblyNameAttributeName);
var originalDocumentPath = documentElement.Attribute(LinkFilePathAttributeName);
var originalAssemblyName = documentElement.Attribute(LinkAssemblyNameAttributeName)?.Value;
var originalProjectName = documentElement.Attribute(LinkProjectNameAttributeName)?.Value;

if (originalProjectName == null || originalDocumentPath == null)
if (originalAssemblyName == null && originalProjectName == null)
{
throw new ArgumentException("Linked file specified without LinkAssemblyName or LinkFilePath.");
throw new ArgumentException($"Linked files must specify either a {LinkAssemblyNameAttributeName} or {LinkProjectNameAttributeName}");
}

var originalProjectNameStr = originalProjectName.Value;
var originalDocumentPathStr = originalDocumentPath.Value;

var originalProject = workspaceElement.Elements(ProjectElementName).First(p =>
var originalProject = workspaceElement.Elements(ProjectElementName).FirstOrDefault(p =>
{
var assemblyName = p.Attribute(AssemblyNameAttributeName);
return assemblyName != null && assemblyName.Value == originalProjectNameStr;
if (originalAssemblyName != null)
{
return p.Attribute(AssemblyNameAttributeName)?.Value == originalAssemblyName;
}
else
{
return p.Attribute(ProjectNameAttribute)?.Value == originalProjectName;
}
});

if (originalProject == null)
{
throw new ArgumentException("Linked file's LinkAssemblyName '{0}' project not found.", originalProjectNameStr);
if (originalProjectName != null)
{
throw new ArgumentException($"Linked file's {LinkProjectNameAttributeName} '{originalProjectName}' project not found.");
}
else
{
throw new ArgumentException($"Linked file's {LinkAssemblyNameAttributeName} '{originalAssemblyName}' project not found.");
}
}

var originalDocumentPath = documentElement.Attribute(LinkFilePathAttributeName)?.Value;

if (originalDocumentPath == null)
{
throw new ArgumentException($"Linked files must specify a {LinkFilePathAttributeName}");
}

var originalDocument = originalProject.Elements(DocumentElementName).First(d =>
documentElement = originalProject.Elements(DocumentElementName).FirstOrDefault(d =>
{
var documentPath = d.Attribute(FilePathAttributeName);
return documentPath != null && documentPath.Value == originalDocumentPathStr;
return d.Attribute(FilePathAttributeName)?.Value == originalDocumentPath;
});

if (originalDocument == null)
if (documentElement == null)
{
throw new ArgumentException("Linked file's LinkFilePath '{0}' file not found.", originalDocumentPathStr);
throw new ArgumentException($"Linked file's LinkFilePath '{originalDocumentPath}' file not found.");
}

markupCode = originalDocument.NormalizedValue();
filePath = GetFilePath(workspace, originalDocument, ref documentId);
}
else
{
markupCode = documentElement.NormalizedValue();
filePath = GetFilePath(workspace, documentElement, ref documentId);
}

markupCode = documentElement.NormalizedValue();
filePath = GetFilePath(workspace, documentElement, ref documentId);

var folders = GetFolders(documentElement);
var optionsElement = documentElement.Element(ParseOptionsElementName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,61 @@ End Class
AssertEx.SetEqual(references.Select(Function(r) r.Definition.ContainingAssembly.Name), {"VBProj1"})
End Using
End Function

<Fact, Trait(Traits.Feature, Traits.Features.FindReferences)>
Public Function TestLinkedFiles_LinkedFilesWithSameAssemblyNameNoReferences() As Task
Dim definition =
<Workspace>
<Project Language="C#" CommonReferences="true" AssemblyName="LinkedProj" Name="CSProj.1">
<Document FilePath="C.cs"><![CDATA[
class {|Definition:$$C|}
{
}
]]>
</Document>
</Project>
<Project Language="C#" CommonReferences="true" AssemblyName="LinkedProj" Name="CSProj.2">
<Document IsLinkFile="true" LinkProjectName="CSProj.1" LinkFilePath="C.cs"/>
</Project>
</Workspace>

Return TestAsync(definition)
End Function

<Fact, Trait(Traits.Feature, Traits.Features.FindReferences)>
Public Function TestLinkedFiles_LinkedFilesWithSameAssemblyNameWithReferences() As Task
Dim definition =
<Workspace>
<Project Language="C#" CommonReferences="true" AssemblyName="LinkedProj" Name="CSProj.1">
<Document FilePath="C.cs"><![CDATA[
public class {|Definition:$$C|}
{
}
]]>
</Document>
</Project>
<Project Language="C#" CommonReferences="true" AssemblyName="LinkedProj" Name="CSProj.2">
<Document IsLinkFile="true" LinkProjectName="CSProj.1" LinkFilePath="C.cs"/>
</Project>
<Project Language="C#" CommonReferences="true" AssemblyName="ReferencingProject1">
<ProjectReference>CSProj.1</ProjectReference>
<Document FilePath="D.cs"><![CDATA[
public class D : [|$$C|]
{
}]]>
</Document>
</Project>
<Project Language="C#" CommonReferences="true" AssemblyName="ReferencingProject2">
<ProjectReference>CSProj.2</ProjectReference>
<Document FilePath="E.cs"><![CDATA[
public class D : [|$$C|]
{
}]]>
</Document>
</Project>
</Workspace>

Return TestAsync(definition)
End Function
End Class
End Namespace
Loading

0 comments on commit 2423300

Please sign in to comment.