Skip to content

Commit

Permalink
Merge remote branch 'sinesignal/master' into MonoIntegration
Browse files Browse the repository at this point in the history
Conflicts:
	.gitignore
	Reporting/ReportParameters.cs
  • Loading branch information
gasparnagy committed Jun 29, 2010
2 parents d676ad2 + b73812e commit 8aad449
Show file tree
Hide file tree
Showing 47 changed files with 944 additions and 77 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
*.pidb
*.userprefs
*.resharper
*.cache
*.gpState
Binary file added Documentation/SpecFlowMonoGuide.docx
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<Addin namespace = "MonoDevelop"
id = "TechTalk.SpecFlow"
name = "SpecFlow Support"
author = "TechTalk, SineSignal"
copyright = "BSD"
url = "http://www.specflow.org"
description = "Integrates SpecFlow into the MonoDevelop IDE."
category = "IDE extensions"
version = "2.4">

<Runtime>
<Import assembly="Gherkin.dll"/>
<Import assembly="IKVM.OpenJDK.Core.dll"/>
<Import assembly="IKVM.OpenJDK.Security.dll"/>
<Import assembly="IKVM.OpenJDK.Text.dll"/>
<Import assembly="IKVM.Runtime.dll"/>
<Import assembly="TechTalk.SpecFlow.Generator.dll"/>
<Import assembly="TechTalk.SpecFlow.Parser.dll"/>
</Runtime>

<Dependencies>
<Addin id="Core" version="2.4"/>
<Addin id="Ide" version="2.4"/>
</Dependencies>

<Extension path="/MonoDevelop/Core/MimeTypes">
<MimeType id="application/feature-template" _description="Feature Template" icon="res:SpecFlowFeatureIcon.ico" isText="true">
<File pattern="*.feature"/>
</MimeType>
</Extension>

<Extension path="/MonoDevelop/Ide/FileFilters">
<FileFilter id = "FeatureTemplates"
insertbefore = "AllFiles"
_label = "Feature Templates"
extensions = "*.feature"/>
</Extension>

<Extension path="/MonoDevelop/Ide/FileTemplates">
<FileTemplate id="SpecFlowFeatureTemplate" resource="SpecFlowFeature.xft.xml"/>
<FileTemplate id="SpecFlowStepDefinition" resource="SpecFlowStepDefinition.xft.xml"/>
<FileTemplate id="SpecFlowEventDefinition" resource="SpecFlowEventDefinition.xft.xml"/>
</Extension>

<Extension path="/MonoDevelop/Ide/CustomTools">
<Tool name="SpecFlowSingleFileGenerator" type="MonoDevelop.TechTalk.SpecFlow.SingleFeatureFileGenerator"/>
</Extension>
</Addin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{199D2315-F5BD-463C-B16A-BE31A845792B}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>MonoDevelop.TechTalk.SpecFlow</RootNamespace>
<AssemblyName>MonoDevelop.TechTalk.SpecFlow</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<EmbeddedResource Include="MonoDevelop.TechTalk.SpecFlow.addin.xml">
<LogicalName>MonoDevelop.TechTalk.SpecFlow.addin.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Templates\SpecFlowFeature.xft.xml">
<LogicalName>SpecFlowFeature.xft.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Gui\SpecFlowFeatureIcon.ico">
<LogicalName>SpecFlowFeatureIcon.ico</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Gui\SpecFlowEventDefinitionIcon.ico">
<LogicalName>SpecFlowEventDefinitionIcon.ico</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Gui\SpecFlowStepDefinitionIcon.ico">
<LogicalName>SpecFlowStepDefinitionIcon.ico</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Templates\SpecFlowStepDefinition.xft.xml">
<LogicalName>SpecFlowStepDefinition.xft.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Templates\SpecFlowEventDefinition.xft.xml">
<LogicalName>SpecFlowEventDefinition.xft.xml</LogicalName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Templates\" />
<Folder Include="Gui\" />
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Reference Include="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\monodevelop\MonoDevelop.Ide.dll</HintPath>
</Reference>
<Reference Include="MonoDevelop.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\monodevelop\MonoDevelop.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="SingleFeatureFileGenerator.cs" />
<Compile Include="MonoDevelopProjectReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="..\..\VersionInfo.cs">
<Link>VersionInfo.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Generator\TechTalk.SpecFlow.Generator.csproj">
<Project>{453D8014-B6CD-4E86-80A8-D59F59092334}</Project>
<Name>TechTalk.SpecFlow.Generator</Name>
</ProjectReference>
<ProjectReference Include="..\..\Parser\TechTalk.SpecFlow.Parser.csproj">
<Project>{7CCEF6D6-FC17-422E-9BED-EDD752B6496F}</Project>
<Name>TechTalk.SpecFlow.Parser</Name>
</ProjectReference>
</ItemGroup>
</Project>
64 changes: 64 additions & 0 deletions IdeIntegration/MonoDevelopIntegration/MonoDevelopProjectReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using MonoDevelop.Projects;

using TechTalk.SpecFlow.Generator.Configuration;

