Skip to content

HPF PR: dev <- Azure:dev #367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 1, 2016
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
120 changes: 120 additions & 0 deletions tools/StaticAnalysis/AnalysisLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace StaticAnalysis
{
/// <summary>
/// Abstract class to implement the report logging structure
/// </summary>
public abstract class AnalysisLogger
{
string _baseDirectory;

/// <summary>
/// Create an analysis logger that will write reports to the given directory
/// </summary>
/// <param name="baseDirectory"></param>
public AnalysisLogger(string baseDirectory)
{
_baseDirectory = baseDirectory;
}

IList<ReportLogger> _loggers = new List<ReportLogger>();
protected virtual IList<ReportLogger> Loggers { get { return _loggers; } }

/// <summary>
/// Write an error report.
/// </summary>
/// <param name="error">The message to write</param>
public abstract void WriteError(string error);

public virtual void WriteError(string format, params object[] args)
{
WriteError(string.Format(format, args));
}

/// <summary>
/// Write an informational message.
/// </summary>
/// <param name="message">The message to write</param>
public abstract void WriteMessage(string message);

public virtual void WriteMessage(string format, params object[] args)
{
WriteMessage(string.Format(format, args));
}

/// <summary>
/// Write a warning.
/// </summary>
/// <param name="message">The warning text</param>
public abstract void WriteWarning(string message);

public virtual void WriteWarning(string format, params object[] args)
{
WriteWarning(string.Format(format, args));
}

/// <summary>
/// Write a report file to the given file, using the given file contents.
/// </summary>
/// <param name="name">The path to the file</param>
/// <param name="contents">The contents of the report</param>
public abstract void WriteReport(string name, string contents);

/// <summary>
/// Create a logger for a particular report
/// </summary>
/// <typeparam name="T">The type of records written to the log</typeparam>
/// <param name="fileName">The filename (without file path) where the report will be written</param>
/// <returns>The given logger. Analyzer may write records to this logger and they will be written to
/// the report file.</returns>
public virtual ReportLogger<T> CreateLogger<T>(string fileName) where T : IReportRecord, new()
{
if (string.IsNullOrWhiteSpace(fileName))
{
throw new ArgumentNullException("fileName");
}

var filePath = Path.Combine(_baseDirectory, fileName);
var logger = new ReportLogger<T>(filePath, this);
Loggers.Add(logger);
return logger;
}

/// <summary>
/// Write out the report files for each of the added report loggers.
/// </summary>
public void WriteReports()
{
foreach (var logger in Loggers.Where(l => l.Records.Any()))
{
StringBuilder reportText = new StringBuilder();
reportText.AppendLine(logger.Records.First().PrintHeaders());
foreach (var reportRecord in logger.Records)
{
reportText.AppendLine(reportRecord.FormatRecord());
}

WriteReport(logger.FileName, reportText.ToString());
}
}
}
}
51 changes: 51 additions & 0 deletions tools/StaticAnalysis/ConsoleLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

using System;
using System.IO;

namespace StaticAnalysis
{
/// <summary>
/// Simple class for logging errors and warnings to the console and writing reports to the file system.
/// </summary>
public class ConsoleLogger : AnalysisLogger
{

public ConsoleLogger(string baseDirectory)
: base(baseDirectory)
{
}

public override void WriteError(string error)
{
Console.WriteLine("### ERROR {0}", error);
}

public override void WriteMessage(string message)
{
Console.WriteLine(message);
}

public override void WriteWarning(string message)
{
Console.WriteLine("Warning: {0}", message);
}

public override void WriteReport(string name, string records)
{
File.WriteAllText(name, records);
}
}
}
88 changes: 88 additions & 0 deletions tools/StaticAnalysis/Decorator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

using System;

