Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
* Redesign CompilationResult so that it does not throw when CompiledT…
Browse files Browse the repository at this point in the history
…ype is

accessed.
* Update to use ICompilationException interface from
  Microsoft.Framework.Runtime
* Update to use RoslynCompilationException

Fixes #955
  • Loading branch information
pranavkm committed Feb 23, 2015
1 parent 6b3119e commit fc38efe
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 205 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

using System;
using System.Collections.Generic;
using Microsoft.AspNet.Diagnostics;
using System.Linq;
using Microsoft.Framework.Runtime;

namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// An exception thrown when accessing the result of a failed compilation.
/// An <see cref="Exception"/> thrown when accessing the result of a failed compilation.
/// </summary>
public class CompilationFailedException : Exception, ICompilationException
{
Expand All @@ -19,12 +20,19 @@ public class CompilationFailedException : Exception, ICompilationException
/// details of the compilation failure.</param>
public CompilationFailedException(
[NotNull] ICompilationFailure compilationFailure)
: base(Resources.FormatCompilationFailed(compilationFailure.SourceFilePath))
: base(FormatMessage(compilationFailure))
{
CompilationFailures = new[] { compilationFailure };
}

/// <inheritdoc />
public IEnumerable<ICompilationFailure> CompilationFailures { get; }

private static string FormatMessage(ICompilationFailure compilationFailure)
{
return Resources.FormatCompilationFailed(compilationFailure.SourceFilePath) +
Environment.NewLine +
string.Join(Environment.NewLine, compilationFailure.Messages.Select(message => message.Message));
}
}
}
45 changes: 17 additions & 28 deletions src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationFailure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,40 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using Microsoft.AspNet.Diagnostics;
using Microsoft.Framework.Runtime;

namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// Default implementation of <see cref="ICompilationFailure"/>.
/// <see cref="ICompilationFailure"/> for Razor parse failures.
/// </summary>
public class CompilationFailure : ICompilationFailure
public class RazorCompilationFailure : ICompilationFailure
{
/// <summary>Initializes a new instance of <see cref="CompilationFailure"/>.</summary>
/// <param name="filePath">The path of the Razor source file that was compiled.</param>
/// <param name="fileContent">The contents of the Razor source file.</param>
/// <param name="compiledContent">The generated C# content that was compiled.</param>
/// <summary>Initializes a new instance of <see cref="RazorCompilationFailure"/>.</summary>
/// <param name="sourceFilePath">The path of the Razor source file that was compiled.</param>
/// <param name="sourceFileContent">The contents of the Razor source file.</param>
/// <param name="messages">A sequence of <see cref="ICompilationMessage"/> encountered
/// during compilation.</param>
public CompilationFailure(
[NotNull] string filePath,
[NotNull] string fileContent,
[NotNull] string compiledContent,
[NotNull] IEnumerable<ICompilationMessage> messages)
public RazorCompilationFailure(
[NotNull] string sourceFilePath,
[NotNull] string sourceFileContent,
[NotNull] IEnumerable<RazorCompilationMessage> messages)
{
SourceFilePath = filePath;
SourceFileContent = fileContent;
SourceFilePath = sourceFilePath;
SourceFileContent = sourceFileContent;
Messages = messages;
CompiledContent = compiledContent;
}

/// <summary>
/// Gets the path of the Razor source file that produced the compilation failure.
/// </summary>
/// <inheritdoc />
public string SourceFilePath { get; }

/// <summary>
/// Gets the content of the Razor source file.
/// </summary>
/// <inheritdoc />
public string SourceFileContent { get; }

/// <summary>
/// Gets the generated C# content that was compiled.
/// </summary>
public string CompiledContent { get; }
/// <inheritdoc />
public string CompiledContent { get; } = null;

/// <summary>
/// Gets a sequence of <see cref="ICompilationMessage"/> instances encountered during compilation.
/// </summary>
/// <inheritdoc />
public IEnumerable<ICompilationMessage> Messages { get; }
}
}
48 changes: 31 additions & 17 deletions src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationMessage.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.AspNet.Diagnostics;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.Framework.Runtime;

namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// Represents a message encountered during compilation.
/// <see cref="ICompilationMessage"/> for a <see cref="RazorError"/> encountered during parsing.
/// </summary>
public class CompilationMessage : ICompilationMessage
public class RazorCompilationMessage : ICompilationMessage
{
/// <summary>
/// Initializes a <see cref="CompilationMessage"/> with the specified message.
/// Initializes a <see cref="RazorCompilationMessage"/> with the specified message.
/// </summary>
/// <param name="message">A message <see cref="string"/> produced from compilation.</param>
public CompilationMessage(string message,
int startColumn,
int startLine,
int endColumn,
int endLine)
/// <param name="razorError">A <see cref="RazorError"/>.</param>
/// <param name="sourceFilePath">The path of the Razor source file that was parsed.</param>
public RazorCompilationMessage(
[NotNull] RazorError razorError,
string sourceFilePath)
{
Message = message;
StartColumn = startColumn;
StartLine = startLine;
EndColumn = endColumn;
EndLine = endLine;
SourceFilePath = sourceFilePath;
Message = razorError.Message;
FormattedMessage = razorError.Message;

var location = razorError.Location;
StartColumn = location.CharacterIndex;
StartLine = location.LineIndex;
EndColumn = location.CharacterIndex + razorError.Length;
EndLine = location.LineIndex;
}

/// <summary>
Expand All @@ -44,10 +48,20 @@ public class CompilationMessage : ICompilationMessage
/// <inheritdoc />
public int EndLine { get; }

/// <inheritdoc />
public string SourceFilePath { get; }

/// <inheritdoc />
public string FormattedMessage { get; }

/// <inheritdoc />
// All Razor diagnostics are errors
public CompilationMessageSeverity Severity { get; } = CompilationMessageSeverity.Error;

/// <summary>
/// Returns a <see cref="string"/> representation of this instance of <see cref="CompilationMessage"/>.
/// Returns a <see cref="string"/> representation of this instance of <see cref="RazorCompilationMessage"/>.
/// </summary>
/// <returns>A <see cref="string"/> representing this <see cref="CompilationMessage"/> instance.</returns>
/// <returns>A <see cref="string"/> representing this <see cref="RazorCompilationMessage"/> instance.</returns>
/// <remarks>Returns same value as <see cref="Message"/>.</remarks>
public override string ToString()
{
Expand Down
103 changes: 26 additions & 77 deletions src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +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 Microsoft.AspNet.FileProviders;
using Microsoft.Framework.Runtime;

namespace Microsoft.AspNet.Mvc.Razor
{
Expand All @@ -13,119 +11,70 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary>
public class CompilationResult
{
private Type _type;

/// <summary>
// <summary>
/// Creates a new instance of <see cref="CompilationResult"/>.
/// </summary>
protected CompilationResult()
{
}

/// <summary>
/// Gets the path of the Razor file that was compiled.
/// Gets (or sets in derived types) the type produced as a result of compilation.
/// </summary>
public string FilePath
{
get
{
if (File != null)
{
return File.PhysicalPath;
}
return null;
}
}
/// <remarks>This property is <c>null</c> when compilation fails.</remarks>
public Type CompiledType { get; protected set; }

/// <summary>
/// Gets a sequence of <see cref="CompilationMessage"/> instances encountered during compilation.
/// Gets (or sets in derived types) the generated C# content that was compiled.
/// </summary>
public IEnumerable<CompilationMessage> Messages { get; private set; }
public string CompiledContent { get; protected set; }

/// <summary>
/// Gets (or sets in derived types) the generated C# content that was compiled.
/// Gets the <see cref="ICompilationFailure"/> produced from parsing or compiling the Razor file.
/// </summary>
public string CompiledContent { get; protected set; }
/// <remarks>This property is <c>null</c> when compilation succeeds.</remarks>
public ICompilationFailure CompilationFailure { get; private set; }

/// <summary>
/// Gets (or sets in derived types) the type produced as a result of compilation.
/// Gets the <see cref="CompilationResult"/>.
/// </summary>
/// <exception cref="CompilationFailedException">An error occured during compilation.</exception>
public Type CompiledType
/// <returns>The current <see cref="CompilationResult"/> instance.</returns>
/// <exception cref="CompilationFailedException">Thrown if compilation failed.</exception>
public CompilationResult EnsureSuccessful()
{
get
if (CompilationFailure != null)
{
if (_type == null)
{
throw CreateCompilationFailedException();
}

return _type;
throw new CompilationFailedException(CompilationFailure);
}
protected set
{
_type = value;
}
}

private IFileInfo File { get; set; }
return this;
}

/// <summary>
/// Creates a <see cref="CompilationResult"/> that represents a failure in compilation.
/// Creates a <see cref="CompilationResult"/> for a failed compilation.
/// </summary>
/// <param name="fileInfo">The <see cref="IFileInfo"/> for the Razor file that was compiled.</param>
/// <param name="compilationContent">The generated C# content to be compiled.</param>
/// <param name="messages">The sequence of failure messages encountered during compilation.</param>
/// <returns>A CompilationResult instance representing a failure.</returns>
public static CompilationResult Failed([NotNull] IFileInfo file,
[NotNull] string compilationContent,
[NotNull] IEnumerable<CompilationMessage> messages)
/// <param name="compilationFailure">The <see cref="ICompilationFailure"/> produced from parsing or
/// compiling the Razor file.</param>
/// <returns>A <see cref="CompilationResult"/> instance representing a failure.</returns>
public static CompilationResult Failed([NotNull] ICompilationFailure compilationFailure)
{
return new CompilationResult
{
File = file,
CompiledContent = compilationContent,
Messages = messages,
CompilationFailure = compilationFailure
};
}

/// <summary>
/// Creates a <see cref="CompilationResult"/> that represents a success in compilation.
/// Creates a <see cref="CompilationResult"/> for a successful compilation.
/// </summary>
/// <param name="type">The compiled type.</param>
/// <returns>A CompilationResult instance representing a success.</returns>
/// <returns>A <see cref="CompilationResult"/> instance representing a success.</returns>
public static CompilationResult Successful([NotNull] Type type)
{
return new CompilationResult
{
CompiledType = type
};
}

private CompilationFailedException CreateCompilationFailedException()
{
var fileContent = ReadContent(File);
var compilationFailure = new CompilationFailure(FilePath, fileContent, CompiledContent, Messages);
return new CompilationFailedException(compilationFailure);
}

private static string ReadContent(IFileInfo file)
{
try
{
using (var stream = file.CreateReadStream())
{
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
catch (Exception)
{
// Don't throw if reading the file fails.
return string.Empty;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public class CompilerCache : ICompilerCache
string normalizedPath,
Func<RelativeFileInfo, CompilationResult> compile)
{
var compilationResult = compile(file);
var compilationResult = compile(file).EnsureSuccessful();

// Concurrent addition to MemoryCache with the same key result in safe race.
var cacheEntry = _cache.Set(normalizedPath,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.AspNet.FileProviders;

namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
Expand All @@ -13,11 +11,11 @@ public interface ICompilationService
/// <summary>
/// Compiles content and returns the result of compilation.
/// </summary>
/// <param name="fileInfo">The <see cref="IFileInfo"/> for the Razor file that was compiled.</param>
/// <param name="fileInfo">The <see cref="RelativeFileInfo"/> for the Razor file that was compiled.</param>
/// <param name="compilationContent">The generated C# content to be compiled.</param>
/// <returns>
/// A <see cref="CompilationResult"/> representing the result of compilation.
/// </returns>
CompilationResult Compile(IFileInfo fileInfo, string compilationContent);
CompilationResult Compile(RelativeFileInfo fileInfo, string compilationContent);
}
}
Loading

0 comments on commit fc38efe

Please sign in to comment.