Browse Source

Implemented FxCop task.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1229 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
4415e32c07
  1. 5
      src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin
  2. 1
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs
  3. 5
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  4. 5
      src/AddIns/BackendBindings/ILAsmBinding/Project/ILAsmBinding.addin
  5. 5
      src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin
  6. 6
      src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin
  7. 2
      src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs
  8. 266
      src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs
  9. 15
      src/Libraries/ICSharpCode.Build.Tasks/Project/ICSharpCode.Build.Tasks.csproj
  10. 38
      src/Libraries/ICSharpCode.Build.Tasks/Project/SharpDevelop.CodeAnalysis.targets
  11. 32
      src/Main/Base/Project/Src/Project/MSBuildEngine.cs

5
src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin

@ -30,6 +30,11 @@ @@ -30,6 +30,11 @@
extensions = "*.boo"/>
</Path>
<Path name = "/SharpDevelop/MSBuildEngine/CompileTaskNames">
<!-- Makes SharpDevelop show the text 'Compiling ProjectName...' when the task is started -->
<String id="booc" text = "booc"/>
</Path>
<Path name = "/AddIns/FileTypeRegisterer/FileTypes">
<FiletypeAssociation
id = "booproj"

1
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs

@ -26,7 +26,6 @@ namespace Grunwald.BooBinding @@ -26,7 +26,6 @@ namespace Grunwald.BooBinding
LanguageProperties = BooLanguageProperties.Instance;
if (!initialized) {
initialized = true;
MSBuildEngine.CompileTaskNames.Add("booc");
MSBuildEngine.MSBuildProperties.Add("BooBinPath", BooBinPath);
}
}

5
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin

@ -25,6 +25,11 @@ @@ -25,6 +25,11 @@
</Condition>
</Path>
<Path name = "/SharpDevelop/MSBuildEngine/CompileTaskNames">
<!-- Makes SharpDevelop show the text 'Compiling ProjectName...' when the task is started -->
<String id="csc" text = "csc"/>
</Path>
<Path name = "/SharpDevelop/Workbench/FileFilter">
<FileFilter id = "C#"
insertbefore="AllFiles"

5
src/AddIns/BackendBindings/ILAsmBinding/Project/ILAsmBinding.addin

@ -19,6 +19,11 @@ @@ -19,6 +19,11 @@
extensions = "*.il"/>
</Path>
<Path name = "/SharpDevelop/MSBuildEngine/CompileTaskNames">
<!-- Makes SharpDevelop show the text 'Compiling ProjectName...' when the task is started -->
<String id="ilasm" text = "ilasm"/>
</Path>
<Path name = "/SharpDevelop/BackendBindings/Templates">
<Directory id = "ILAsm" path = "./Templates" />
</Path>

5
src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin

@ -24,6 +24,11 @@ @@ -24,6 +24,11 @@
extensions = "*.vb"/>
</Path>
<Path name = "/SharpDevelop/MSBuildEngine/CompileTaskNames">
<!-- Makes SharpDevelop show the text 'Compiling ProjectName...' when the task is started -->
<String id="vbc" text = "vbc"/>
</Path>
<Path name = "/Workspace/Parser">
<Parser id = "VBNet"
supportedextensions = ".vb"

6
src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin

@ -11,7 +11,11 @@ @@ -11,7 +11,11 @@
<Import assembly = "CodeAnalysis.dll"/>
</Runtime>
<Path path = "/SharpDevelop/BackendBindings/ProjectOptions/C#">
<Path name = "/SharpDevelop/MSBuildEngine/AdditionalTargetFiles">
<String id="CodeAnalysis" text = "$(SharpDevelopBinPath)/SharpDevelop.CodeAnalysis.targets"/>
</Path>
<Path name = "/SharpDevelop/BackendBindings/ProjectOptions/C#">
<DialogPanel id = "CodeAnalysis"
label = "${res:ICSharpCode.CodeAnalysis}"
insertafter = "Publish"

2
src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs

@ -50,6 +50,7 @@ namespace ICSharpCode.CodeAnalysis @@ -50,6 +50,7 @@ namespace ICSharpCode.CodeAnalysis
if (fxCopPath.Length > 0 && File.Exists(Path.Combine(fxCopPath, "FxCopCommon.dll"))) {
return fxCopPath;
}
// Code duplication: FxCop.cs in ICSharpCode.Build.Tasks
fxCopPath = FromRegistry(Registry.CurrentUser.OpenSubKey(@"Software\Classes\FxCopProject\Shell\Open\Command"));
if (fxCopPath.Length > 0 && File.Exists(Path.Combine(fxCopPath, "FxCopCommon.dll"))) {
return fxCopPath;
@ -63,6 +64,7 @@ namespace ICSharpCode.CodeAnalysis @@ -63,6 +64,7 @@ namespace ICSharpCode.CodeAnalysis
static string FromRegistry(RegistryKey key)
{
// Code duplication: FxCop.cs in ICSharpCode.Build.Tasks
if (key == null) return string.Empty;
using (key) {
string cmd = key.GetValue("").ToString();

266
src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs

@ -0,0 +1,266 @@ @@ -0,0 +1,266 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.IO;
using System.Globalization;
using System.Text;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Tasks;
using Microsoft.Build.Utilities;
using Microsoft.Win32;
namespace ICSharpCode.Build.Tasks
{
public sealed class FxCop : ToolTask
{
string logFile;
string realLogFile;
string inputAssembly;
string rules;
string[] ruleAssemblies;
string[] referencePaths;
#region Properties
public string LogFile {
get {
return logFile;
}
set {
logFile = value;
}
}
public string InputAssembly {
get {
return inputAssembly;
}
set {
inputAssembly = value;
}
}
public string Rules {
get {
return rules;
}
set {
rules = value;
}
}
public string[] RuleAssemblies {
get {
return ruleAssemblies;
}
set {
ruleAssemblies = value;
}
}
public string[] ReferencePaths {
get {
return referencePaths;
}
set {
referencePaths = value;
}
}
#endregion
protected override string ToolName {
get {
return "FxCopCmd.exe";
}
}
public override bool Execute()
{
if (string.IsNullOrEmpty(ToolPath) || !File.Exists(GenerateFullPathToTool())) {
string path = FindFxCopPath();
Log.LogMessage(MessageImportance.High, "Running Code Analysis...");
if (path != null) {
ToolPath = path;
} else {
Log.LogError("SharpDevelop cannot find FxCop. Please specify the MSBuild property 'FxCopDir'.");
return false;
}
}
realLogFile = logFile ?? Path.GetTempFileName();
try {
bool result = base.Execute();
if (File.Exists(realLogFile)) {
try {
Console.WriteLine(File.ReadAllText(realLogFile));
XmlDocument doc = new XmlDocument();
doc.Load(realLogFile);
foreach (XmlNode node in doc.DocumentElement.SelectNodes(".//Exception")) {
XmlElement el = node as XmlElement;
if (el == null) continue;
result = false;
string checkId = el.GetAttribute("CheckId");
string keyword = el.GetAttribute("Keyword");
string message = el["ExceptionMessage"].InnerText;
if (checkId.Length > 0) {
Log.LogError(null, null, keyword, "", 0, 0, 0, 0,
"{0} : {2} ({1}): {3}", keyword, el.GetAttribute("Category"), checkId, el.GetAttribute("Target"), message);
} else {
Log.LogError(keyword + " : " + message);
}
}
foreach (XmlNode node in doc.DocumentElement.SelectNodes(".//Message")) {
XmlElement el = node as XmlElement;
if (el == null) continue;
result &= LogMessage(el);
}
} catch (XmlException e) {
Log.LogError("Cannot read FxCop log file: " + e.Message);
}
}
return result;
} finally {
if (logFile == null) {
File.Delete(realLogFile);
}
}
}
/// <summary>
/// Logs a message.
/// </summary>
/// <returns>True for warning, false for error.</returns>
bool LogMessage(XmlElement message)
{
bool isWarning = true;
string checkId = message.GetAttribute("CheckId");
string category = message.GetAttribute("Category");
foreach (XmlNode node in message.SelectNodes(".//Issue")) {
XmlElement issueEl = node as XmlElement;
if (issueEl == null) continue;
if ("true".Equals(message.GetAttribute("BreaksBuild"), StringComparison.OrdinalIgnoreCase)) {
isWarning = false;
}
string issueText = issueEl.InnerText;
string issuePath = issueEl.GetAttribute("Path");
string issueFile = issueEl.GetAttribute("File");
string issueLine = issueEl.GetAttribute("Line");
int issueLineNumber = 0;
string issueFullFile = null;
if (issuePath.Length > 0 && issueLine.Length > 0 && issueFile.Length > 0) {
issueFullFile = Path.Combine(issuePath, issueFile);
issueLineNumber = int.Parse(issueLine, CultureInfo.InvariantCulture);
} else {
// Try to find additional information about this type
string memberName = null;
XmlNode parent = message.ParentNode;
while (parent != null) {
if (parent.Name == "Member" || parent.Name == "Type" || parent.Name == "Namespace") {
if (memberName == null)
memberName = ((XmlElement)parent).GetAttribute("Name");
else
memberName = ((XmlElement)parent).GetAttribute("Name") + "." + memberName;
}
parent = parent.ParentNode;
}
if (memberName != null) {
issueFullFile = "positionof#" + memberName;
}
}
issueText = checkId + " : " + category + " : " + issueText;
if (isWarning) {
Log.LogWarning(null, null, checkId, issueFullFile, issueLineNumber, 0, 0, 0, issueText);
} else {
Log.LogError(null, null, checkId, issueFullFile, issueLineNumber, 0, 0, 0, issueText);
}
}
return isWarning;
}
string FindFxCopPath()
{
// Code duplication: FxCopWrapper.cs in CodeAnalysis addin
string fxCopPath = FromRegistry(Registry.CurrentUser.OpenSubKey(@"Software\Classes\FxCopProject\Shell\Open\Command"));
if (fxCopPath.Length > 0 && File.Exists(Path.Combine(fxCopPath, ToolName))) {
return fxCopPath;
}
fxCopPath = FromRegistry(Registry.ClassesRoot.OpenSubKey(@"FxCopProject\Shell\Open\Command"));
if (fxCopPath.Length > 0 && File.Exists(Path.Combine(fxCopPath, ToolName))) {
return fxCopPath;
}
return null;
}
string FromRegistry(RegistryKey key)
{
// Code duplication: FxCopWrapper.cs in CodeAnalysis addin
if (key == null) return string.Empty;
using (key) {
string cmd = key.GetValue("").ToString();
int pos;
if (cmd.StartsWith("\""))
pos = cmd.IndexOf('"', 1);
else
pos = cmd.IndexOf(' ');
try {
if (cmd.StartsWith("\""))
return Path.GetDirectoryName(cmd.Substring(1, pos - 1));
else
return Path.GetDirectoryName(cmd.Substring(0, pos));
} catch (ArgumentException ex) {
Log.LogWarning(cmd);
Log.LogWarningFromException(ex);
return string.Empty;
}
}
}
protected override string GenerateFullPathToTool()
{
return Path.Combine(ToolPath.Trim('"'), ToolName);
}
static void AppendSwitch(StringBuilder b, string @switch, string val)
{
if (!string.IsNullOrEmpty(val)) {
b.Append(" /");
b.Append(@switch);
b.Append(':');
if (val[0] == '"') {
b.Append(val);
} else {
b.Append('"');
b.Append(val);
b.Append('"');
}
}
}
protected override string GenerateResponseFileCommands()
{
StringBuilder b = new StringBuilder();
AppendSwitch(b, "o", realLogFile);
AppendSwitch(b, "f", inputAssembly);
if (referencePaths != null) {
foreach (string path in referencePaths) {
AppendSwitch(b, "d", Path.GetDirectoryName(path));
}
}
if (ruleAssemblies != null) {
foreach (string asm in ruleAssemblies) {
AppendSwitch(b, "r", asm);
}
}
AppendSwitch(b, "rid", rules);
return b.ToString();
}
}
}

15
src/Libraries/ICSharpCode.Build.Tasks/Project/ICSharpCode.Build.Tasks.csproj

@ -9,7 +9,6 @@ @@ -9,7 +9,6 @@
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<NoStdLib>False</NoStdLib>
<DebugType>None</DebugType>
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>92405760</BaseAddress>
@ -17,7 +16,6 @@ @@ -17,7 +16,6 @@
<FileAlignment>4096</FileAlignment>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>..\..\..\..\bin\</OutputPath>
@ -29,6 +27,14 @@ @@ -29,6 +27,14 @@
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>Full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>None</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
@ -78,11 +84,16 @@ @@ -78,11 +84,16 @@
</None>
<Compile Include="MonoBasicCompilerResultsParser.cs" />
<Compile Include="MonoCSharpCompilerTask.cs" />
<Compile Include="FxCop.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="SharpDevelop.Build.CSharp.targets">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="SharpDevelop.CodeAnalysis.targets">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Folder Include="Mono" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

38
src/Libraries/ICSharpCode.Build.Tasks/Project/SharpDevelop.CodeAnalysis.targets

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
<?xml version="1.0"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="ICSharpCode.Build.Tasks.FxCop"
AssemblyFile="$(SharpDevelopBinPath)\ICSharpCode.Build.Tasks.dll"/>
<PropertyGroup>
<!-- Define compilation symbols -->
<DefineConstants Condition="'$(RunCodeAnalysis)'=='true' and '$(Language)'!='C#' ">$(DefineConstants);CODE_ANALYSIS</DefineConstants>
<FinalDefineConstants Condition="'$(RunCodeAnalysis)'=='true' and '$(Language)'=='VB' ">$(FinalDefineConstants),CODE_ANALYSIS=1</FinalDefineConstants>
<!-- prepare task properties -->
<SharpDevelopFxCopAssembly Condition="'$(CodeAnalysisInputAssembly)'!=''">$(CodeAnalysisInputAssembly)</SharpDevelopFxCopAssembly>
<SharpDevelopFxCopAssembly Condition="'$(CodeAnalysisInputAssembly)'==''">$(OutDir)$(TargetName)$(TargetExt)</SharpDevelopFxCopAssembly>
<SharpDevelopFxCopLogFile Condition="'$(CodeAnalysisLogFile)'!=''">$(CodeAnalysisLogFile)</SharpDevelopFxCopLogFile>
<SharpDevelopFxCopLogFile Condition="'$(CodeAnalysisLogFile)'==''">$(SharpDevelopFxCopAssembly).CodeAnalysisLog.xml</SharpDevelopFxCopLogFile>
<!-- register custom target -->
<PrepareForRunDependsOn>$(PrepareForRunDependsOn);SharpDevelopFxCopRun</PrepareForRunDependsOn>
</PropertyGroup>
<!-- run SharpDevelop FxCop. Disabled if the Microsoft CodeAnalysis extension is installed -->
<Target Name="SharpDevelopFxCopRun"
Condition="'$(RunCodeAnalysis)'=='true' and '$(CodeAnalysisInputAssemblyForTask)'==''"
Inputs="$(SharpDevelopFxCopAssembly)"
Outputs="$(SharpDevelopFxCopLogFile)"
DependsOnTargets="Compile">
<CreateItem Include = "$(SharpDevelopFxCopLogFile)">
<Output ItemName = "SharpDevelopFxCopLogFile" TaskParameter="Include"/>
</CreateItem>
<FxCop ToolPath = "$(FxCopDir)"
InputAssembly = "$(SharpDevelopFxCopAssembly)"
Rules = "$(CodeAnalysisRules)"
RuleAssemblies = "$(CodeAnalysisRuleAssemblies)"
LogFile = "$(SharpDevelopFxCopLogFile)"
ReferencePaths = "@(ReferencePath)"/>
</Target>
</Project>

32
src/Main/Base/Project/Src/Project/MSBuildEngine.cs

@ -39,9 +39,18 @@ namespace ICSharpCode.SharpDevelop.Project @@ -39,9 +39,18 @@ namespace ICSharpCode.SharpDevelop.Project
/// </summary>
public static readonly SortedList<string, string> MSBuildProperties;
/// <summary>
/// Gets a list of additional target files that are automatically loaded into all projects.
/// </summary>
public static readonly List<string> AdditionalTargetFiles;
static MSBuildEngine()
{
CompileTaskNames = new List<string>(new string[] {"csc", "vbc", "ilasm"});
CompileTaskNames = AddInTree.BuildItems<string>("/SharpDevelop/MSBuildEngine/CompileTaskNames", null, false);
for (int i = 0; i < CompileTaskNames.Count; i++) {
CompileTaskNames[i] = CompileTaskNames[i].ToLowerInvariant();
}
AdditionalTargetFiles = AddInTree.BuildItems<string>("/SharpDevelop/MSBuildEngine/AdditionalTargetFiles", null, false);
MSBuildProperties = new SortedList<string, string>();
MSBuildProperties.Add("SharpDevelopBinPath", Path.GetDirectoryName(typeof(MSBuildEngine).Assembly.Location));
}
@ -203,6 +212,11 @@ namespace ICSharpCode.SharpDevelop.Project @@ -203,6 +212,11 @@ namespace ICSharpCode.SharpDevelop.Project
Microsoft.Build.BuildEngine.Project project = engine.CreateNewProject();
try {
project.Load(buildFile);
foreach (string targetFile in AdditionalTargetFiles) {
project.AddNewImport(targetFile, null);
}
if (engine.BuildProject(project, targets))
results.NativeCompilerReturnValue = 0;
else
@ -217,6 +231,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -217,6 +231,7 @@ namespace ICSharpCode.SharpDevelop.Project
if (callback != null) {
WorkbenchSingleton.MainForm.BeginInvoke(callback, results);
}
engine.UnloadAllProjects();
}
}
@ -307,6 +322,21 @@ namespace ICSharpCode.SharpDevelop.Project @@ -307,6 +322,21 @@ namespace ICSharpCode.SharpDevelop.Project
{
if (string.Equals(file, activeTaskName, StringComparison.InvariantCultureIgnoreCase)) {
file = "";
} else if (file.StartsWith("positionof#")) {
string memberName = file.Substring(11);
file = "";
IProject project = ProjectService.GetProject(projectFiles.Peek());
if (project != null) {
IProjectContent pc = ParserService.GetProjectContent(project);
if (pc != null) {
Position pos = pc.GetPosition(memberName);
if (pos != null) {
file = pos.Cu.FileName ?? "";
lineNumber = pos.Line;
columnNumber = pos.Column;
}
}
}
} else {
bool isShortFileName = file == Path.GetFileNameWithoutExtension(file);
if (projectFiles.Count > 0) {

Loading…
Cancel
Save