Skip to content
This repository was archived by the owner on Dec 18, 2017. It is now read-only.

Added ProjectFormatException and more detailed errors to DTH #1065

Merged
merged 1 commit into from
Jan 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/Microsoft.Framework.DesignTimeHost/ApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Linq;
using System.Runtime.Versioning;
using System.Threading;
using Microsoft.CodeAnalysis.Text;
using Microsoft.Framework.DesignTimeHost.Models;
using Microsoft.Framework.DesignTimeHost.Models.IncomingMessages;
using Microsoft.Framework.DesignTimeHost.Models.OutgoingMessages;
Expand Down Expand Up @@ -103,6 +102,14 @@ public void ProcessLoop(object state)
Message = ex.Message
};

var projectFormatException = ex as ProjectFormatException;
if (projectFormatException != null)
{
error.Path = projectFormatException.Path;
error.Line = projectFormatException.Line;
error.Column = projectFormatException.Column;
}

var message = new Message
{
ContextId = Id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ namespace Microsoft.Framework.DesignTimeHost.Models.OutgoingMessages
public class ErrorMessage
{
public string Message { get; set; }
public string Path { get; set; }
public int Line { get; set; }
public int Column { get; set; }
}
}
97 changes: 82 additions & 15 deletions src/Microsoft.Framework.Runtime/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using System.IO;
using System.Linq;
using System.Runtime.Versioning;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NuGet;

Expand Down Expand Up @@ -253,33 +255,67 @@ public static bool TryGetProject(string path, out Project project)
projectPath = Path.Combine(path, ProjectFileName);
}

var json = File.ReadAllText(projectPath);

// Assume the directory name is the project name if none was specified
var projectName = GetDirectoryName(path);
projectPath = Path.GetFullPath(projectPath);

project = GetProject(json, projectName, projectPath);
try
{
using (var stream = File.OpenRead(projectPath))
{
project = GetProject(stream, projectName, projectPath);
}
}
catch (JsonReaderException ex)
{
throw ProjectFormatException.Create(ex, projectPath);
}

return true;
}

public static Project GetProject(string json, string projectName, string projectPath)
{
var ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
return GetProject(ms, projectName, projectPath);
}