namespace StaticAnalysis
{
/// <summary>
/// Abstract class to implement the Decorator pattern
/// </summary>
/// <typeparam name="T"></typeparam>
public class Decorator<T>
{
Action<T> _action;
string _name;

protected Decorator(Action<T> action, string name)
{
_action = action;
_name = name;
Inner = null;
}

public static Decorator<T> Create()
{
return new Decorator<T>(r => { }, "default");
}

public void Apply(T record)
{
_action(record);
if (Inner != null)
{
Inner.Apply(record);
}
}

public void AddDecorator(Action<T> action, string name)
{
if (action == null)
{
throw new ArgumentNullException("action");
}

if (name == null)
{
throw new ArgumentNullException("name");
}

if (Inner == null)
{
Inner = new Decorator<T>(action, name);
}
else
{
Inner.AddDecorator(action, name);
}
}

public void Remove(string name)
{
if (Inner != null)
{
if (string.Equals(Inner._name, name))
{
Inner = Inner.Inner;
}
else
{
Inner.Remove(name);
}
}
}

protected Decorator<T> Inner { get; set; }
}
}
101 changes: 101 additions & 0 deletions tools/StaticAnalysis/DependencyAnalyzer/AssemblyLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

using System;
using System.Reflection;

namespace StaticAnalysis.DependencyAnalyzer
{
/// <summary>
/// A class using .Net Remoting to load assemblies and retrieve information in a separate app domain
/// </summary>
public class AssemblyLoader : MarshalByRefObject
{
/// <summary>
/// Load the assembly in the reflection context by name. Will succeed if the referenced assembly name can
/// be found using default assembly loading rules (i.e. it is in the current directory or the GAC)
/// </summary>
/// <param name="assemblyName">The full name of the assembly</param>
/// <returns>Information on the given assembly, if it was loaded successfully, or null if there is an
/// assembly loading issue. </returns>
public AssemblyMetadata GetReflectedAssemblyInfo(string assemblyName)
{
if (string.IsNullOrWhiteSpace(assemblyName))
{
throw new ArgumentException("assemblyName");
}

AssemblyMetadata result = null;
try
{
result = new AssemblyMetadata(Assembly.ReflectionOnlyLoad(assemblyName));
}
catch
{
}

return result;
}

/// <summary>
/// Load the assembly found at the given path in the reflection context and return assembly metadata
/// </summary>
/// <param name="assemblyPath">The full path to the assembly file.</param>
/// <returns>Assembly metadata if the assembly is loaded successfully, or null if there are load errors.</returns>
public AssemblyMetadata GetReflectedAssemblyFromFile(string assemblyPath)
{
if (string.IsNullOrWhiteSpace(assemblyPath))
{
throw new ArgumentException("assemblyPath");
}

AssemblyMetadata result = null;
try
{
return new AssemblyMetadata(Assembly.ReflectionOnlyLoadFrom(assemblyPath));
}
catch
{
}

return result;
}

/// <summary>
/// Create a new AppDomain and create a remote instance of AssemblyLoader we can use there
/// </summary>
/// <param name="directoryPath">directory containing assemblies</param>
/// <param name="testDomain">A new AppDomain, where assemblies can be loaded</param>
/// <returns>A proxy to the AssemblyLoader running in the newly created app domain</returns>
public static AssemblyLoader Create(string directoryPath, out AppDomain testDomain)
{
if (string.IsNullOrWhiteSpace(directoryPath))
{
throw new ArgumentException("directoryPath");
}

var setup = new AppDomainSetup();
setup.ApplicationBase = directoryPath;
setup.ApplicationName = "TestDomain";
setup.ApplicationTrust = AppDomain.CurrentDomain.ApplicationTrust;
setup.DisallowApplicationBaseProbing = false;
setup.DisallowCodeDownload = false;
setup.DisallowBindingRedirects = false;
setup.DisallowPublisherPolicy = false;
testDomain = AppDomain.CreateDomain("TestDomain", null, setup);
return testDomain.CreateInstanceFromAndUnwrap(typeof(AssemblyLoader).Assembly.Location,
typeof(AssemblyLoader).FullName) as AssemblyLoader;
}
}
}
Loading