public Project ReadProject(Stream stream, string projectName, string projectPath, ProjectReaderSettings settings = null) { settings = settings ?? new ProjectReaderSettings(); var project = new Project(); var reader = new StreamReader(stream); JObject rawProject; using (var jsonReader = new JsonTextReader(reader)) { rawProject = JObject.Load(jsonReader); // Try to read another token to ensure we're at the end of the document. // This will no-op if we are, and throw a JsonReaderException if there is additional content (which is what we want) jsonReader.Read(); } if (rawProject == null) { throw FileFormatException.Create( "The JSON file can't be deserialized to a JSON object.", projectPath); } // Meta-data properties project.Name = rawProject.Value <string>("name") ?? projectName; project.ProjectFilePath = Path.GetFullPath(projectPath); var version = rawProject.Value <string>("version"); if (version == null) { project.Version = new NuGetVersion("1.0.0"); } else { try { var buildVersion = settings.VersionSuffix; project.Version = SpecifySnapshot(version, buildVersion); } catch (Exception ex) { throw FileFormatException.Create(ex, version, project.ProjectFilePath); } } var fileVersion = settings.AssemblyFileVersion; if (string.IsNullOrWhiteSpace(fileVersion)) { project.AssemblyFileVersion = project.Version.Version; } else { try { var simpleVersion = project.Version.Version; project.AssemblyFileVersion = new Version(simpleVersion.Major, simpleVersion.Minor, simpleVersion.Build, int.Parse(fileVersion)); } catch (FormatException ex) { throw new FormatException("The assembly file version is invalid: " + fileVersion, ex); } } project.Description = rawProject.Value <string>("description"); project.Copyright = rawProject.Value <string>("copyright"); project.Title = rawProject.Value <string>("title"); project.EntryPoint = rawProject.Value <string>("entryPoint"); project.TestRunner = rawProject.Value <string>("testRunner"); project.Authors = rawProject.Value <JToken>("authors")?.Values <string>().ToArray() ?? EmptyArray <string> .Value; project.Language = rawProject.Value <string>("language"); // REVIEW: Move this to the dependencies node? project.EmbedInteropTypes = rawProject.Value <bool>("embedInteropTypes"); project.Dependencies = new List <ProjectLibraryDependency>(); project.Tools = new List <ProjectLibraryDependency>(); project.Runtimes = new List <string>(); // Project files project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath); AddProjectFilesCollectionDiagnostics(rawProject, project); var commands = rawProject.Value <JToken>("commands") as JObject; if (commands != null) { foreach (var command in commands) { var commandValue = command.Value.Type == JTokenType.String ? command.Value.Value <string>() : null; if (commandValue != null) { project.Commands[command.Key] = commandValue; } } } var scripts = rawProject.Value <JToken>("scripts") as JObject; if (scripts != null) { foreach (var script in scripts) { var stringValue = script.Value.Type == JTokenType.String ? script.Value.Value <string>() : null; if (stringValue != null) { project.Scripts[script.Key] = new string[] { stringValue }; continue; } var arrayValue = script.Value.Type == JTokenType.Array ? script.Value.Values <string>().ToArray() : null; if (arrayValue != null) { project.Scripts[script.Key] = arrayValue; continue; } throw FileFormatException.Create( string.Format("The value of a script in {0} can only be a string or an array of strings", Project.FileName), script.Value, project.ProjectFilePath); } } project.PackOptions = GetPackOptions(rawProject, project) ?? new PackOptions(); project.RuntimeOptions = GetRuntimeOptions(rawProject) ?? new RuntimeOptions(); project.PublishOptions = GetPublishInclude(rawProject, project); BuildTargetFrameworksAndConfigurations(project, rawProject); PopulateDependencies( project.ProjectFilePath, project.Dependencies, rawProject, "dependencies", isGacOrFrameworkReference: false); PopulateDependencies( project.ProjectFilePath, project.Tools, rawProject, "tools", isGacOrFrameworkReference: false); PopulateRuntimes(project.Runtimes, rawProject); JToken runtimeOptionsToken; if (rawProject.TryGetValue("runtimeOptions", out runtimeOptionsToken)) { var runtimeOptions = runtimeOptionsToken as JObject; if (runtimeOptions == null) { throw FileFormatException.Create("The runtimeOptions must be an object", runtimeOptionsToken); } project.RawRuntimeOptions = runtimeOptions.ToString(); } return(project); }
private void BuildTargetFrameworksAndConfigurations(Project project, JObject projectJsonObject) { // Get the shared compilationOptions project._defaultCompilerOptions = GetCompilationOptions(projectJsonObject, project) ?? new CommonCompilerOptions { CompilerName = "csc" }; project._defaultTargetFrameworkConfiguration = new TargetFrameworkInformation { Dependencies = new List <ProjectLibraryDependency>() }; // Add default configurations project._compilerOptionsByConfiguration["Debug"] = new CommonCompilerOptions { Defines = new[] { "DEBUG", "TRACE" }, Optimize = false }; project._compilerOptionsByConfiguration["Release"] = new CommonCompilerOptions { Defines = new[] { "RELEASE", "TRACE" }, Optimize = true }; // The configuration node has things like debug/release compiler settings /* * { * "configurations": { * "Debug": { * }, * "Release": { * } * } * } */ var configurationsSection = projectJsonObject.Value <JToken>("configurations") as JObject; if (configurationsSection != null) { foreach (var configKey in configurationsSection) { var compilerOptions = GetCompilationOptions(configKey.Value as JObject, project); // Only use this as a configuration if it's not a target framework project._compilerOptionsByConfiguration[configKey.Key] = compilerOptions; } } // The frameworks node is where target frameworks go /* * { * "frameworks": { * "net45": { * }, * "dnxcore50": { * } * } * } */ var frameworks = projectJsonObject.Value <JToken>("frameworks") as JObject; if (frameworks != null) { foreach (var framework in frameworks) { try { var frameworkToken = framework.Value as JObject; var success = BuildTargetFrameworkNode(project, framework.Key, frameworkToken); if (!success) { var lineInfo = (IJsonLineInfo)framework.Value; project.Diagnostics.Add( new DiagnosticMessage( ErrorCodes.NU1008, $"\"{framework.Key}\" is an unsupported framework.", project.ProjectFilePath, DiagnosticMessageSeverity.Error, lineInfo.LineNumber, lineInfo.LinePosition)); } } catch (Exception ex) { throw FileFormatException.Create(ex, framework.Value, project.ProjectFilePath); } } } }
private static CommonCompilerOptions GetCompilationOptions(JObject rawObject, Project project) { var compilerName = rawObject.Value <string>("compilerName"); if (compilerName != null) { var lineInfo = rawObject.Value <IJsonLineInfo>("compilerName"); project.Diagnostics.Add( new DiagnosticMessage( ErrorCodes.DOTNET1016, $"The 'compilerName' option in the root is deprecated. Use it in 'buildOptions' instead.", project.ProjectFilePath, DiagnosticMessageSeverity.Warning, lineInfo.LineNumber, lineInfo.LinePosition)); } var rawOptions = rawObject.Value <JToken>("buildOptions") as JObject; if (rawOptions == null) { rawOptions = rawObject.Value <JToken>("compilationOptions") as JObject; if (rawOptions == null) { return(new CommonCompilerOptions { CompilerName = compilerName ?? "csc" }); } var lineInfo = (IJsonLineInfo)rawOptions; project.Diagnostics.Add( new DiagnosticMessage( ErrorCodes.DOTNET1015, $"The 'compilationOptions' option is deprecated. Use 'buildOptions' instead.", project.ProjectFilePath, DiagnosticMessageSeverity.Warning, lineInfo.LineNumber, lineInfo.LinePosition)); } var analyzerOptionsJson = rawOptions.Value <JToken>("analyzerOptions") as JObject; if (analyzerOptionsJson != null) { var analyzerOptions = new AnalyzerOptions(); foreach (var analyzerOption in analyzerOptionsJson) { switch (analyzerOption.Key) { case "languageId": if (analyzerOption.Value.Type != JTokenType.String) { throw FileFormatException.Create( "The analyzer languageId must be a string", analyzerOption.Value.ToString(), project.ProjectFilePath); } analyzerOptions = new AnalyzerOptions(analyzerOption.Value.ToString()); break; default: throw FileFormatException.Create( $"Unrecognized analyzerOption key: {analyzerOption.Key}", project.ProjectFilePath); } } project.AnalyzerOptions = analyzerOptions; } return(new CommonCompilerOptions { Defines = rawOptions.Value <JToken>("define")?.Values <string>().ToArray(), SuppressWarnings = rawOptions.Value <JToken>("nowarn")?.Values <string>().ToArray(), AdditionalArguments = rawOptions.Value <JToken>("additionalArguments")?.Values <string>().ToArray(), LanguageVersion = rawOptions.Value <string>("languageVersion"), AllowUnsafe = rawOptions.Value <bool?>("allowUnsafe"), Platform = rawOptions.Value <string>("platform"), WarningsAsErrors = rawOptions.Value <bool?>("warningsAsErrors"), Optimize = rawOptions.Value <bool?>("optimize"), KeyFile = rawOptions.Value <string>("keyFile"), DelaySign = rawOptions.Value <bool?>("delaySign"), PublicSign = rawOptions.Value <bool?>("publicSign"), DebugType = rawOptions.Value <string>("debugType"), EmitEntryPoint = rawOptions.Value <bool?>("emitEntryPoint"), GenerateXmlDocumentation = rawOptions.Value <bool?>("xmlDoc"), PreserveCompilationContext = rawOptions.Value <bool?>("preserveCompilationContext"), OutputName = rawOptions.Value <string>("outputName"), CompilerName = rawOptions.Value <string>("compilerName") ?? compilerName ?? "csc", CompileInclude = GetIncludeContext( project, rawOptions, "compile", defaultBuiltInInclude: ProjectFilesCollection.DefaultCompileBuiltInPatterns, defaultBuiltInExclude: ProjectFilesCollection.DefaultBuiltInExcludePatterns), EmbedInclude = GetIncludeContext( project, rawOptions, "embed", defaultBuiltInInclude: ProjectFilesCollection.DefaultResourcesBuiltInPatterns, defaultBuiltInExclude: ProjectFilesCollection.DefaultBuiltInExcludePatterns), CopyToOutputInclude = GetIncludeContext( project, rawOptions, "copyToOutput", defaultBuiltInInclude: null, defaultBuiltInExclude: ProjectFilesCollection.DefaultPublishExcludePatterns) }); }
private static void PopulateDependencies( string projectPath, IList <ProjectLibraryDependency> results, JObject settings, string propertyName, bool isGacOrFrameworkReference) { var dependencies = settings.Value <JToken>(propertyName) as JObject; if (dependencies != null) { foreach (var dependency in dependencies) { if (string.IsNullOrEmpty(dependency.Key)) { throw FileFormatException.Create( "Unable to resolve dependency ''.", dependency.Key, projectPath); } var dependencyValue = dependency.Value; var dependencyTypeValue = LibraryDependencyType.Default; var dependencyIncludeFlagsValue = LibraryIncludeFlags.All; var dependencyExcludeFlagsValue = LibraryIncludeFlags.None; var suppressParentFlagsValue = LibraryIncludeFlagUtils.DefaultSuppressParent; var target = isGacOrFrameworkReference ? LibraryDependencyTarget.Reference : LibraryDependencyTarget.All; string dependencyVersionAsString = null; if (dependencyValue.Type == JTokenType.Object) { // "dependencies" : { "Name" : { "version": "1.0", "type": "build", "target": "project" } } dependencyVersionAsString = dependencyValue.Value <string>("version"); var type = dependencyValue.Value <string>("type"); if (type != null) { dependencyTypeValue = LibraryDependencyType.Parse(new [] { type }); } // Read the target if specified if (!isGacOrFrameworkReference) { var targetStr = dependencyValue.Value <string>("target"); target = LibraryDependencyTargetUtils.Parse(targetStr); } IEnumerable <string> strings; if (TryGetStringEnumerable(dependencyValue["include"], out strings)) { dependencyIncludeFlagsValue = LibraryIncludeFlagUtils.GetFlags(strings); } if (TryGetStringEnumerable(dependencyValue["exclude"], out strings)) { dependencyExcludeFlagsValue = LibraryIncludeFlagUtils.GetFlags(strings); } if (TryGetStringEnumerable(dependencyValue["suppressParent"], out strings)) { // This overrides any settings that came from the type property. suppressParentFlagsValue = LibraryIncludeFlagUtils.GetFlags(strings); } } else if (dependencyValue.Type == JTokenType.String) { // "dependencies" : { "Name" : "1.0" } dependencyVersionAsString = dependencyValue.Value <string>(); } else { throw FileFormatException.Create( string.Format( "Invalid dependency version: {0}. The format is not recognizable.", dependency.Key), dependencyValue, projectPath); } VersionRange dependencyVersionRange = null; if (!string.IsNullOrEmpty(dependencyVersionAsString)) { try { dependencyVersionRange = VersionRange.Parse(dependencyVersionAsString); } catch (Exception ex) { throw FileFormatException.Create(ex, dependencyValue, projectPath); } } // the dependency flags are: Include flags - Exclude flags var includeFlags = dependencyIncludeFlagsValue & ~dependencyExcludeFlagsValue; var lineInfo = (IJsonLineInfo)dependencyValue; results.Add(new ProjectLibraryDependency { LibraryRange = new LibraryRange( dependency.Key, dependencyVersionRange, target), Type = dependencyTypeValue, IncludeType = includeFlags, SuppressParent = suppressParentFlagsValue, SourceFilePath = projectPath, SourceLine = lineInfo.LineNumber, SourceColumn = lineInfo.LinePosition }); } } }