diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.fragment.lock.json
new file mode 100644
index 000000000..d803c7d2c
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.fragment.lock.json
@@ -0,0 +1,25 @@
+{
+ "version": 2,
+ "exports": {
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ }
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.json b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.json
new file mode 100644
index 000000000..1323d5f29
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.json
@@ -0,0 +1,22 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+
+ "frameworks": {
+ "net46": {
+ "dependencies": {
+ "ClassLibrary1": {
+ "target": "project"
+ },
+ "ClassLibrary2": {
+ "target": "project"
+ },
+ "ClassLibrary3": {
+ "target": "project"
+ }
+ }
+ }
+ }
+}
diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.lock.json
new file mode 100644
index 000000000..244c3771b
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.lock.json
@@ -0,0 +1,61 @@
+{
+ "locked": false,
+ "version": 2,
+ "targets": {
+ ".NETFramework,Version=v4.6": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x64": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x86": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ }
+ },
+ "libraries": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj"
+ }
+ },
+ "projectFileDependencyGroups": {
+ "": [],
+ ".NETFramework,Version=v4.6": [
+ "ClassLibrary1",
+ "ClassLibrary2",
+ "ClassLibrary3"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.fragment.lock.json
new file mode 100644
index 000000000..7b6738e49
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.fragment.lock.json
@@ -0,0 +1,35 @@
+{
+ "version": 3,
+ "exports": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.5.2",
+ "compile": {
+ "bin/Debug/ClassLibrary1.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary1.dll": {}
+ }
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ }
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.json b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.json
new file mode 100644
index 000000000..1323d5f29
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.json
@@ -0,0 +1,22 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+
+ "frameworks": {
+ "net46": {
+ "dependencies": {
+ "ClassLibrary1": {
+ "target": "project"
+ },
+ "ClassLibrary2": {
+ "target": "project"
+ },
+ "ClassLibrary3": {
+ "target": "project"
+ }
+ }
+ }
+ }
+}
diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.lock.json
new file mode 100644
index 000000000..244c3771b
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.lock.json
@@ -0,0 +1,61 @@
+{
+ "locked": false,
+ "version": 2,
+ "targets": {
+ ".NETFramework,Version=v4.6": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x64": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x86": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ }
+ },
+ "libraries": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj"
+ }
+ },
+ "projectFileDependencyGroups": {
+ "": [],
+ ".NETFramework,Version=v4.6": [
+ "ClassLibrary1",
+ "ClassLibrary2",
+ "ClassLibrary3"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.json b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.json
new file mode 100644
index 000000000..1323d5f29
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.json
@@ -0,0 +1,22 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+
+ "frameworks": {
+ "net46": {
+ "dependencies": {
+ "ClassLibrary1": {
+ "target": "project"
+ },
+ "ClassLibrary2": {
+ "target": "project"
+ },
+ "ClassLibrary3": {
+ "target": "project"
+ }
+ }
+ }
+ }
+}
diff --git a/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.lock.json
new file mode 100644
index 000000000..244c3771b
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.lock.json
@@ -0,0 +1,61 @@
+{
+ "locked": false,
+ "version": 2,
+ "targets": {
+ ".NETFramework,Version=v4.6": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x64": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x86": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ }
+ },
+ "libraries": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj"
+ }
+ },
+ "projectFileDependencyGroups": {
+ "": [],
+ ".NETFramework,Version=v4.6": [
+ "ClassLibrary1",
+ "ClassLibrary2",
+ "ClassLibrary3"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/valid/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/valid/project.fragment.lock.json
new file mode 100644
index 000000000..415fc75d8
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/valid/project.fragment.lock.json
@@ -0,0 +1,35 @@
+{
+ "version": 2,
+ "exports": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.5.2",
+ "compile": {
+ "bin/Debug/ClassLibrary1.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary1.dll": {}
+ }
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ }
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/valid/project.json b/TestAssets/LockFiles/ExportFiles/valid/project.json
new file mode 100644
index 000000000..1323d5f29
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/valid/project.json
@@ -0,0 +1,22 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+
+ "frameworks": {
+ "net46": {
+ "dependencies": {
+ "ClassLibrary1": {
+ "target": "project"
+ },
+ "ClassLibrary2": {
+ "target": "project"
+ },
+ "ClassLibrary3": {
+ "target": "project"
+ }
+ }
+ }
+ }
+}
diff --git a/TestAssets/LockFiles/ExportFiles/valid/project.lock.json b/TestAssets/LockFiles/ExportFiles/valid/project.lock.json
new file mode 100644
index 000000000..244c3771b
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/valid/project.lock.json
@@ -0,0 +1,61 @@
+{
+ "locked": false,
+ "version": 2,
+ "targets": {
+ ".NETFramework,Version=v4.6": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x64": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x86": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ }
+ },
+ "libraries": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj"
+ }
+ },
+ "projectFileDependencyGroups": {
+ "": [],
+ ".NETFramework,Version=v4.6": [
+ "ClassLibrary1",
+ "ClassLibrary2",
+ "ClassLibrary3"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.fragment.lock.json
new file mode 100644
index 000000000..415fc75d8
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.fragment.lock.json
@@ -0,0 +1,35 @@
+{
+ "version": 2,
+ "exports": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.5.2",
+ "compile": {
+ "bin/Debug/ClassLibrary1.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary1.dll": {}
+ }
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ }
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.json b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.json
new file mode 100644
index 000000000..2959f5fbc
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.json
@@ -0,0 +1,10 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+
+ "frameworks": {
+ "net46": { }
+ }
+}
diff --git a/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.lock.json b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.lock.json
new file mode 100644
index 000000000..e7b45e57d
--- /dev/null
+++ b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.lock.json
@@ -0,0 +1,13 @@
+{
+ "locked": false,
+ "version": 2,
+ "targets": {
+ ".NETFramework,Version=v4.6": { }
+ },
+ "libraries": {
+ },
+ "projectFileDependencyGroups": {
+ "": [],
+ ".NETFramework,Version=v4.6": []
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/.gitignore b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/.gitignore
new file mode 100644
index 000000000..497f0e325
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/.gitignore
@@ -0,0 +1,3 @@
+# Negates the lock file
+# MSBuiild references' project model server tests requires these lock files, since they can't be created without VS tooling.
+!project.lock.json
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Class1.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Class1.cs
new file mode 100644
index 000000000..08281c64a
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Class1.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClassLibrary1
+{
+ public class Class1
+ {
+ }
+}
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/ClassLibrary1.csproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/ClassLibrary1.csproj
new file mode 100644
index 000000000..7364cb64d
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/ClassLibrary1.csproj
@@ -0,0 +1,62 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {FD073258-550B-4E57-86AE-DC4874015EB1}
+ Library
+ Properties
+ ClassLibrary1
+ ClassLibrary1
+ v4.5.2
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..6437643a7
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ClassLibrary1")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ClassLibrary1")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fd073258-550b-4e57-86ae-dc4874015eb1")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/packages.config b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/packages.config
new file mode 100644
index 000000000..1975352b1
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Class1.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Class1.cs
new file mode 100644
index 000000000..ad2fff55e
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Class1.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClassLibrary2
+{
+ public class Class1
+ {
+ }
+}
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/ClassLibrary2.csproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/ClassLibrary2.csproj
new file mode 100644
index 000000000..fb17ee317
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/ClassLibrary2.csproj
@@ -0,0 +1,61 @@
+
+
+
+
+ Debug
+ AnyCPU
+ 0f2d2a48-e867-496c-85a7-e97b64cfeda4
+ Library
+ Properties
+ ClassLibrary2
+ ClassLibrary2
+ v4.6
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..b40cfab4c
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ClassLibrary2")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ClassLibrary2")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0f2d2a48-e867-496c-85a7-e97b64cfeda4")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Class1.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Class1.cs
new file mode 100644
index 000000000..21384c5b2
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Class1.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClassLibrary3
+{
+ public class Class1
+ {
+ }
+}
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/ClassLibrary3.csproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/ClassLibrary3.csproj
new file mode 100644
index 000000000..0bcde3dfe
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/ClassLibrary3.csproj
@@ -0,0 +1,61 @@
+
+
+
+
+ Debug
+ AnyCPU
+ 428e95cb-8435-414b-a313-9d734c633b3e
+ Library
+ Properties
+ ClassLibrary3
+ ClassLibrary3
+ v4.6
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..0eadf724e
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ClassLibrary3")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ClassLibrary3")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("428e95cb-8435-414b-a313-9d734c633b3e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ConsoleApp13.sln b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ConsoleApp13.sln
new file mode 100644
index 000000000..1ac8ff099
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ConsoleApp13.sln
@@ -0,0 +1,53 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25029.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1443ACE0-3065-4C20-AD59-D561798AE0A5}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0AE82780-22C8-4DC8-8F1E-86977FDD092F}"
+ ProjectSection(SolutionItems) = preProject
+ global.json = global.json
+ EndProjectSection
+EndProject
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ConsoleApp13", "src\ConsoleApp13\ConsoleApp13.xproj", "{767D3038-AC3A-4722-B21F-F85F2CBC3AA3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary1", "ClassLibrary1\ClassLibrary1.csproj", "{FD073258-550B-4E57-86AE-DC4874015EB1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary2", "ClassLibrary2\ClassLibrary2.csproj", "{0F2D2A48-E867-496C-85A7-E97B64CFEDA4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary3", "ClassLibrary3\ClassLibrary3.csproj", "{428E95CB-8435-414B-A313-9D734C633B3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FD073258-550B-4E57-86AE-DC4874015EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FD073258-550B-4E57-86AE-DC4874015EB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FD073258-550B-4E57-86AE-DC4874015EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FD073258-550B-4E57-86AE-DC4874015EB1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {428E95CB-8435-414B-A313-9D734C633B3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {428E95CB-8435-414B-A313-9D734C633B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {428E95CB-8435-414B-A313-9D734C633B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {428E95CB-8435-414B-A313-9D734C633B3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {767D3038-AC3A-4722-B21F-F85F2CBC3AA3} = {1443ACE0-3065-4C20-AD59-D561798AE0A5}
+ {FD073258-550B-4E57-86AE-DC4874015EB1} = {1443ACE0-3065-4C20-AD59-D561798AE0A5}
+ {0F2D2A48-E867-496C-85A7-E97B64CFEDA4} = {1443ACE0-3065-4C20-AD59-D561798AE0A5}
+ {428E95CB-8435-414B-A313-9D734C633B3E} = {1443ACE0-3065-4C20-AD59-D561798AE0A5}
+ EndGlobalSection
+EndGlobal
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/global.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/global.json
new file mode 100644
index 000000000..5e6422e6d
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/global.json
@@ -0,0 +1,3 @@
+{
+ "projects": [ "src", "test" ]
+}
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/MainApp.xproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/MainApp.xproj
new file mode 100644
index 000000000..ec559dc46
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/MainApp.xproj
@@ -0,0 +1,24 @@
+
+
+
+ 14.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+ 767d3038-ac3a-4722-b21f-f85f2cbc3aa3
+ ConsoleApp13
+ ..\..\artifacts\obj\$(MSBuildProjectName)
+ ..\..\artifacts\
+ v4.6
+
+
+ 2.0
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Program.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Program.cs
new file mode 100644
index 000000000..6723332b1
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Program.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace ConsoleApp13
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ var q = new ClassLibrary1.Class1();
+ }
+ }
+}
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..83e8803f8
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Properties/AssemblyInfo.cs
@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ConsoleApp13")]
+[assembly: AssemblyTrademark("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("767d3038-ac3a-4722-b21f-f85f2cbc3aa3")]
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.fragment.lock.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.fragment.lock.json
new file mode 100644
index 000000000..1efff4670
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.fragment.lock.json
@@ -0,0 +1,36 @@
+{
+ "version": 2,
+ "exports": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.5.2",
+ "compile": {
+ "bin/Debug/ClassLibrary1.dll": {}
+ },
+ "runtime": {
+ "../packages/Newtonsoft.Json.8.0.3/lib/net45/Newtonsoft.Json.dll": {},
+ "bin/Debug/ClassLibrary1.dll": {}
+ }
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary2.dll": {}
+ }
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "framework": ".NETFramework,Version=v4.6",
+ "compile": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ },
+ "runtime": {
+ "bin/Debug/ClassLibrary3.dll": {}
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.json
new file mode 100644
index 000000000..1323d5f29
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.json
@@ -0,0 +1,22 @@
+{
+ "version": "1.0.0-*",
+ "compilationOptions": {
+ "emitEntryPoint": true
+ },
+
+ "frameworks": {
+ "net46": {
+ "dependencies": {
+ "ClassLibrary1": {
+ "target": "project"
+ },
+ "ClassLibrary2": {
+ "target": "project"
+ },
+ "ClassLibrary3": {
+ "target": "project"
+ }
+ }
+ }
+ }
+}
diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.lock.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.lock.json
new file mode 100644
index 000000000..244c3771b
--- /dev/null
+++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.lock.json
@@ -0,0 +1,61 @@
+{
+ "locked": false,
+ "version": 2,
+ "targets": {
+ ".NETFramework,Version=v4.6": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x64": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ },
+ ".NETFramework,Version=v4.6/win7-x86": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project"
+ }
+ }
+ },
+ "libraries": {
+ "ClassLibrary1/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj"
+ },
+ "ClassLibrary2/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj"
+ },
+ "ClassLibrary3/1.0.0": {
+ "type": "project",
+ "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj"
+ }
+ },
+ "projectFileDependencyGroups": {
+ "": [],
+ ".NETFramework,Version=v4.6": [
+ "ClassLibrary1",
+ "ClassLibrary2",
+ "ClassLibrary3"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs
index d83638068..ce43b4b0b 100644
--- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs
@@ -140,11 +140,12 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
return LibraryExportBuilder.Create(library).Build();
}
- if (Equals(LibraryType.Package, library.Identity.Type))
+ var libraryType = library.Identity.Type;
+ if (Equals(LibraryType.Package, libraryType) || Equals(LibraryType.MSBuildProject, libraryType))
{
- return ExportPackage((PackageDescription)library);
+ return ExportPackage((TargetLibraryWithAssets)library);
}
- else if (Equals(LibraryType.Project, library.Identity.Type))
+ else if (Equals(LibraryType.Project, libraryType))
{
return ExportProject((ProjectDescription)library);
}
@@ -154,22 +155,26 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
}
}
- private LibraryExport ExportPackage(PackageDescription package)
+ private LibraryExport ExportPackage(TargetLibraryWithAssets library)
{
- var builder = LibraryExportBuilder.Create(package);
- builder.AddNativeLibraryGroup(new LibraryAssetGroup(PopulateAssets(package, package.NativeLibraries)));
- builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(PopulateAssets(package, package.RuntimeAssemblies)));
- builder.WithCompilationAssemblies(PopulateAssets(package, package.CompileTimeAssemblies));
- builder.WithSourceReferences(GetSharedSources(package));
- builder.WithAnalyzerReference(GetAnalyzerReferences(package));
+ var builder = LibraryExportBuilder.Create(library);
+ builder.AddNativeLibraryGroup(new LibraryAssetGroup(PopulateAssets(library, library.NativeLibraries)));
+ builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(PopulateAssets(library, library.RuntimeAssemblies)));
+ builder.WithCompilationAssemblies(PopulateAssets(library, library.CompileTimeAssemblies));
- if (package.ContentFiles.Any())
+ if (library.Identity.Type.Equals(LibraryType.Package))
+ {
+ builder.WithSourceReferences(GetSharedSources((PackageDescription) library));
+ builder.WithAnalyzerReference(GetAnalyzerReferences((PackageDescription) library));
+ }
+
+ if (library.ContentFiles.Any())
{
var parameters = PPFileParameters.CreateForProject(_rootProject.Project);
Action transform = (input, output) => PPFilePreprocessor.Preprocess(input, output, parameters);
var sourceCodeLanguage = _rootProject.Project.GetSourceCodeLanguage();
- var languageGroups = package.ContentFiles.GroupBy(file => file.CodeLanguage);
+ var languageGroups = library.ContentFiles.GroupBy(file => file.CodeLanguage);
var selectedGroup = languageGroups.FirstOrDefault(g => g.Key == sourceCodeLanguage) ??
languageGroups.FirstOrDefault(g => g.Key == null);
if (selectedGroup != null)
@@ -184,14 +189,14 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
var fileTransform = contentFile.PPOutputPath != null ? transform : null;
- var fullPath = Path.Combine(package.Path, contentFile.Path);
+ var fullPath = Path.Combine(library.Path, contentFile.Path);
if (contentFile.BuildAction == BuildAction.Compile)
{
- builder.AddSourceReference(LibraryAsset.CreateFromRelativePath(package.Path, contentFile.Path, fileTransform));
+ builder.AddSourceReference(LibraryAsset.CreateFromRelativePath(library.Path, contentFile.Path, fileTransform));
}
else if (contentFile.BuildAction == BuildAction.EmbeddedResource)
{
- builder.AddEmbedddedResource(LibraryAsset.CreateFromRelativePath(package.Path, contentFile.Path, fileTransform));
+ builder.AddEmbedddedResource(LibraryAsset.CreateFromRelativePath(library.Path, contentFile.Path, fileTransform));
}
if (contentFile.CopyToOutput)
{
@@ -200,9 +205,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
}
}
}
- if (package.RuntimeTargets.Any())
+ if (library.RuntimeTargets.Any())
{
- foreach (var targetGroup in package.RuntimeTargets.GroupBy(t => t.Runtime))
+ foreach (var targetGroup in library.RuntimeTargets.GroupBy(t => t.Runtime))
{
var runtime = new List();
var native = new List();
@@ -211,11 +216,11 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
{
if (string.Equals(lockFileRuntimeTarget.AssetType, "native", StringComparison.OrdinalIgnoreCase))
{
- native.Add(LibraryAsset.CreateFromRelativePath(package.Path, lockFileRuntimeTarget.Path));
+ native.Add(LibraryAsset.CreateFromRelativePath(library.Path, lockFileRuntimeTarget.Path));
}
else if (string.Equals(lockFileRuntimeTarget.AssetType, "runtime", StringComparison.OrdinalIgnoreCase))
{
- runtime.Add(LibraryAsset.CreateFromRelativePath(package.Path, lockFileRuntimeTarget.Path));
+ runtime.Add(LibraryAsset.CreateFromRelativePath(library.Path, lockFileRuntimeTarget.Path));
}
}
@@ -342,7 +347,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
private IEnumerable GetSharedSources(PackageDescription package)
{
return package
- .Library
+ .PackageLibrary
.Files
.Where(path => path.StartsWith("shared" + Path.DirectorySeparatorChar))
.Select(path => LibraryAsset.CreateFromRelativePath(package.Path, path));
@@ -351,11 +356,12 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
private IEnumerable GetAnalyzerReferences(PackageDescription package)
{
var analyzers = package
- .Library
+ .PackageLibrary
.Files
.Where(path => path.StartsWith("analyzers" + Path.DirectorySeparatorChar) &&
path.EndsWith(".dll"));
+
var analyzerRefs = new List();
// See https://docs.nuget.org/create/analyzers-conventions for the analyzer
// NuGet specification
@@ -416,12 +422,11 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
return analyzerRefs;
}
-
- private IEnumerable PopulateAssets(PackageDescription package, IEnumerable section)
+ private IEnumerable PopulateAssets(TargetLibraryWithAssets library, IEnumerable section)
{
foreach (var assemblyPath in section)
{
- yield return LibraryAsset.CreateFromRelativePath(package.Path, assemblyPath.Path);
+ yield return LibraryAsset.CreateFromRelativePath(library.Path, assemblyPath.Path);
}
}
diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs
index b5111adbb..21b105ae5 100644
--- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs
+++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs
@@ -115,7 +115,7 @@ namespace Microsoft.Extensions.DependencyModel
{
var type = export.Library.Identity.Type;
- var serviceable = (export.Library as PackageDescription)?.Library.IsServiceable ?? false;
+ var serviceable = (export.Library as PackageDescription)?.PackageLibrary.IsServiceable ?? false;
var libraryDependencies = new HashSet();
foreach (var libraryDependency in export.Library.Dependencies)
diff --git a/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs b/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs
index 095bbf9b2..83e229eef 100644
--- a/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs
+++ b/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs
@@ -13,5 +13,8 @@ namespace Microsoft.DotNet.ProjectModel
// Multiple libraries marked as "platform"
public static readonly string DOTNET1013 = nameof(DOTNET1013);
+
+ // Failed to read lock file
+ public static readonly string DOTNET1014 = nameof(DOTNET1014);
}
}
diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/ExportFile.cs b/src/Microsoft.DotNet.ProjectModel/Graph/ExportFile.cs
new file mode 100644
index 000000000..933742559
--- /dev/null
+++ b/src/Microsoft.DotNet.ProjectModel/Graph/ExportFile.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.DotNet.ProjectModel.Graph
+{
+ public class ExportFile
+ {
+ public static readonly string ExportFileName = "project.fragment.lock.json";
+
+ public int Version { get; }
+ public string ExportFilePath { get; }
+
+ public IList Exports { get; }
+
+ public ExportFile(string exportFilePath, int version, IList exports)
+ {
+ ExportFilePath = exportFilePath;
+ Version = version;
+ Exports = exports.Any() ? exports : new List(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs
index 1398b0a88..4a18dccbe 100644
--- a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs
@@ -11,11 +11,13 @@ namespace Microsoft.DotNet.ProjectModel.Graph
public static readonly LibraryType Package = new LibraryType(nameof(Package));
public static readonly LibraryType Project = new LibraryType(nameof(Project));
public static readonly LibraryType ReferenceAssembly = new LibraryType(nameof(ReferenceAssembly));
+ public static readonly LibraryType MSBuildProject = new LibraryType(nameof(MSBuildProject));
// Default value
public static readonly LibraryType Unspecified = new LibraryType();
public string Value { get; }
+
private LibraryType(string value)
{
diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs
index 99e41df88..9f9db6459 100644
--- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs
@@ -4,9 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using Microsoft.DotNet.ProjectModel.Utilities;
-using NuGet.Versioning;
namespace Microsoft.DotNet.ProjectModel.Graph
{
@@ -22,6 +19,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
public IList PackageLibraries { get; set; } = new List();
public IList ProjectLibraries { get; set; } = new List();
public IList Targets { get; set; } = new List();
+ public ExportFile ExportFile { get; set; }
public LockFile(string lockFilePath)
{
diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFilePatcher.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFilePatcher.cs
new file mode 100644
index 000000000..a0f7c0c0e
--- /dev/null
+++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFilePatcher.cs
@@ -0,0 +1,128 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.DotNet.ProjectModel.Resolution;
+
+namespace Microsoft.DotNet.ProjectModel.Graph
+{
+ public class LockFilePatcher
+ {
+ private readonly LockFile _lockFile;
+ private Dictionary> _msbuildTargetLibraries;
+
+ public LockFilePatcher(LockFile lockFile)
+ {
+ _lockFile = lockFile;
+
+ var msbuildProjectLibraries = lockFile.ProjectLibraries.Where(MSBuildDependencyProvider.IsMSBuildProjectLibrary);
+ _msbuildTargetLibraries = msbuildProjectLibraries.ToDictionary(GetProjectLibraryKey, l => GetTargetsForLibrary(_lockFile, l));
+ }
+
+ public void PatchIfNecessary()
+ {
+ var exportFilePath = GetExportFilePath(_lockFile.LockFilePath);
+
+ if (File.Exists(exportFilePath) && _msbuildTargetLibraries.Any())
+ {
+ var exportFile = LockFileReader.ReadExportFile(exportFilePath);
+ PatchLockWithExport(exportFile);
+ }
+ else
+ {
+ ThrowIfAnyMsbuildLibrariesPresent();
+ }
+ }
+
+ public void ThrowIfAnyMsbuildLibrariesPresent()
+ {
+ if (_msbuildTargetLibraries.Any())
+ {
+ throw new LockFilePatchingException($"Lock file {_lockFile} contains msbuild projects but there is no export file");
+ }
+ }
+
+ private void PatchLockWithExport(ExportFile exportFile)
+ {
+ if (_lockFile.Version != exportFile.Version)
+ {
+ throw new LockFilePatchingException($"Export file {exportFile.ExportFilePath} has a different version than the lock file {_lockFile.LockFilePath}");
+ }
+
+ var exportDict = exportFile.Exports.ToDictionary(GetTargetLibraryKey);
+
+ var uncoveredLibraries = _msbuildTargetLibraries.Keys.Except(exportDict.Keys);
+ if (uncoveredLibraries.Any())
+ {
+ throw new LockFilePatchingException($"Export {exportFile.ExportFilePath} does not provide exports for all the msbuild projects in {_lockFile.LockFilePath}");
+ }
+
+ foreach(var exportKey in exportDict.Keys)
+ {
+ var export = exportDict[exportKey];
+ var librariesToPatch = _msbuildTargetLibraries[exportKey];
+
+ foreach (var libraryToPatch in librariesToPatch)
+ {
+ Patch(libraryToPatch, export);
+ }
+ }
+
+ _lockFile.ExportFile = exportFile;
+ }
+
+ private static void Patch(LockFileTargetLibrary libraryToPatch, LockFileTargetLibrary export)
+ {
+ libraryToPatch.CompileTimeAssemblies = export.CompileTimeAssemblies;
+ libraryToPatch.ContentFiles = export.ContentFiles;
+ libraryToPatch.FrameworkAssemblies = export.FrameworkAssemblies;
+ libraryToPatch.NativeLibraries = export.NativeLibraries;
+ libraryToPatch.ResourceAssemblies = export.ResourceAssemblies;
+ libraryToPatch.RuntimeAssemblies = export.RuntimeAssemblies;
+ }
+
+ private static IList GetTargetsForLibrary(LockFile lockFile, LockFileProjectLibrary library)
+ {
+ return lockFile.Targets
+ .SelectMany(
+ t => t.Libraries
+ .Where(
+ l => string.Equals(GetProjectLibraryKey(library), (GetTargetLibraryKey(l)))
+ )
+ )
+ .ToList();
+ }
+
+ private static object TypeName(LockFileTargetLibrary library)
+ {
+ return library.Name + "/" + library.Version + "/" + library.Type;
+ }
+
+ private static string GetTargetLibraryKey(LockFileTargetLibrary library)
+ {
+ return library.Name + "/" + library.Version;
+ }
+
+ private static string GetProjectLibraryKey(LockFileProjectLibrary library)
+ {
+ return library.Name + "/" + library.Version;
+ }
+
+ private static string GetExportFilePath(string masterLockFilePath)
+ {
+ var parentDirectory = Directory.GetParent(masterLockFilePath).FullName;
+ return Path.Combine(parentDirectory, ExportFile.ExportFileName);
+ }
+ }
+
+ internal class LockFilePatchingException : Exception
+ {
+ public LockFilePatchingException(string message) : base(message)
+ {
+ }
+ }
+
+}
diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs
index 7a1b9d632..bdc459235 100644
--- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs
@@ -12,5 +12,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
public NuGetVersion Version { get; set; }
public string Path { get; set; }
+
+ public string MSBuildProject { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs
index cb9d176dd..84fea0ada 100644
--- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs
+++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs
@@ -15,13 +15,13 @@ namespace Microsoft.DotNet.ProjectModel.Graph
{
public static class LockFileReader
{
- public static LockFile Read(string lockFilePath)
+ public static LockFile Read(string lockFilePath, bool patchWithExportFile = true)
{
using (var stream = ResilientFileStreamOpener.OpenFile(lockFilePath))
{
try
{
- return Read(lockFilePath, stream);
+ return Read(lockFilePath, stream, patchWithExportFile);
}
catch (FileFormatException ex)
{
@@ -34,21 +34,36 @@ namespace Microsoft.DotNet.ProjectModel.Graph
}
}
- public static LockFile Read(string lockFilePath, Stream stream)
+ public static LockFile Read(string lockFilePath, Stream stream, bool patchWithExportFile = true)
{
try
{
var reader = new StreamReader(stream);
var jobject = JsonDeserializer.Deserialize(reader) as JsonObject;
- if (jobject != null)
- {
- return ReadLockFile(lockFilePath, jobject);
- }
- else
+ if (jobject == null)
{
throw new InvalidDataException();
}
+
+ var lockFile = ReadLockFile(lockFilePath, jobject);
+
+ var patcher = new LockFilePatcher(lockFile);
+
+ if (patchWithExportFile)
+ {
+ patcher.PatchIfNecessary();
+ }
+ else
+ {
+ patcher.ThrowIfAnyMsbuildLibrariesPresent();
+ }
+
+ return lockFile;
+ }
+ catch (LockFilePatchingException)
+ {
+ throw;
}
catch
{
@@ -60,6 +75,36 @@ namespace Microsoft.DotNet.ProjectModel.Graph
}
}
+ public static ExportFile ReadExportFile(string fragmentLockFilePath)
+ {
+ using (var stream = ResilientFileStreamOpener.OpenFile(fragmentLockFilePath))
+ {
+ try
+ {
+ var rootJObject = JsonDeserializer.Deserialize(new StreamReader(stream)) as JsonObject;
+
+ if (rootJObject == null)
+ {
+ throw new InvalidDataException();
+ }
+
+ var version = ReadInt(rootJObject, "version", defaultValue: int.MinValue);
+ var exports = ReadObject(rootJObject.ValueAsJsonObject("exports"), ReadTargetLibrary);
+
+ return new ExportFile(fragmentLockFilePath, version, exports);
+
+ }
+ catch (FileFormatException ex)
+ {
+ throw ex.WithFilePath(fragmentLockFilePath);
+ }
+ catch (Exception ex)
+ {
+ throw FileFormatException.Create(ex, fragmentLockFilePath);
+ }
+ }
+ }
+
private static LockFile ReadLockFile(string lockFilePath, JsonObject cursor)
{
var lockFile = new LockFile(lockFilePath);
@@ -105,12 +150,19 @@ namespace Microsoft.DotNet.ProjectModel.Graph
}
else if (type == "project")
{
- lockFile.ProjectLibraries.Add(new LockFileProjectLibrary
+ var projectLibrary = new LockFileProjectLibrary
{
Name = name,
- Version = version,
- Path = ReadString(value.Value("path"))
- });
+ Version = version
+ };
+
+ var pathValue = value.Value("path");
+ projectLibrary.Path = pathValue == null ? null : ReadString(pathValue);
+
+ var buildTimeDependencyValue = value.Value("msbuildProject");
+ projectLibrary.MSBuildProject = buildTimeDependencyValue == null ? null : ReadString(buildTimeDependencyValue);
+
+ lockFile.ProjectLibraries.Add(projectLibrary);
}
}
}
diff --git a/src/Microsoft.DotNet.ProjectModel/MSBuildProjectDescription.cs b/src/Microsoft.DotNet.ProjectModel/MSBuildProjectDescription.cs
new file mode 100644
index 000000000..71e613ea4
--- /dev/null
+++ b/src/Microsoft.DotNet.ProjectModel/MSBuildProjectDescription.cs
@@ -0,0 +1,49 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.DotNet.ProjectModel.Graph;
+
+namespace Microsoft.DotNet.ProjectModel
+{
+ ///
+ /// Represents an MSBuild project.
+ /// It has been invisibly built by MSBuild, so it behaves like a package: can provide all assets up front
+ ///
+ /// Path points to the project's directory
+ /// MSBuildPRojectPath points to the csproj file
+ ///
+ public class MSBuildProjectDescription : TargetLibraryWithAssets
+ {
+ public MSBuildProjectDescription(
+ string path,
+ string msbuildProjectPath,
+ LockFileProjectLibrary projectLibrary,
+ LockFileTargetLibrary lockFileLibrary,
+ Project projectFile,
+ IEnumerable dependencies,
+ bool compatible,
+ bool resolved)
+ : base(
+ new LibraryIdentity(projectLibrary.Name, projectLibrary.Version, LibraryType.MSBuildProject),
+ string.Empty, //msbuild projects don't have hashes
+ path,
+ lockFileLibrary,
+ dependencies,
+ resolved: resolved,
+ compatible: compatible,
+ framework: null)
+ {
+ MSBuildProjectPath = msbuildProjectPath;
+ ProjectFile = projectFile;
+ ProjectLibrary = projectLibrary;
+ }
+
+ public LockFileProjectLibrary ProjectLibrary { get; }
+
+ public string MSBuildProjectPath { get; set; }
+
+ public Project ProjectFile { get; }
+ }
+}
diff --git a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs
index ab050b72b..b52e0aa54 100644
--- a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs
+++ b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs
@@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.ProjectModel.Graph;
@@ -9,7 +8,7 @@ using Microsoft.DotNet.ProjectModel.Resolution;
namespace Microsoft.DotNet.ProjectModel
{
- public class PackageDescription : LibraryDescription
+ public class PackageDescription : TargetLibraryWithAssets
{
public PackageDescription(
string path,
@@ -22,32 +21,22 @@ namespace Microsoft.DotNet.ProjectModel
new LibraryIdentity(package.Name, package.Version, LibraryType.Package),
"sha512-" + package.Sha512,
path,
- dependencies: dependencies,
- framework: null,
+ lockFileLibrary,
+ dependencies,
resolved: resolved,
- compatible: compatible)
+ compatible: compatible,
+ framework: null)
{
- Library = package;
- Target = lockFileLibrary;
+ PackageLibrary = package;
}
- private LockFileTargetLibrary Target { get; }
+ public LockFilePackageLibrary PackageLibrary { get; }
- public LockFilePackageLibrary Library { get; }
+ public override IEnumerable RuntimeAssemblies => FilterPlaceholders(base.RuntimeAssemblies);
- public IEnumerable RuntimeAssemblies => FilterPlaceholders(Target.RuntimeAssemblies);
+ public override IEnumerable CompileTimeAssemblies => FilterPlaceholders(base.CompileTimeAssemblies);
- public IEnumerable CompileTimeAssemblies => FilterPlaceholders(Target.CompileTimeAssemblies);
-
- public IEnumerable ResourceAssemblies => Target.ResourceAssemblies;
-
- public IEnumerable NativeLibraries => Target.NativeLibraries;
-
- public IEnumerable ContentFiles => Target.ContentFiles;
-
- public IEnumerable RuntimeTargets => Target.RuntimeTargets;
-
- private IEnumerable FilterPlaceholders(IList items)
+ private static IEnumerable FilterPlaceholders(IEnumerable items)
{
return items.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a));
}
diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs
index b920e857c..7fe2e7622 100644
--- a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs
+++ b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs
@@ -151,7 +151,11 @@ namespace Microsoft.DotNet.ProjectModel
.Where(t => t.TargetFramework.Equals(TargetFramework))
.Any(t => !string.IsNullOrEmpty(t.RuntimeIdentifier));
- var context = Create(ProjectFile.ProjectFilePath, TargetFramework, standalone ? runtimeIdentifiers : Enumerable.Empty());
+ var context = CreateBuilder(ProjectFile.ProjectFilePath, TargetFramework)
+ .WithRuntimeIdentifiers(standalone ? runtimeIdentifiers : Enumerable.Empty())
+ .WithLockFile(LockFile)
+ .Build();
+
if (standalone && context.RuntimeIdentifier == null)
{
// We are standalone, but don't support this runtime
diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs
index 6e2d6b58f..4548a0ad4 100644
--- a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs
+++ b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text;
using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.ProjectModel.Resolution;
using Microsoft.Extensions.Internal;
@@ -138,6 +139,8 @@ namespace Microsoft.DotNet.ProjectModel
public ProjectContext Build()
{
+ var diagnostics = new List();
+
ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory;
if (GlobalSettings == null && ProjectDirectory != null)
@@ -159,7 +162,7 @@ namespace Microsoft.DotNet.ProjectModel
LockFileLookup lockFileLookup = null;
EnsureProjectLoaded();
- LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
+ ReadLockFile(diagnostics);
var validLockFile = true;
string lockFileValidationMessage = null;
@@ -192,8 +195,9 @@ namespace Microsoft.DotNet.ProjectModel
target = SelectTarget(LockFile);
if (target != null)
{
- var packageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver);
- ScanLibraries(target, lockFileLookup, libraries, packageResolver, projectResolver);
+ var nugetPackageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver);
+ var msbuildProjectResolver = new MSBuildDependencyProvider(Project, ProjectResolver);
+ ScanLibraries(target, lockFileLookup, libraries, msbuildProjectResolver, nugetPackageResolver, projectResolver);
}
}
@@ -203,8 +207,6 @@ namespace Microsoft.DotNet.ProjectModel
// Resolve the dependencies
ResolveDependencies(libraries, referenceAssemblyDependencyResolver, out requiresFrameworkAssemblies);
- var diagnostics = new List();
-
// REVIEW: Should this be in NuGet (possibly stored in the lock file?)
if (LockFile == null)
{
@@ -269,6 +271,51 @@ namespace Microsoft.DotNet.ProjectModel
LockFile);
}
+ private void ReadLockFile(ICollection diagnostics)
+ {
+ try
+ {
+ LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
+ }
+ catch (FileFormatException e)
+ {
+ var lockFilePath = "";
+ if (LockFile != null)
+ {
+ lockFilePath = LockFile.LockFilePath;
+ }
+ else if (Project != null)
+ {
+ lockFilePath = Path.Combine(Project.ProjectDirectory, LockFile.FileName);
+ }
+
+ diagnostics.Add(new DiagnosticMessage(
+ ErrorCodes.DOTNET1014,
+ ComposeMessageFromInnerExceptions(e),
+ lockFilePath,
+ DiagnosticMessageSeverity.Error));
+ }
+ }
+
+ private static string ComposeMessageFromInnerExceptions(Exception exception)
+ {
+ var sb = new StringBuilder();
+ var messages = new HashSet();
+
+ while (exception != null)
+ {
+ messages.Add(exception.Message);
+ exception = exception.InnerException;
+ }
+
+ foreach (var message in messages)
+ {
+ sb.AppendLine(message);
+ }
+
+ return sb.ToString();
+ }
+
private void ResolveDependencies(Dictionary libraries,
ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver,
out bool requiresFrameworkAssemblies)
@@ -342,7 +389,7 @@ namespace Microsoft.DotNet.ProjectModel
}
}
- private void ScanLibraries(LockFileTarget target, LockFileLookup lockFileLookup, Dictionary libraries, PackageDependencyProvider packageResolver, ProjectDependencyProvider projectDependencyProvider)
+ private void ScanLibraries(LockFileTarget target, LockFileLookup lockFileLookup, Dictionary libraries, MSBuildDependencyProvider msbuildResolver, PackageDependencyProvider packageResolver, ProjectDependencyProvider projectResolver)
{
foreach (var library in target.Libraries)
{
@@ -355,11 +402,18 @@ namespace Microsoft.DotNet.ProjectModel
if (projectLibrary != null)
{
- var path = Path.GetFullPath(Path.Combine(ProjectDirectory, projectLibrary.Path));
- description = projectDependencyProvider.GetDescription(library.Name, path, library, ProjectResolver);
+ if (MSBuildDependencyProvider.IsMSBuildProjectLibrary(projectLibrary))
+ {
+ description = msbuildResolver.GetDescription(TargetFramework, projectLibrary, library);
+ type = LibraryType.MSBuildProject;
+ }
+ else
+ {
+ var path = Path.GetFullPath(Path.Combine(ProjectDirectory, projectLibrary.Path));
+ description = projectResolver.GetDescription(library.Name, path, library, ProjectResolver);
+ type = LibraryType.Project;
+ }
}
-
- type = LibraryType.Project;
}
else
{
diff --git a/src/Microsoft.DotNet.ProjectModel/Resolution/MSBuildDependencyProvider.cs b/src/Microsoft.DotNet.ProjectModel/Resolution/MSBuildDependencyProvider.cs
new file mode 100644
index 000000000..ea9bda755
--- /dev/null
+++ b/src/Microsoft.DotNet.ProjectModel/Resolution/MSBuildDependencyProvider.cs
@@ -0,0 +1,106 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Microsoft.DotNet.ProjectModel.Graph;
+using NuGet.Frameworks;
+
+namespace Microsoft.DotNet.ProjectModel.Resolution
+{
+ public class MSBuildDependencyProvider
+ {
+ private readonly Project _rootProject;
+ private readonly Func _projectResolver;
+
+ public MSBuildDependencyProvider(Project rootProject, Func projectResolver)
+ {
+ _rootProject = rootProject;
+ _projectResolver = projectResolver;
+ }
+
+ public MSBuildProjectDescription GetDescription(NuGetFramework targetFramework, LockFileProjectLibrary projectLibrary, LockFileTargetLibrary targetLibrary)
+ {
+ var compatible = targetLibrary.FrameworkAssemblies.Any() ||
+ targetLibrary.CompileTimeAssemblies.Any() ||
+ targetLibrary.RuntimeAssemblies.Any();
+
+ var dependencies = new List(targetLibrary.Dependencies.Count + targetLibrary.FrameworkAssemblies.Count);
+ PopulateDependencies(dependencies, targetLibrary, targetFramework);
+
+ var msbuildProjectFilePath = GetMSBuildProjectFilePath(projectLibrary);
+ var msbuildProjectDirectoryPath = Path.GetDirectoryName(msbuildProjectFilePath);
+
+ var exists = Directory.Exists(msbuildProjectDirectoryPath);
+
+ var projectFile = projectLibrary.Path == null ? null : _projectResolver(projectLibrary.Path);
+
+ var msbuildPackageDescription = new MSBuildProjectDescription(
+ msbuildProjectDirectoryPath,
+ msbuildProjectFilePath,
+ projectLibrary,
+ targetLibrary,
+ projectFile,
+ dependencies,
+ compatible,
+ resolved: compatible && exists);
+
+ return msbuildPackageDescription;
+ }
+
+ private string GetMSBuildProjectFilePath(LockFileProjectLibrary projectLibrary)
+ {
+ if (_rootProject == null)
+ {
+ throw new InvalidOperationException("Root xproj project does not exist. Cannot compute the path of its referenced csproj projects.");
+ }
+
+ var rootProjectPath = Path.GetDirectoryName(_rootProject.ProjectFilePath);
+ var msbuildProjectFilePath = Path.Combine(rootProjectPath, projectLibrary.MSBuildProject);
+
+ return Path.GetFullPath(msbuildProjectFilePath);
+ }
+
+ private void PopulateDependencies(
+ List dependencies,
+ LockFileTargetLibrary targetLibrary,
+ NuGetFramework targetFramework)
+ {
+ foreach (var dependency in targetLibrary.Dependencies)
+ {
+ dependencies.Add(new LibraryRange(
+ dependency.Id,
+ dependency.VersionRange,
+ LibraryType.Unspecified,
+ LibraryDependencyType.Default));
+ }
+
+ if (!targetFramework.IsPackageBased)
+ {
+ // Only add framework assemblies for non-package based frameworks.
+ foreach (var frameworkAssembly in targetLibrary.FrameworkAssemblies)
+ {
+ dependencies.Add(new LibraryRange(
+ frameworkAssembly,
+ LibraryType.ReferenceAssembly,
+ LibraryDependencyType.Default));
+ }
+ }
+ }
+
+ public static bool IsMSBuildProjectLibrary(LockFileProjectLibrary projectLibrary)
+ {
+ var msbuildProjectPath = projectLibrary.MSBuildProject;
+ if (msbuildProjectPath == null)
+ {
+ return false;
+ }
+
+ var extension = Path.GetExtension(msbuildProjectPath);
+
+ return !string.Equals(extension, ".xproj", StringComparison.OrdinalIgnoreCase);
+ }
+ }
+}
diff --git a/src/Microsoft.DotNet.ProjectModel/TargetLibraryWithAssets.cs b/src/Microsoft.DotNet.ProjectModel/TargetLibraryWithAssets.cs
new file mode 100644
index 000000000..31a8b48da
--- /dev/null
+++ b/src/Microsoft.DotNet.ProjectModel/TargetLibraryWithAssets.cs
@@ -0,0 +1,47 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using Microsoft.DotNet.ProjectModel.Graph;
+using NuGet.Frameworks;
+
+namespace Microsoft.DotNet.ProjectModel
+{
+ public abstract class TargetLibraryWithAssets : LibraryDescription
+ {
+ public TargetLibraryWithAssets(
+ LibraryIdentity libraryIdentity,
+ string sha512,
+ string path,
+ LockFileTargetLibrary lockFileLibrary,
+ IEnumerable dependencies,
+ bool compatible,
+ bool resolved,
+ NuGetFramework framework = null)
+ : base(
+ libraryIdentity,
+ sha512,
+ path,
+ dependencies: dependencies,
+ framework: null,
+ resolved: resolved,
+ compatible: compatible)
+ {
+ TargetLibrary = lockFileLibrary;
+ }
+
+ private LockFileTargetLibrary TargetLibrary { get; }
+
+ public virtual IEnumerable RuntimeAssemblies => TargetLibrary.RuntimeAssemblies;
+
+ public virtual IEnumerable CompileTimeAssemblies => TargetLibrary.CompileTimeAssemblies;
+
+ public virtual IEnumerable ResourceAssemblies => TargetLibrary.ResourceAssemblies;
+
+ public virtual IEnumerable NativeLibraries => TargetLibrary.NativeLibraries;
+
+ public virtual IEnumerable ContentFiles => TargetLibrary.ContentFiles;
+
+ public virtual IEnumerable RuntimeTargets => TargetLibrary.RuntimeTargets;
+ }
+}
diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs
index db5b0429a..15c1e5dec 100644
--- a/src/dotnet/commands/dotnet-build/CompileContext.cs
+++ b/src/dotnet/commands/dotnet-build/CompileContext.cs
@@ -603,6 +603,11 @@ namespace Microsoft.DotNet.Tools.Build
}
compilerIO.Inputs.Add(project.LockFile.LockFilePath);
+
+ if (project.LockFile.ExportFile != null)
+ {
+ compilerIO.Inputs.Add(project.LockFile.ExportFile.ExportFilePath);
+ }
}
private static void AddDependencies(ProjectDependenciesFacade dependencies, CompilerIO compilerIO)
diff --git a/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs b/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs
index 684d2e403..01cb47e25 100644
--- a/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs
+++ b/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs
@@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Microsoft.DotNet.ProjectModel.Compilation;
+using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.ProjectModel.Server.Helpers;
using Microsoft.DotNet.ProjectModel.Server.Models;
using Microsoft.DotNet.Cli.Compiler.Common;
@@ -51,15 +51,13 @@ namespace Microsoft.DotNet.ProjectModel.Server
var description = DependencyDescription.Create(export.Library, diagnostics, allExports);
allDependencies[description.Name] = description;
- var projectDescription = export.Library as ProjectDescription;
- if (projectDescription != null)
+ var projectReferene = ProjectReferenceDescription.Create(export.Library);
+ if (projectReferene != null && export.Library.Identity.Name != context.ProjectFile.Name)
{
- if (projectDescription.Identity.Name != context.ProjectFile.Name)
- {
- allProjectReferences.Add(ProjectReferenceDescription.Create(projectDescription));
- }
+ allProjectReferences.Add(projectReferene);
}
- else
+
+ if (export.Library.Identity.Type != LibraryType.Project)
{
allFileReferences.AddRange(export.CompilationAssemblies.Select(asset => asset.ResolvedPath));
}
diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs b/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs
index c30be87d9..07aa58a64 100644
--- a/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs
+++ b/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs
@@ -5,7 +5,6 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.ProjectModel.Compilation;
using Microsoft.DotNet.ProjectModel.Graph;
-using Microsoft.DotNet.ProjectModel.Server.Helpers;
namespace Microsoft.DotNet.ProjectModel.Server.Models
{
@@ -24,7 +23,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models
public string Type { get; private set; }
public bool Resolved { get; private set; }
-
+
public IEnumerable Dependencies { get; private set; }
public IEnumerable Errors { get; private set; }
@@ -57,7 +56,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models
List diagnostics,
IDictionary exportsLookup)
{
- return new DependencyDescription
+ var result = new DependencyDescription
{
Name = library.Identity.Name,
DisplayName = library.Identity.Name,
@@ -71,6 +70,14 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models
Warnings = diagnostics.Where(d => d.Severity == DiagnosticMessageSeverity.Warning)
.Select(d => new DiagnosticMessageView(d))
};
+
+ var msbuildLibrary = library as MSBuildProjectDescription;
+ if (msbuildLibrary != null)
+ {
+ result.Path = msbuildLibrary.MSBuildProjectPath;
+ }
+
+ return result;
}
private static DependencyItem GetDependencyItem(LibraryRange dependency,
diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs b/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs
index b0cb6ffc0..224837488 100644
--- a/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs
+++ b/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs
@@ -1,8 +1,6 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using NuGet.Frameworks;
-
namespace Microsoft.DotNet.ProjectModel.Server.Models
{
internal class ProjectReferenceDescription
@@ -12,44 +10,48 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models
public FrameworkData Framework { get; set; }
public string Name { get; set; }
public string Path { get; set; }
- public string WrappedProjectPath { get; set; }
public override bool Equals(object obj)
{
var other = obj as ProjectReferenceDescription;
return other != null &&
string.Equals(Name, other.Name) &&
- string.Equals(Path, other.Path) &&
- string.Equals(WrappedProjectPath, other.WrappedProjectPath);
+ string.Equals(Path, other.Path);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
-
- public static ProjectReferenceDescription Create(ProjectDescription description)
+
+ ///
+ /// Create a ProjectReferenceDescription from given LibraryDescription. If the library doesn't
+ /// represent a project reference returns null.
+ ///
+ public static ProjectReferenceDescription Create(LibraryDescription library)
{
- var targetFrameworkInformation = description.TargetFrameworkInfo;
-
- string wrappedProjectPath = null;
- if (!string.IsNullOrEmpty(targetFrameworkInformation?.WrappedProject) &&
- description.Project != null)
+ if (library is ProjectDescription)
{
- wrappedProjectPath = System.IO.Path.Combine(
- description.Project.ProjectDirectory,
- targetFrameworkInformation.WrappedProject);
-
- wrappedProjectPath = System.IO.Path.GetFullPath(wrappedProjectPath);
+ return new ProjectReferenceDescription
+ {
+ Framework = library.Framework.ToPayload(),
+ Name = library.Identity.Name,
+ Path = library.Path
+ };
}
-
- return new ProjectReferenceDescription
+ else if (library is MSBuildProjectDescription)
{
- Framework = description.Framework.ToPayload(),
- Name = description.Identity.Name,
- Path = description.Path,
- WrappedProjectPath = wrappedProjectPath,
- };
+ return new ProjectReferenceDescription
+ {
+ Framework = library.Framework.ToPayload(),
+ Name = library.Identity.Name,
+ Path = ((MSBuildProjectDescription)library).MSBuildProjectPath,
+ };
+ }
+ else
+ {
+ return null;
+ }
}
}
}
diff --git a/src/dotnet/commands/dotnet-publish/Program.cs b/src/dotnet/commands/dotnet-publish/Program.cs
index e06e484a9..849fec5fd 100644
--- a/src/dotnet/commands/dotnet-publish/Program.cs
+++ b/src/dotnet/commands/dotnet-publish/Program.cs
@@ -28,6 +28,7 @@ namespace Microsoft.DotNet.Tools.Publish
var configuration = app.Option("-c|--configuration ", "Configuration under which to build", CommandOptionType.SingleValue);
var projectPath = app.Argument("", "The project to publish, defaults to the current directory. Can be a path to a project.json or a project directory");
var nativeSubdirectories = app.Option("--native-subdirectory", "Temporary mechanism to include subdirectories from native assets of dependency packages in output", CommandOptionType.NoValue);
+ var noBuild = app.Option("--no-build", "Do not build projects before publishing", CommandOptionType.NoValue);
app.OnExecute(() =>
{
@@ -41,6 +42,7 @@ namespace Microsoft.DotNet.Tools.Publish
publish.NativeSubdirectories = nativeSubdirectories.HasValue();
publish.ProjectPath = projectPath.Value;
publish.VersionSuffix = versionSuffix.Value();
+ publish.ShouldBuild = !noBuild.HasValue();
if (string.IsNullOrEmpty(publish.ProjectPath))
{
diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs
index 9fb175ed7..abe835442 100644
--- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs
+++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs
@@ -35,6 +35,7 @@ namespace Microsoft.DotNet.Tools.Publish
public string VersionSuffix { get; set; }
public int NumberOfProjects { get; private set; }
public int NumberOfPublishedProjects { get; private set; }
+ public bool ShouldBuild { get; set; }
public bool TryPrepareForPublish()
{
@@ -119,34 +120,7 @@ namespace Microsoft.DotNet.Tools.Publish
}
// Compile the project (and transitively, all it's dependencies)
- var args = new List() {
- "--framework",
- $"{context.TargetFramework.DotNetFrameworkName}",
- "--configuration",
- configuration,
- context.ProjectFile.ProjectDirectory
- };
-
- if (!string.IsNullOrEmpty(context.RuntimeIdentifier))
- {
- args.Insert(0, context.RuntimeIdentifier);
- args.Insert(0, "--runtime");
- }
-
- if (!string.IsNullOrEmpty(VersionSuffix))
- {
- args.Add("--version-suffix");
- args.Add(VersionSuffix);
- }
-
- if (!string.IsNullOrEmpty(buildBasePath))
- {
- args.Add("--build-base-path");
- args.Add(buildBasePath);
- }
-
- var result = Build.BuildCommand.Run(args.ToArray());
- if (result != 0)
+ if (ShouldBuild && !InvokeBuildOnProject(context, buildBasePath, configuration))
{
return false;
}
@@ -206,6 +180,40 @@ namespace Microsoft.DotNet.Tools.Publish
return true;
}
+ private bool InvokeBuildOnProject(ProjectContext context, string buildBasePath, string configuration)
+ {
+ var args = new List()
+ {
+ "--framework",
+ $"{context.TargetFramework.DotNetFrameworkName}",
+ "--configuration",
+ configuration,
+ context.ProjectFile.ProjectDirectory
+ };
+
+ if (!string.IsNullOrEmpty(context.RuntimeIdentifier))
+ {
+ args.Insert(0, context.RuntimeIdentifier);
+ args.Insert(0, "--runtime");
+ }
+
+ if (!string.IsNullOrEmpty(VersionSuffix))
+ {
+ args.Add("--version-suffix");
+ args.Add(VersionSuffix);
+ }
+
+ if (!string.IsNullOrEmpty(buildBasePath))
+ {
+ args.Add("--build-base-path");
+ args.Add(buildBasePath);
+ }
+
+ var result = Build.BuildCommand.Run(args.ToArray());
+
+ return result == 0;
+ }
+
private HashSet GetExclusionList(ProjectContext context, Dictionary exports)
{
var exclusionList = new HashSet();
diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/LockFilePatchingTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/LockFilePatchingTests.cs
new file mode 100644
index 000000000..2688643ee
--- /dev/null
+++ b/test/Microsoft.DotNet.ProjectModel.Tests/LockFilePatchingTests.cs
@@ -0,0 +1,127 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.IO;
+using System.Linq;
+using FluentAssertions;
+using Xunit;
+using Microsoft.DotNet.ProjectModel.Graph;
+using Microsoft.DotNet.Tools.Test.Utilities;
+using NuGet.ProjectModel;
+
+namespace Microsoft.DotNet.ProjectModel.Tests
+{
+ public class LockFilePatchingTests : TestBase
+ {
+
+ private static string ExportFilesRoot=> Path.Combine(RepoRoot, "TestAssets", "LockFiles", "ExportFiles");
+
+ [Fact]
+ public void TestExportFileIsParsed()
+ {
+ var lockFilePath = GetLockFilePath("valid");
+ var lockFile = LockFileReader.Read(lockFilePath);
+
+ var exportFile = lockFile.ExportFile;
+
+ exportFile.Should().NotBeNull();
+ exportFile.Exports.Count.Should().Be(3);
+ exportFile.Exports.Should().OnlyHaveUniqueItems();
+
+ // check export structure
+ foreach (var export in exportFile.Exports)
+ {
+ export.TargetFramework.Should().NotBeNull();
+ AssertTargetLibrary(export);
+ }
+ }
+
+ [Fact]
+ public void TestLockFileIsPatchedWithExportData()
+ {
+ var lockFilePath = GetLockFilePath("valid");
+ var lockFile = LockFileReader.Read(lockFilePath);
+
+ // check lock file structure is similar to export structure
+ foreach (var target in lockFile.Targets)
+ {
+ target.Libraries.Count.Should().Be(3);
+
+ foreach (var library in target.Libraries)
+ {
+ AssertTargetLibrary(library);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestFragmentExistsButNoHolesInLockFile()
+ {
+ var lockFilePath = GetLockFilePath("valid_staleFragment");
+ var lockFile = LockFileReader.Read(lockFilePath);
+
+ var exportFile = lockFile.ExportFile;
+
+ exportFile.Should().BeNull();
+
+ lockFile.Targets.Count.Should().Be(1);
+
+ lockFile.Targets[0].Libraries.Count.Should().Be(0);
+ }
+
+ [Fact]
+ public void TestMissingExportFileThrows()
+ {
+ var lockFilePath = GetLockFilePath("invalid_nofragment");
+
+ Assert.Throws(() => LockFileReader.Read(lockFilePath));
+ }
+
+ [Fact]
+ public void TestMissingExportsThrow()
+ {
+ var lockFilePath = GetLockFilePath("invalid_missing-exports");
+
+ Assert.Throws(() => LockFileReader.Read(lockFilePath));
+ }
+
+ [Fact]
+ public void TestMissmatchingFileVersionsThrows()
+ {
+ var lockFilePath = GetLockFilePath("invalid_missmatching-versions");
+
+ Assert.Throws(() => LockFileReader.Read(lockFilePath));
+ }
+
+ private static int LibraryNumberFromName(Microsoft.DotNet.ProjectModel.Graph.LockFileTargetLibrary library)
+ {
+ var libraryName = library.Name;
+ return (int)char.GetNumericValue(libraryName[libraryName.Length - 1]);
+ }
+
+ private static void AssertTargetLibrary(Microsoft.DotNet.ProjectModel.Graph.LockFileTargetLibrary library)
+ {
+ var libraryNumber = LibraryNumberFromName(library);
+
+ library.Type.Should().Be("project");
+
+ library.Name.Should().Be("ClassLibrary" + libraryNumber);
+ library.Version.ToNormalizedString().Should().Be("1.0.0");
+
+ var dll = $"bin/Debug/ClassLibrary{libraryNumber}.dll";
+ dll = dll.Replace('/', Path.DirectorySeparatorChar);
+
+ library.CompileTimeAssemblies.Count.Should().Be(1);
+ library.CompileTimeAssemblies.ElementAt(0).Path.Should().Be(dll);
+
+ library.RuntimeAssemblies.Count.Should().Be(1);
+ library.RuntimeAssemblies.ElementAt(0).Path.Should().Be(dll);
+ }
+
+ private static string GetLockFilePath(string exportSample)
+ {
+ return Path.Combine(ExportFilesRoot, exportSample, "project.lock.json");
+ }
+ }
+}
diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs
index 284d5be39..509530b9b 100644
--- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs
+++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs
@@ -19,9 +19,10 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
private readonly string _framework;
private readonly string _runtime;
private readonly string _config;
+ private readonly bool _noBuild;
private readonly string _output;
- public PublishCommand(string projectPath, string framework = "", string runtime = "", string output = "", string config = "", bool forcePortable = false)
+ public PublishCommand(string projectPath, string framework = "", string runtime = "", string output = "", string config = "", bool forcePortable = false, bool noBuild = false)
: base("dotnet")
{
_path = projectPath;
@@ -30,6 +31,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
_runtime = runtime;
_output = output;
_config = config;
+ _noBuild = noBuild;
}
public override CommandResult Execute(string args = "")
@@ -91,12 +93,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
private string BuildArgs()
{
- return $"{_path} {FrameworkOption} {RuntimeOption} {OutputOption} {ConfigOption}";
+ return $"{_path} {FrameworkOption} {RuntimeOption} {OutputOption} {ConfigOption} {NoBuildFlag}";
}
private string FrameworkOption => string.IsNullOrEmpty(_framework) ? "" : $"-f {_framework}";
private string RuntimeOption => string.IsNullOrEmpty(_runtime) ? "" : $"-r {_runtime}";
private string OutputOption => string.IsNullOrEmpty(_output) ? "" : $"-o \"{_output}\"";
private string ConfigOption => string.IsNullOrEmpty(_config) ? "" : $"-c {_output}";
+ private string NoBuildFlag => _noBuild ? "--no-build" :"";
}
}
diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs
index 1d10084ab..92df20c70 100644
--- a/test/dotnet-projectmodel-server.Tests/DthTests.cs
+++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
@@ -148,8 +149,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
.AssertJArrayCount(1)
.RetrieveArraryElementAs(0)
.AssertProperty("Name", expectedUnresolvedDependency)
- .AssertProperty("Path", expectedUnresolvedProjectPath)
- .AssertProperty("WrappedProjectPath", prop => !prop.HasValues);
+ .AssertProperty("Path", expectedUnresolvedProjectPath);
}
else if (referenceType == "Package")
{
@@ -412,5 +412,64 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
}
}
}
+
+ [Fact]
+ public void MSBuildReferenceTest()
+ {
+ var testProject = Path.Combine(RepoRoot, "TestAssets",
+ "ProjectModelServer",
+ "MSBuildReferencesProjects",
+ "ValidCase01",
+ "src",
+ "MainApp");
+
+ using (var server = new DthTestServer(_loggerFactory))
+ using (var client = new DthTestClient(server, _loggerFactory))
+ {
+ client.Initialize(testProject);
+ var messages = client.DrainAllMessages();
+
+ var classLibraries = new HashSet(new string[] { "ClassLibrary1", "ClassLibrary2", "ClassLibrary3" });
+ var dependencies = messages.RetrieveSingleMessage(MessageTypes.Dependencies);
+ var testProjectRoot = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MSBuildReferencesProjects", "ValidCase01");
+ foreach (var classLibrary in classLibraries)
+ {
+ dependencies.RetrieveDependency(classLibrary)
+ .AssertProperty("Type", LibraryType.MSBuildProject.ToString())
+ .AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, classLibrary, $"{classLibrary}.csproj")))
+ .AssertProperty("Resolved", true)
+ .AssertProperty("Name", classLibrary)
+ .AssertProperty("Errors", array => array.Count == 0)
+ .AssertProperty("Warnings", array => array.Count == 0);
+ }
+
+ var references = messages.RetrieveSingleMessage(MessageTypes.References)
+ .RetrievePayloadAs();
+
+ var projectReferences = references.RetrievePropertyAs("ProjectReferences");
+ Assert.Equal(3, projectReferences.Count);
+ for (int i = 0; i < 3; ++i)
+ {
+ var projectRef = projectReferences.RetrieveArraryElementAs(i);
+ var name = projectRef["Name"].Value();
+
+ Assert.True(classLibraries.Contains(name));
+ projectRef.AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, name, $"{name}.csproj")));
+ }
+
+ var fileReferences = references.RetrievePropertyAs("FileReferences")
+ .Select(each => each.Value())
+ .ToArray();
+ foreach (var each in classLibraries)
+ {
+ fileReferences.Contains(Path.Combine("ValidCase01", "ClassLibrary1", "bin", "Debug", $"{each}.dll"));
+ }
+ }
+ }
+
+ private static string NormalizePathString(string original)
+ {
+ return original.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar);
+ }
}
}
diff --git a/test/dotnet-publish.Tests/PublishTests.cs b/test/dotnet-publish.Tests/PublishTests.cs
index 7aa760807..99a282b7f 100644
--- a/test/dotnet-publish.Tests/PublishTests.cs
+++ b/test/dotnet-publish.Tests/PublishTests.cs
@@ -176,6 +176,31 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
publishCommand.Execute().Should().Fail();
}
+ [Fact]
+ public void PublishFailsWhenProjectNotBuiltAndNoBuildFlagSet()
+ {
+ TestInstance instance = TestAssetsManager.CreateTestInstance("TestAppCompilationContext")
+ .WithLockFiles();
+
+ var testProject = _getProjectJson(instance.TestRoot, "TestApp");
+ var publishCommand = new PublishCommand(testProject, noBuild: true);
+
+ publishCommand.Execute().Should().Fail();
+ }
+
+ [Fact]
+ public void PublishSucceedsWhenProjectPreviouslyCompiledAndNoBuildFlagSet()
+ {
+ TestInstance instance = TestAssetsManager.CreateTestInstance("TestAppCompilationContext")
+ .WithLockFiles()
+ .WithBuildArtifacts();
+
+ var testProject = _getProjectJson(instance.TestRoot, "TestApp");
+ var publishCommand = new PublishCommand(testProject, noBuild: true);
+
+ publishCommand.Execute().Should().Pass();
+ }
+
[Fact]
public void PublishScriptsRun()
{
diff --git a/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs b/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs
index f1c0629c1..81d9da1c1 100644
--- a/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs
+++ b/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs
@@ -21,7 +21,7 @@ namespace Microsoft.DotNet.ProjectModel
{
if (export.Library.Identity.Type == LibraryType.Package)
{
- var runtimeJson = ((PackageDescription) export.Library).Library.Files.FirstOrDefault(f => f == RuntimeJsonFileName);
+ var runtimeJson = ((PackageDescription) export.Library).PackageLibrary.Files.FirstOrDefault(f => f == RuntimeJsonFileName);
if (runtimeJson != null)
{
var runtimeJsonFullName = Path.Combine(export.Library.Path, runtimeJson);