namespace MonoDevelop.TechTalk.SpecFlow
{
internal static class MonoDevelopProjectReader
{
public static SpecFlowProject CreateSpecFlowProjectFrom(Project project)
{
var specFlowProject = new SpecFlowProject();
specFlowProject.ProjectFolder = project.BaseDirectory;
specFlowProject.ProjectName = project.Name;

string defaultNamespace = "Namespace";
if (project is DotNetProject)
{
defaultNamespace = ((DotNetProject)project).GetDefaultNamespace(project.Name);
}

// No way to get AssemblyName right now, therefore we'll just use DefaultNamespace
specFlowProject.AssemblyName = defaultNamespace;
specFlowProject.DefaultNamespace = defaultNamespace;

// TODO: Find out if we really need to add all the feature files everytime we generate
foreach (ProjectFile projectFile in project.Files.Where(IsFeatureOrAppConfigFile))
{
string extension = Path.GetExtension(projectFile.Name);

if (extension.Equals(".feature", StringComparison.InvariantCultureIgnoreCase))
{
string fileName = projectFile.FilePath.ToRelative(project.BaseDirectory);
var featureFile = new SpecFlowFeatureFile(fileName);
var customToolNamespace = projectFile.CustomToolNamespace;

if (!String.IsNullOrEmpty(customToolNamespace))
featureFile.CustomNamespace = customToolNamespace;

specFlowProject.FeatureFiles.Add(featureFile);
}

if (extension.Equals(".config", StringComparison.InvariantCultureIgnoreCase))
{
string configContent = File.ReadAllText(projectFile.FilePath);
GeneratorConfigurationReader.UpdateConfigFromFileContent(specFlowProject.GeneratorConfiguration, configContent);
}
}

return specFlowProject;
}

private static bool IsFeatureOrAppConfigFile(ProjectFile projectFile)
{
string extension = Path.GetExtension(projectFile.Name);
return extension.Equals(".feature", StringComparison.InvariantCultureIgnoreCase)
|| projectFile.Name.Equals("app.config", StringComparison.InvariantCultureIgnoreCase);
}
}
}
24 changes: 24 additions & 0 deletions IdeIntegration/MonoDevelopIntegration/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("MonoDevelop.TechTalk.SpecFlow")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("MonoDevelop.TechTalk.SpecFlow")]
[assembly: AssemblyCopyright("Copyright © TechTalk, SineSignal, LLC 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("0ACD56A4-7A81-11DF-93DF-699DDFD72085")]

154 changes: 154 additions & 0 deletions IdeIntegration/MonoDevelopIntegration/SingleFeatureFileGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Text;
using System.Threading;

using Microsoft.CSharp;
using MonoDevelop.Core;
using MonoDevelop.Ide.CustomTools;
using MonoDevelop.Projects;

using TechTalk.SpecFlow.Generator;
using TechTalk.SpecFlow.Generator.Configuration;
using TechTalk.SpecFlow.Parser;

namespace MonoDevelop.TechTalk.SpecFlow
{
public class SingleFeatureFileGenerator : ISingleFileCustomTool
{
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result)
{
return new ThreadAsyncOperation(() => {

FilePath codeFilePath = file.FilePath.ChangeExtension(".feature.cs");

try
{
codeFilePath = GenerateFeatureCodeFileFor(file);
}
catch (Exception ex)
{
HandleException(ex, file, result);
}

result.GeneratedFilePath = codeFilePath;

}, result);
}

private FilePath GenerateFeatureCodeFileFor(ProjectFile featureFile)
{
// TODO: We only support C# for now, later we'll add support to grab the provider based on the project
CodeDomProvider codeProvider = new CSharpCodeProvider();
FilePath outputFile = featureFile.FilePath.ChangeExtension(".feature." + codeProvider.FileExtension);
SpecFlowProject specFlowProject = MonoDevelopProjectReader.CreateSpecFlowProjectFrom(featureFile.Project);
var specFlowGenerator = new SpecFlowGenerator(specFlowProject);

using (var writer = new StringWriter(new StringBuilder()))
using (var reader = new StringReader(File.ReadAllText(featureFile.FilePath)))
{
SpecFlowFeatureFile specFlowFeatureFile = specFlowProject.GetOrCreateFeatureFile(featureFile.FilePath);
specFlowGenerator.GenerateTestFile(specFlowFeatureFile, codeProvider, reader, writer);
File.WriteAllText(outputFile, writer.ToString());
}

return outputFile;
}

private void HandleException(Exception ex, ProjectFile file, SingleFileCustomToolResult result)
{
if (ex is SpecFlowParserException)
{
SpecFlowParserException sfpex = (SpecFlowParserException) ex;

if (sfpex.ErrorDetails == null || sfpex.ErrorDetails.Count == 0)
{
result.UnhandledException = ex;
}
else
{
var compilerErrors = new CompilerErrorCollection();

foreach (var errorDetail in sfpex.ErrorDetails)
{
var compilerError = new CompilerError(file.Name, errorDetail.ForcedLine, errorDetail.ForcedColumn, "0", errorDetail.Message);
compilerErrors.Add(compilerError);
}

result.Errors.AddRange(compilerErrors);
}
}
else
{
result.UnhandledException = ex;
}
}
}

internal class ThreadAsyncOperation : IAsyncOperation
{
private Thread Thread { get; set; }
private bool Cancelled { get; set; }
private SingleFileCustomToolResult Result { get; set; }
private Action Task { get; set; }

public ThreadAsyncOperation(Action task, SingleFileCustomToolResult result)
{
if (result == null)
throw new ArgumentNullException("result");

Task = task;
Result = result;
Thread = new Thread(Run);
Thread.Start();
}

private void Run()
{
try
{
Task();
}
catch (ThreadAbortException ex)
{
Result.UnhandledException = ex;
Thread.ResetAbort();
}
catch (Exception ex)
{
Result.UnhandledException = ex;
}

if (Completed != null)
Completed(this);
}

public event OperationHandler Completed;

public void Cancel()
{
Thread.Abort();
}

public void WaitForCompleted()
{
Thread.Join();
}

public bool IsCompleted
{
get { return !Thread.IsAlive; }
}

public bool Success
{
get { return !Cancelled && Result.Success; }
}

public bool SuccessWithWarnings
{
get { return !Cancelled && Result.SuccessWithWarnings; }
}
}
}
Loading

0 comments on commit 8aad449

Please sign in to comment.