public static Project GetProject(Stream stream, string projectName, string projectPath)
{
var project = new Project();

var rawProject = JObject.Parse(json);
var reader = new JsonTextReader(new StreamReader(stream));
var rawProject = JObject.Load(reader);

// Metadata properties
var version = rawProject["version"];
var authors = rawProject["authors"];
var tags = rawProject["tags"];

project.Name = projectName;
project.Version = version == null ? new SemanticVersion("1.0.0") : new SemanticVersion(version.Value<string>());
project.ProjectFilePath = Path.GetFullPath(projectPath);

if (version == null)
{
project.Version = new SemanticVersion("1.0.0");
}
else
{
try
{
project.Version = new SemanticVersion(version.Value<string>());
}
catch (Exception ex)
{
var lineInfo = (IJsonLineInfo)version;

throw ProjectFormatException.Create(ex, version, project.ProjectFilePath);
}
}

project.Description = GetValue<string>(rawProject, "description");
project.Authors = authors == null ? new string[] { } : authors.ToObject<string[]>();
project.Dependencies = new List<LibraryDependency>();
project.ProjectFilePath = Path.GetFullPath(projectPath);
project.WebRoot = GetValue<string>(rawProject, "webroot");
project.EntryPoint = GetValue<string>(rawProject, "entryPoint");
project.ProjectUrl = GetValue<string>(rawProject, "projectUrl");
Expand Down Expand Up @@ -342,8 +378,10 @@ public static Project GetProject(string json, string projectName, string project
}
else
{
throw new InvalidDataException(string.Format(
"The value of a script in {0} can only be a string or an array of strings", ProjectFileName));
throw ProjectFormatException.Create(
string.Format("The value of a script in {0} can only be a string or an array of strings", ProjectFileName),
value,
project.ProjectFilePath);
}
}
}
Expand All @@ -357,6 +395,7 @@ public static Project GetProject(string json, string projectName, string project
project.BuildTargetFrameworksAndConfigurations(rawProject);

PopulateDependencies(
project.ProjectFilePath,
project.Dependencies,
rawProject,
"dependencies",
Expand Down Expand Up @@ -426,6 +465,7 @@ private static IEnumerable<string> GetSourcesSplit(string sourceDescription)
}

private static void PopulateDependencies(
string projectPath,
IList<LibraryDependency> results,
JObject settings,
string propertyName,
Expand All @@ -436,9 +476,13 @@ private static void PopulateDependencies(
{
foreach (var dependency in dependencies)
{
if (String.IsNullOrEmpty(dependency.Key))
if (string.IsNullOrEmpty(dependency.Key))
{
throw new InvalidDataException("Unable to resolve dependency ''.");

throw ProjectFormatException.Create(
"Unable to resolve dependency ''.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of a crappy error. Should it say like "empty dependency" or something?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or say that the dependency isn't specified? Or that dependency names can't be empty?

dependency.Value,
projectPath);
}

// Support
Expand All @@ -447,8 +491,11 @@ private static void PopulateDependencies(
// }

var dependencyValue = dependency.Value;
string dependencyVersionValue = null;
var dependencyTypeValue = LibraryDependencyType.Default;

string dependencyVersionValue = null;
JToken dependencyVersionToken = dependencyValue;

if (dependencyValue.Type == JTokenType.String)
{
dependencyVersionValue = dependencyValue.Value<string>();
Expand All @@ -457,7 +504,7 @@ private static void PopulateDependencies(
{
if (dependencyValue.Type == JTokenType.Object)
{
var dependencyVersionToken = dependencyValue["version"];
dependencyVersionToken = dependencyValue["version"];
if (dependencyVersionToken != null && dependencyVersionToken.Type == JTokenType.String)
{
dependencyVersionValue = dependencyVersionToken.Value<string>();
Expand All @@ -472,9 +519,20 @@ private static void PopulateDependencies(
}

SemanticVersion dependencyVersion = null;
if (!String.IsNullOrEmpty(dependencyVersionValue))

if (!string.IsNullOrEmpty(dependencyVersionValue))
{
dependencyVersion = SemanticVersion.Parse(dependencyVersionValue);
try
{
dependencyVersion = SemanticVersion.Parse(dependencyVersionValue);
}
catch (Exception ex)
{
throw ProjectFormatException.Create(
ex,
dependencyVersionToken,
projectPath);
}
}

results.Add(new LibraryDependency(
Expand Down Expand Up @@ -601,7 +659,14 @@ private void BuildTargetFrameworksAndConfigurations(JObject rawProject)
{
foreach (var framework in frameworks)
{
BuildTargetFrameworkNode(framework);
try
{
BuildTargetFrameworkNode(framework);
}
catch (Exception ex)
{
throw ProjectFormatException.Create(ex, framework.Value, ProjectFilePath);
}
}
}
}
Expand Down Expand Up @@ -642,13 +707,15 @@ private bool BuildTargetFrameworkNode(KeyValuePair<string, JToken> targetFramewo
var properties = targetFramework.Value.Value<JObject>();

PopulateDependencies(
ProjectFilePath,
targetFrameworkInformation.Dependencies,
properties,
"dependencies",
isGacOrFrameworkReference: false);

var frameworkAssemblies = new List<LibraryDependency>();
PopulateDependencies(
ProjectFilePath,
frameworkAssemblies,
properties,
"frameworkAssemblies",
Expand Down
64 changes: 64 additions & 0 deletions src/Microsoft.Framework.Runtime/ProjectFormatException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.Framework.Runtime
{
public sealed class ProjectFormatException : Exception
{
public ProjectFormatException(string message) :
base(message)
{
}

public ProjectFormatException(string message, Exception innerException) :
base(message, innerException)
{

}

public string Path { get; private set; }
public int Line { get; private set; }
public int Column { get; private set; }

private ProjectFormatException WithLineInfo(IJsonLineInfo lineInfo)
{
Line = lineInfo.LineNumber;
Column = lineInfo.LinePosition;

return this;
}

public static ProjectFormatException Create(Exception exception, JToken value, string path)
{
var lineInfo = (IJsonLineInfo)value;

return new ProjectFormatException(exception.Message, exception)
{
Path = path
}
.WithLineInfo(lineInfo);
}

public static ProjectFormatException Create(string message, JToken value, string path)
{
var lineInfo = (IJsonLineInfo)value;

return new ProjectFormatException(message)
{
Path = path
}
.WithLineInfo(lineInfo);
}

internal static ProjectFormatException Create(JsonReaderException exception, string path)
{
return new ProjectFormatException(exception.Message, exception)
{
Path = path,
Column = exception.LineNumber,
Line = exception.LinePosition
};
}
}
}