Permalink
Browse files

using new generator interface

  • Loading branch information...
1 parent 9564644 commit 46ac55fb9d5dfcb3d6a064cf081c3f65a8fb62d0 @gasparnagy gasparnagy committed Mar 31, 2011
Showing with 883 additions and 190 deletions.
  1. +17 −0 CommonAssemblyInfo.cs
  2. +25 −0 Generator/ErrorHandlingTestGenerator.cs
  3. +48 −0 Generator/FeatureFileInputExtensions.cs
  4. +2 −1 Generator/GeneratorContainerBuilder.cs
  5. +10 −0 Generator/ITestHeaderWriter.cs
  6. +24 −8 Generator/Interfaces/FeatureFileInput.cs
  7. +2 −16 Generator/Interfaces/GenerationSettings.cs
  8. +4 −2 Generator/Interfaces/ITestGenerator.cs
  9. +1 −1 Generator/Interfaces/ITestGeneratorFactory.cs
  10. +23 −0 Generator/Interfaces/ProjectPlatformSettings.cs
  11. +22 −0 Generator/Interfaces/ProjectSettings.cs
  12. +5 −0 Generator/TechTalk.SpecFlow.Generator.csproj
  13. +44 −17 Generator/TestGenerator.cs
  14. +2 −1 Generator/TestGeneratorFactory.cs
  15. +24 −0 Generator/TestHeaderWriter.cs
  16. +5 −0 GeneratorTests/GeneratorTests.csproj
  17. +79 −9 GeneratorTests/TestGeneratorBasicsTests.cs
  18. +11 −12 GeneratorTests/TestGeneratorErrorsTests.cs
  19. +16 −9 GeneratorTests/TestGeneratorFactoryTests.cs
  20. +35 −22 GeneratorTests/TestGeneratorTestsBase.cs
  21. +98 −0 GeneratorTests/TestHeaderWriterTests.cs
  22. +79 −0 IdeIntegration/IdeIntegration/GeneratorServices.cs
  23. +14 −0 IdeIntegration/IdeIntegration/Properties/AssemblyInfo.cs
  24. +67 −0 IdeIntegration/IdeIntegration/TechTalk.SpecFlow.IdeIntegration.csproj
  25. +56 −0 IdeIntegration/Vs2010Integration/Generator/VsGeneratorServices.cs
  26. +6 −0 IdeIntegration/Vs2010Integration/LanguageService/NoProjectScope.cs
  27. +9 −1 IdeIntegration/Vs2010Integration/LanguageService/ProjectFeatureFilesTracker.cs
  28. +2 −0 IdeIntegration/Vs2010Integration/LanguageService/ProjectScope.cs
  29. +7 −0 IdeIntegration/Vs2010Integration/LanguageService/VsProjectScope.cs
  30. +1 −16 IdeIntegration/Vs2010Integration/Properties/AssemblyInfo.cs
  31. +16 −54 IdeIntegration/Vs2010Integration/SingleFileGenerator/SpecFlowSingleFileGenerator.cs
  32. +8 −0 IdeIntegration/Vs2010Integration/TechTalk.SpecFlow.Vs2010Integration.csproj
  33. +20 −2 TechTalk.SpecFlow.sln
  34. +1 −0 Utils/TechTalk.SpecFlow.Utils.csproj
  35. +73 −0 Utils/TempFile.cs
  36. +27 −19 lib/MiniDi/MiniDi.cs
View
17 CommonAssemblyInfo.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyCompany("TechTalk")]
+[assembly: AssemblyProduct("SpecFlow")]
+[assembly: AssemblyCopyright("Copyright © TechTalk 2011")]
+[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)]
+[assembly: CLSCompliant(false)]
+[assembly: NeutralResourcesLanguage("en-US")]
View
25 Generator/ErrorHandlingTestGenerator.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics;
using System.Linq;
using TechTalk.SpecFlow.Generator.Interfaces;
using TechTalk.SpecFlow.Parser;
@@ -9,6 +10,9 @@ public abstract class ErrorHandlingTestGenerator : ITestGenerator
{
public TestGeneratorResult GenerateTestFile(FeatureFileInput featureFileInput, GenerationSettings settings)
{
+ if (featureFileInput == null) throw new ArgumentNullException("featureFileInput");
+ if (settings == null) throw new ArgumentNullException("settings");
+
try
{
return GenerateTestFileWithExceptions(featureFileInput, settings);
@@ -27,6 +31,27 @@ public TestGeneratorResult GenerateTestFile(FeatureFileInput featureFileInput, G
}
}
+ public Version DetectGeneratedTestVersion(FeatureFileInput featureFileInput)
+ {
+ if (featureFileInput == null) throw new ArgumentNullException("featureFileInput");
+
+ try
+ {
+ return DetectGeneratedTestVersionWithExceptions(featureFileInput);
+ }
+ catch(Exception exception)
+ {
+ Debug.WriteLine(exception, "ErrorHandlingTestGenerator.DetectGeneratedTestVersion");
+ return null;
+ }
+ }
+
protected abstract TestGeneratorResult GenerateTestFileWithExceptions(FeatureFileInput featureFileInput, GenerationSettings settings);
+ protected abstract Version DetectGeneratedTestVersionWithExceptions(FeatureFileInput featureFileInput);
+
+ public virtual void Dispose()
+ {
+ //nop;
+ }
}
}
View
48 Generator/FeatureFileInputExtensions.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using TechTalk.SpecFlow.Generator.Interfaces;
+
+namespace TechTalk.SpecFlow.Generator
+{
+ public static class FeatureFileInputExtensions
+ {
+ public static TextReader GetFeatureFileContentReader(this FeatureFileInput featureFileInput, ProjectSettings projectSettings)
+ {
+ if (featureFileInput == null) throw new ArgumentNullException("featureFileInput");
+
+ if (featureFileInput.FeatureFileContent != null)
+ return new StringReader(featureFileInput.FeatureFileContent);
+
+ Debug.Assert(projectSettings != null);
+
+ return new StreamReader(Path.Combine(projectSettings.ProjectFolder, featureFileInput.ProjectRelativePath));
+ }
+
+ public static string GetFullPath(this FeatureFileInput featureFileInput, ProjectSettings projectSettings)
+ {
+ if (featureFileInput == null) throw new ArgumentNullException("featureFileInput");
+
+ if (projectSettings == null)
+ return featureFileInput.ProjectRelativePath;
+
+ return Path.GetFullPath(Path.Combine(projectSettings.ProjectFolder, featureFileInput.ProjectRelativePath));
+ }
+
+ public static string GetGeneratedTestFullPath(this FeatureFileInput featureFileInput, ProjectSettings projectSettings)
+ {
+ if (featureFileInput == null) throw new ArgumentNullException("featureFileInput");
+
+ if (featureFileInput.GeneratedTestProjectRelativePath == null)
+ return null;
+
+ if (projectSettings == null)
+ return featureFileInput.GeneratedTestProjectRelativePath;
+
+ return Path.GetFullPath(Path.Combine(projectSettings.ProjectFolder, featureFileInput.GeneratedTestProjectRelativePath));
+ }
+ }
+}
View
3 Generator/GeneratorContainerBuilder.cs
@@ -31,7 +31,8 @@ public static IObjectContainer CreateContainer(SpecFlowConfigurationHolder confi
private static void RegisterDefaults(ObjectContainer container)
{
- container.RegisterTypeAs<TestGenerator,ITestGenerator>();
+ container.RegisterTypeAs<TestGenerator, ITestGenerator>();
+ container.RegisterTypeAs<TestHeaderWriter, ITestHeaderWriter>();
}
}
}
View
10 Generator/ITestHeaderWriter.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Linq;
+
+namespace TechTalk.SpecFlow.Generator
+{
+ public interface ITestHeaderWriter
+ {
+ Version DetectGeneratedTestVersion(string generatedTestContent);
+ }
+}
View
32 Generator/Interfaces/FeatureFileInput.cs
@@ -6,19 +6,35 @@ namespace TechTalk.SpecFlow.Generator.Interfaces
[Serializable]
public class FeatureFileInput
{
- public string FullPath { get; private set; }
+ /// <summary>
+ /// The project relative path of the feature file. Must be sepecified.
+ /// </summary>
public string ProjectRelativePath { get; private set; }
- public string CustomNamespace { get; private set; }
- public TextReader ContentReader { get; private set; }
+ /// <summary>
+ /// The content of the feature file. Optional. If not specified, the content is read from <see cref="ProjectRelativePath"/>.
+ /// </summary>
+ public string FeatureFileContent { get; set; }
+ /// <summary>
+ /// A custom namespace for the generated test class. Optional.
+ /// </summary>
+ public string CustomNamespace { get; set; }
- public FeatureFileInput(string fullPath, string projectRelativePath, string customNamespace, TextReader contentReader)
+ /// <summary>
+ /// The project relative path of the generated test class file. Optional, used for up-to-date checking.
+ /// </summary>
+ public string GeneratedTestProjectRelativePath { get; set; }
+ /// <summary>
+ /// The content of the existing test class file. Optional, used for up-to-date checking.
+ /// </summary>
+ public string GeneratedTestFileContent { get; set; }
+
+ public FeatureFileInput(string projectRelativePath)
{
- if (contentReader == null) throw new ArgumentNullException("contentReader");
+ if (projectRelativePath == null) throw new ArgumentNullException("projectRelativePath");
+ if (string.IsNullOrEmpty(Path.GetFileName(projectRelativePath)))
+ throw new ArgumentException("The feature file path must denote a file and not a directory", "projectRelativePath");
- FullPath = fullPath;
ProjectRelativePath = projectRelativePath;
- CustomNamespace = customNamespace;
- ContentReader = contentReader;
}
}
}
View
18 Generator/Interfaces/GenerationSettings.cs
@@ -5,27 +5,13 @@ namespace TechTalk.SpecFlow.Generator.Interfaces
[Serializable]
public class GenerationSettings
{
- public string TargetLanguage { get; set; }
- public Version TargetLanguageVersion { get; set; }
-
- public string TargetPlatform { get; set; }
- public Version TargetPlatformVersion { get; set; }
-
- public string ProjectDefaultNamespace { get; set; }
-
public bool CheckUpToDate { get; set; }
+ public bool WriteResultToFile { get; set; }
public GenerationSettings()
{
- TargetLanguage = GenerationTargetLanguage.CSharp;
- TargetLanguageVersion = new Version(3, 0);
-
- TargetPlatform = GenerationTargetPlatform.DotNet;
- TargetPlatformVersion = new Version(3, 5);
-
- ProjectDefaultNamespace = "SpecFlow.GeneratedTests";
-
CheckUpToDate = false;
+ WriteResultToFile = false;
}
}
}
View
6 Generator/Interfaces/ITestGenerator.cs
@@ -1,9 +1,11 @@
-using System.IO;
+using System;
+using System.IO;
namespace TechTalk.SpecFlow.Generator.Interfaces
{
- public interface ITestGenerator
+ public interface ITestGenerator : IDisposable
{
TestGeneratorResult GenerateTestFile(FeatureFileInput featureFileInput, GenerationSettings settings);
+ Version DetectGeneratedTestVersion(FeatureFileInput featureFileInput);
}
}
View
2 Generator/Interfaces/ITestGeneratorFactory.cs
@@ -5,6 +5,6 @@ namespace TechTalk.SpecFlow.Generator.Interfaces
public interface ITestGeneratorFactory
{
Version GetGeneratorVersion();
- ITestGenerator CreateGenerator(SpecFlowConfigurationHolder configurationHolder);
+ ITestGenerator CreateGenerator(SpecFlowConfigurationHolder configurationHolder, ProjectSettings projectSettings);
}
}
View
23 Generator/Interfaces/ProjectPlatformSettings.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace TechTalk.SpecFlow.Generator.Interfaces
+{
+ [Serializable]
+ public class ProjectPlatformSettings
+ {
+ public string Language { get; set; }
+ public Version LanguageVersion { get; set; }
+
+ public string Platform { get; set; }
+ public Version PlatformVersion { get; set; }
+
+ public ProjectPlatformSettings()
+ {
+ Language = GenerationTargetLanguage.CSharp;
+ LanguageVersion = new Version(3, 0);
+
+ Platform = GenerationTargetPlatform.DotNet;
+ PlatformVersion = new Version(3, 5);
+ }
+ }
+}
View
22 Generator/Interfaces/ProjectSettings.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace TechTalk.SpecFlow.Generator.Interfaces
+{
+ [Serializable]
+ public class ProjectSettings
+ {
+ public string ProjectFolder { get; set; }
+ public string DefaultNamespace { get; set; }
+ public ProjectPlatformSettings ProjectPlatformSettings { get; set; }
+
+ public ProjectSettings(string projectFolder, string defaultNamespace, ProjectPlatformSettings projectPlatformSettings)
+ {
+ if (projectFolder == null) throw new ArgumentNullException("projectFolder");
+ if (defaultNamespace == null) throw new ArgumentNullException("defaultNamespace");
+
+ ProjectFolder = projectFolder;
+ DefaultNamespace = defaultNamespace;
+ ProjectPlatformSettings = projectPlatformSettings ?? new ProjectPlatformSettings();
+ }
+ }
+}
View
5 Generator/TechTalk.SpecFlow.Generator.csproj
@@ -78,6 +78,7 @@
<Compile Include="Configuration\RuntimeConfigurationReader.cs" />
<Compile Include="Configuration\SpecFlowProject.cs" />
<Compile Include="ErrorHandlingTestGenerator.cs" />
+ <Compile Include="FeatureFileInputExtensions.cs" />
<Compile Include="GeneratorContainerBuilder.cs" />
<Compile Include="IndentProcessingWriter.cs" />
<Compile Include="Interfaces\FeatureFileInput.cs" />
@@ -86,10 +87,14 @@
<Compile Include="GenerationTargetPlatform.cs" />
<Compile Include="Interfaces\ITestGenerator.cs" />
<Compile Include="Interfaces\ITestGeneratorFactory.cs" />
+ <Compile Include="Interfaces\ProjectPlatformSettings.cs" />
+ <Compile Include="Interfaces\ProjectSettings.cs" />
<Compile Include="Interfaces\SpecFlowConfigurationHolder.cs" />
<Compile Include="Interfaces\TestGenerationError.cs" />
<Compile Include="Interfaces\TestGeneratorFactoryAttribute.cs" />
<Compile Include="Interfaces\TestGeneratorResult.cs" />
+ <Compile Include="ITestHeaderWriter.cs" />
+ <Compile Include="TestHeaderWriter.cs" />
<Compile Include="UnitTestConverter\ISpecFlowUnitTestConverter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SpecFlowGenerator.cs" />
View
61 Generator/TestGenerator.cs
@@ -19,16 +19,24 @@ namespace TechTalk.SpecFlow.Generator
{
public class TestGenerator : ErrorHandlingTestGenerator
{
- private readonly GeneratorConfiguration generatorConfiguration;
+ protected readonly GeneratorConfiguration generatorConfiguration;
+ protected readonly ProjectSettings projectSettings;
+ protected readonly ITestHeaderWriter testHeaderWriter;
- public TestGenerator(GeneratorConfiguration generatorConfiguration)
+ public TestGenerator(GeneratorConfiguration generatorConfiguration, ProjectSettings projectSettings, ITestHeaderWriter testHeaderWriter)
{
+ if (generatorConfiguration == null) throw new ArgumentNullException("generatorConfiguration");
+ if (projectSettings == null) throw new ArgumentNullException("projectSettings");
+ if (testHeaderWriter == null) throw new ArgumentNullException("testHeaderWriter");
+
this.generatorConfiguration = generatorConfiguration;
+ this.testHeaderWriter = testHeaderWriter;
+ this.projectSettings = projectSettings;
}
- protected virtual CodeDomProvider CreateCodeDomProvider(GenerationSettings settings)
+ protected virtual CodeDomProvider CreateCodeDomProvider(ProjectPlatformSettings settings)
{
- switch (settings.TargetLanguage)
+ switch (settings.Language)
{
case GenerationTargetLanguage.CSharp:
return new CSharpCodeProvider();
@@ -46,13 +54,16 @@ protected virtual CodeDomHelper CreateCodeDomHelper(CodeDomProvider codeDomProvi
protected override TestGeneratorResult GenerateTestFileWithExceptions(FeatureFileInput featureFileInput, GenerationSettings settings)
{
+ if (featureFileInput == null) throw new ArgumentNullException("featureFileInput");
+ if (settings == null) throw new ArgumentNullException("settings");
+
StringWriter outputStringWriter = new StringWriter();
var outputWriter = new IndentProcessingWriter(outputStringWriter);
- var codeProvider = CreateCodeDomProvider(settings);
+ var codeProvider = CreateCodeDomProvider(projectSettings.ProjectPlatformSettings);
CodeDomHelper codeDomHelper = CreateCodeDomHelper(codeProvider, settings);
- var codeNamespace = GenerateTestFileCode(featureFileInput, codeDomHelper, settings);
+ var codeNamespace = GenerateTestFileCode(featureFileInput, codeDomHelper);
var options = new CodeGeneratorOptions
{
BracingStyle = "C"
@@ -66,12 +77,16 @@ protected override TestGeneratorResult GenerateTestFileWithExceptions(FeatureFil
return new TestGeneratorResult(outputStringWriter.ToString(), false);
}
- private CodeNamespace GenerateTestFileCode(FeatureFileInput featureFileInput, CodeDomHelper codeDomHelper, GenerationSettings settings)
+ private CodeNamespace GenerateTestFileCode(FeatureFileInput featureFileInput, CodeDomHelper codeDomHelper)
{
- string targetNamespace = GetTargetNamespace(featureFileInput, settings);
+ string targetNamespace = GetTargetNamespace(featureFileInput) ?? "SpecFlow.GeneratedTests";
SpecFlowLangParser parser = new SpecFlowLangParser(generatorConfiguration.FeatureLanguage);
- Feature feature = parser.Parse(featureFileInput.ContentReader, featureFileInput.FullPath);
+ Feature feature;
+ using (var contentReader = featureFileInput.GetFeatureFileContentReader(projectSettings))
+ {
+ feature = parser.Parse(contentReader, featureFileInput.GetFullPath(projectSettings));
+ }
IUnitTestGeneratorProvider generatorProvider = ConfigurationServices.CreateInstance<IUnitTestGeneratorProvider>(generatorConfiguration.GeneratorUnitTestProviderType);
codeDomHelper.InjectIfRequired(generatorProvider);
@@ -82,21 +97,19 @@ private CodeNamespace GenerateTestFileCode(FeatureFileInput featureFileInput, Co
return codeNamespace;
}
- private string GetTargetNamespace(FeatureFileInput featureFileInput, GenerationSettings settings)
+ private string GetTargetNamespace(FeatureFileInput featureFileInput)
{
if (!string.IsNullOrEmpty(featureFileInput.CustomNamespace))
return featureFileInput.CustomNamespace;
- if (string.IsNullOrEmpty(settings.ProjectDefaultNamespace))
+ if (projectSettings == null || string.IsNullOrEmpty(projectSettings.DefaultNamespace))
return null;
- string targetNamespace = settings.ProjectDefaultNamespace;
+ string targetNamespace = projectSettings.DefaultNamespace;
- string namespaceExtension = string.Join(".",
- (Path.GetDirectoryName(featureFileInput.ProjectRelativePath) ?? "")
- .TrimStart('\\', '/', '.')
- .Split('\\', '/')
- .Select(f => f.ToIdentifier()).ToArray());
+ var directoryName = Path.GetDirectoryName(featureFileInput.ProjectRelativePath);
+ string namespaceExtension = string.IsNullOrEmpty(directoryName) ? null :
+ string.Join(".", directoryName.TrimStart('\\', '/', '.').Split('\\', '/').Select(f => f.ToIdentifier()).ToArray());
if (!string.IsNullOrEmpty(namespaceExtension))
targetNamespace += "." + namespaceExtension;
return targetNamespace;
@@ -105,6 +118,20 @@ private string GetTargetNamespace(FeatureFileInput featureFileInput, GenerationS
#region Header & Footer
+ protected override Version DetectGeneratedTestVersionWithExceptions(FeatureFileInput featureFileInput)
+ {
+ var generatedTestFileContent = featureFileInput.GeneratedTestFileContent;
+ if (generatedTestFileContent == null)
+ {
+ var generatedTestPath = featureFileInput.GetGeneratedTestFullPath(projectSettings);
+ if (generatedTestPath == null)
+ return null;
+ generatedTestFileContent = File.ReadAllText(generatedTestPath);
+ }
+
+ return testHeaderWriter.DetectGeneratedTestVersion(generatedTestFileContent);
+ }
+
private void AddSpecFlowHeader(CodeDomProvider codeProvider, TextWriter outputWriter, CodeDomHelper codeDomHelper)
{
const string specFlowHeaderTemplate = @"------------------------------------------------------------------------------
View
3 Generator/TestGeneratorFactory.cs
@@ -13,9 +13,10 @@ public Version GetGeneratorVersion()
return GeneratorVersion;
}
- public ITestGenerator CreateGenerator(SpecFlowConfigurationHolder configurationHolder)
+ public ITestGenerator CreateGenerator(SpecFlowConfigurationHolder configurationHolder, ProjectSettings projectSettings)
{
var container = GeneratorContainerBuilder.CreateContainer(configurationHolder);
+ container.RegisterInstanceAs(projectSettings);
return container.Resolve<ITestGenerator>();
}
}
View
24 Generator/TestHeaderWriter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace TechTalk.SpecFlow.Generator
+{
+ public class TestHeaderWriter : ITestHeaderWriter
+ {
+ static private readonly Regex generatorVersionRe = new Regex(@"<auto-generated>.*SpecFlow Generator Version:\s*(?<ver>\d+\.\d+\.\d+\.\d+).*</auto-generated>", RegexOptions.Singleline);
+ static private readonly Regex versionRe = new Regex(@"<auto-generated>.*SpecFlow Version:\s*(?<ver>\d+\.\d+\.\d+\.\d+).*</auto-generated>", RegexOptions.Singleline);
+
+ public Version DetectGeneratedTestVersion(string generatedTestContent)
+ {
+ var match = generatorVersionRe.Match(generatedTestContent);
+
+ if (!match.Success)
+ match = versionRe.Match(generatedTestContent);
+
+ if (match.Success)
+ return new Version(match.Groups["ver"].Value);
+
+ return null;
+ }
+ }
+}
View
5 GeneratorTests/GeneratorTests.csproj
@@ -49,6 +49,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="TestHeaderWriterTests.cs" />
<Compile Include="TestGeneratorErrorsTests.cs" />
<Compile Include="GeneratorContainerBuilderTests.cs" />
<Compile Include="TestGeneratorFactoryTests.cs" />
@@ -61,6 +62,10 @@
<Project>{453D8014-B6CD-4E86-80A8-D59F59092334}</Project>
<Name>TechTalk.SpecFlow.Generator</Name>
</ProjectReference>
+ <ProjectReference Include="..\Utils\TechTalk.SpecFlow.Utils.csproj">
+ <Project>{C0AF4A43-0C3B-47C7-86DE-79FB632B1453}</Project>
+ <Name>TechTalk.SpecFlow.Utils</Name>
+ </ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
View
88 GeneratorTests/TestGeneratorBasicsTests.cs
@@ -1,60 +1,130 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Text;
+using Moq;
using NUnit.Framework;
using TechTalk.SpecFlow.Generator;
using TechTalk.SpecFlow.Generator.Configuration;
using Should;
using TechTalk.SpecFlow.Generator.Interfaces;
+using TechTalk.SpecFlow.Utils;
namespace GeneratorTests
{
[TestFixture]
public class TestGeneratorBasicsTests : TestGeneratorTestsBase
{
- private string GenerateTestFromSimpleFeature(GenerationSettings settings)
+ private string GenerateTestFromSimpleFeature(ProjectSettings projectSettings)
{
- TestGenerator testGenerator = new TestGenerator(new GeneratorConfiguration());
+ var testGenerator = CreateTestGenerator(projectSettings);
- var result = testGenerator.GenerateTestFile(CreateSimpleValidFeatureFileInput(), settings);
+ var result = testGenerator.GenerateTestFile(CreateSimpleValidFeatureFileInput(), defaultSettings);
result.Success.ShouldBeTrue();
return result.GeneratedTestCode;
}
[Test]
public void Should_generate_a_net35_csharp_test_from_simple_feature()
{
- string outputFile = GenerateTestFromSimpleFeature(net35CSSettings);
+ string outputFile = GenerateTestFromSimpleFeature(net35CSProjectSettings);
outputFile.ShouldNotBeEmpty();
}
[Test]
public void Should_generate_a_net35_vb_test_from_simple_feature()
{
- string outputFile = GenerateTestFromSimpleFeature(net35VBSettings);
+ string outputFile = GenerateTestFromSimpleFeature(net35VBProjectSettings);
outputFile.ShouldNotBeEmpty();
}
[Test]
public void Should_include_header_in_generated_file()
{
- string outputFile = GenerateTestFromSimpleFeature(net35CSSettings);
+ string outputFile = GenerateTestFromSimpleFeature(net35CSProjectSettings);
outputFile.ShouldContain("This code was generated by SpecFlow");
}
[Test]
public void Should_wrap_generated_test_with_designer_region()
{
- string outputFile = GenerateTestFromSimpleFeature(net35CSSettings);
+ string outputFile = GenerateTestFromSimpleFeature(net35CSProjectSettings);
outputFile.ShouldContain("#region Designer generated code");
outputFile.ShouldContain("#endregion");
}
[Test]
public void Should_include_generator_version_in_the_header()
{
- string outputFile = GenerateTestFromSimpleFeature(net35CSSettings);
+ string outputFile = GenerateTestFromSimpleFeature(net35CSProjectSettings);
outputFile.ShouldContain(string.Format("SpecFlow Generator Version:{0}", TestGeneratorFactory.GeneratorVersion));
}
+
+ [Test]
+ public void Should_generate_test_from_feature_file_specified_by_path()
+ {
+ using (var tempFile = new TempFile(".feature"))
+ {
+ tempFile.SetContent(CreateSimpleValidFeatureFileInput().FeatureFileContent);
+
+ ProjectSettings projectSettings = new ProjectSettings(tempFile.FolderName, "DefaultNamespace", net35CSSettings);
+ var testGenerator = CreateTestGenerator(projectSettings);
+
+ var result = testGenerator.GenerateTestFile(
+ new FeatureFileInput(tempFile.FileName),
+ defaultSettings);
+ result.Success.ShouldBeTrue();
+ }
+ }
+
+ [Test]
+ public void Should_return_detected_version()
+ {
+ Version version = new Version();
+ TestHeaderWriterStub.Setup(thw => thw.DetectGeneratedTestVersion("any")).Returns(version);
+
+ var testGenerator = CreateTestGenerator();
+ FeatureFileInput featureFileInput = CreateSimpleValidFeatureFileInput();
+ featureFileInput.GeneratedTestFileContent = "any";
+ var result = testGenerator.DetectGeneratedTestVersion(featureFileInput);
+
+ result.ShouldNotBeNull();
+ result.ShouldEqual(version);
+ }
+
+ [Test]
+ public void Should_return_detected_version_from_file()
+ {
+ Version version = new Version();
+ TestHeaderWriterStub.Setup(thw => thw.DetectGeneratedTestVersion("any")).Returns(version);
+
+ using (var tempFile = new TempFile(".cs"))
+ {
+ tempFile.SetContent("any");
+
+ ProjectSettings projectSettings = new ProjectSettings(tempFile.FolderName, "DefaultNamespace", net35CSSettings);
+ var testGenerator = CreateTestGenerator(projectSettings);
+ FeatureFileInput featureFileInput = CreateSimpleValidFeatureFileInput();
+ featureFileInput.GeneratedTestProjectRelativePath = tempFile.FileName;
+ var result = testGenerator.DetectGeneratedTestVersion(featureFileInput);
+
+ result.ShouldNotBeNull();
+ result.ShouldEqual(version);
+ }
+ }
+
+ [Test]
+ public void Should_return_unknown_version_when_there_is_an_error()
+ {
+ TestHeaderWriterStub.Setup(thw => thw.DetectGeneratedTestVersion("any")).Throws(new Exception());
+
+ var testGenerator = CreateTestGenerator();
+ FeatureFileInput featureFileInput = CreateSimpleValidFeatureFileInput();
+ featureFileInput.GeneratedTestFileContent = "any";
+ var result = testGenerator.DetectGeneratedTestVersion(featureFileInput);
+
+ result.ShouldBeNull();
+ }
}
}
View
23 GeneratorTests/TestGeneratorErrorsTests.cs
@@ -1,6 +1,5 @@
-using System.Collections.Generic;
+using System.IO;
using System.Linq;
-using System.Text;
using NUnit.Framework;
using TechTalk.SpecFlow.Generator;
using TechTalk.SpecFlow.Generator.Configuration;
@@ -15,44 +14,44 @@ public class TestGeneratorErrorsTests : TestGeneratorTestsBase
[Test]
public void Should_not_succeed_when_invalid_feature_file()
{
- TestGenerator testGenerator = new TestGenerator(new GeneratorConfiguration());
+ var testGenerator = CreateTestGenerator(net35CSProjectSettings);
- var result = testGenerator.GenerateTestFile(CreateSimpleInvalidFeatureFileInput(), net35CSSettings);
+ var result = testGenerator.GenerateTestFile(CreateSimpleInvalidFeatureFileInput(), defaultSettings);
result.Success.ShouldBeFalse();
}
[Test]
public void Should_report_error_when_invalid_feature_file()
{
- TestGenerator testGenerator = new TestGenerator(new GeneratorConfiguration());
+ var testGenerator = CreateTestGenerator(net35CSProjectSettings);
- var result = testGenerator.GenerateTestFile(CreateSimpleInvalidFeatureFileInput(), net35CSSettings);
+ var result = testGenerator.GenerateTestFile(CreateSimpleInvalidFeatureFileInput(), defaultSettings);
result.Errors.ShouldNotBeNull();
result.Errors.ShouldNotBeEmpty();
}
[Test]
public void Should_report_multiple_errors_when_feature_file_contains_such()
{
- TestGenerator testGenerator = new TestGenerator(new GeneratorConfiguration());
+ var testGenerator = CreateTestGenerator(net35CSProjectSettings);
var result = testGenerator.GenerateTestFile(CreateSimpleFeatureFileInput(@"
Feature: Addition
Scenario: Add two numbers
Given I have entered 50 into the calculator
AndXXX the keyword is misspelled
- AndYYY this keyword is also misspelled"), net35CSSettings);
+ AndYYY this keyword is also misspelled"), defaultSettings);
result.Errors.ShouldNotBeNull();
result.Errors.Count().ShouldEqual(2);
}
[Test]
- public void Should_report_error_when_invalid_input()
+ public void Should_report_error_when_unsupported_project_language()
{
- TestGenerator testGenerator = new TestGenerator(new GeneratorConfiguration());
+ ProjectSettings invalidLangSettings = new ProjectSettings(Path.GetTempPath(), "DN", new ProjectPlatformSettings { Language = "InvalidLang" });
+ var testGenerator = CreateTestGenerator(invalidLangSettings);
- var result = testGenerator.GenerateTestFile(CreateSimpleValidFeatureFileInput(),
- new GenerationSettings { TargetLanguage = "InvalidLang"});
+ var result = testGenerator.GenerateTestFile(CreateSimpleValidFeatureFileInput(), defaultSettings);
result.Errors.ShouldNotBeNull();
result.Errors.ShouldNotBeEmpty();
}
View
25 GeneratorTests/TestGeneratorFactoryTests.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.IO;
using System.Linq;
-using System.Text;
-using System.Xml.Linq;
using NUnit.Framework;
using TechTalk.SpecFlow.Generator;
using Should;
@@ -12,13 +8,14 @@
namespace GeneratorTests
{
[TestFixture]
- public class TestGeneratorFactoryTests
+ public class TestGeneratorFactoryTests : TestGeneratorTestsBase
{
private TestGeneratorFactory factory;
[SetUp]
- public void Setup()
+ public override void Setup()
{
+ base.Setup();
factory = new TestGeneratorFactory();
}
@@ -31,7 +28,7 @@ public void GetGeneratorVersion_should_return_a_version()
[Test]
public void Should_be_able_to_create_generator_with_default_config()
{
- factory.CreateGenerator(new SpecFlowConfigurationHolder()).ShouldNotBeNull();
+ factory.CreateGenerator(new SpecFlowConfigurationHolder(), net35CSProjectSettings).ShouldNotBeNull();
}
private class DummyGenerator : ITestGenerator
@@ -40,6 +37,16 @@ public TestGeneratorResult GenerateTestFile(FeatureFileInput featureFileInput, G
{
throw new NotImplementedException();
}
+
+ public Version DetectGeneratedTestVersion(FeatureFileInput featureFileInput)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Dispose()
+ {
+ //nop;
+ }
}
[Test]
@@ -51,8 +58,8 @@ public void Should_create_custom_generator_when_configured_so()
<register type=""{0}"" as=""{1}""/>
</dependencies>
</specFlow>",
- typeof(DummyGenerator).AssemblyQualifiedName,
- typeof(ITestGenerator).AssemblyQualifiedName)));
+ typeof(DummyGenerator).AssemblyQualifiedName,
+ typeof(ITestGenerator).AssemblyQualifiedName)), net35CSProjectSettings);
generator.ShouldBeType(typeof(DummyGenerator));
}
View
57 GeneratorTests/TestGeneratorTestsBase.cs
@@ -1,37 +1,45 @@
using System;
using System.IO;
+using Moq;
using NUnit.Framework;
using TechTalk.SpecFlow.Generator;
+using TechTalk.SpecFlow.Generator.Configuration;
using TechTalk.SpecFlow.Generator.Interfaces;
namespace GeneratorTests
{
public abstract class TestGeneratorTestsBase
{
- protected GenerationSettings net35CSSettings;
- protected GenerationSettings net35VBSettings;
+ protected ProjectPlatformSettings net35CSSettings;
+ protected ProjectPlatformSettings net35VBSettings;
+ protected ProjectSettings net35CSProjectSettings;
+ protected ProjectSettings net35VBProjectSettings;
+ protected GenerationSettings defaultSettings;
+ protected Mock<ITestHeaderWriter> TestHeaderWriterStub;
[SetUp]
public virtual void Setup()
{
- net35CSSettings = new GenerationSettings
+ net35CSSettings = new ProjectPlatformSettings
{
- TargetLanguage = GenerationTargetLanguage.CSharp,
- TargetLanguageVersion = new Version("3.0"),
- TargetPlatform = GenerationTargetPlatform.DotNet,
- TargetPlatformVersion = new Version("3.5"),
- ProjectDefaultNamespace = "DefaultNamespace",
- CheckUpToDate = false
+ Language = GenerationTargetLanguage.CSharp,
+ LanguageVersion = new Version("3.0"),
+ Platform = GenerationTargetPlatform.DotNet,
+ PlatformVersion = new Version("3.5"),
};
- net35VBSettings = new GenerationSettings
+ net35VBSettings = new ProjectPlatformSettings
{
- TargetLanguage = GenerationTargetLanguage.VB,
- TargetLanguageVersion = new Version("9.0"),
- TargetPlatform = GenerationTargetPlatform.DotNet,
- TargetPlatformVersion = new Version("3.5"),
- ProjectDefaultNamespace = "DefaultNamespace",
- CheckUpToDate = false
+ Language = GenerationTargetLanguage.VB,
+ LanguageVersion = new Version("9.0"),
+ Platform = GenerationTargetPlatform.DotNet,
+ PlatformVersion = new Version("3.5"),
};
+
+ net35CSProjectSettings = new ProjectSettings(Path.GetTempPath(), "DefaultNamespace", net35CSSettings);
+ net35VBProjectSettings = new ProjectSettings(Path.GetTempPath(), "DefaultNamespace", net35VBSettings);
+ defaultSettings = new GenerationSettings();
+
+ TestHeaderWriterStub = new Mock<ITestHeaderWriter>();
}
protected FeatureFileInput CreateSimpleValidFeatureFileInput()
@@ -50,12 +58,7 @@ protected FeatureFileInput CreateSimpleValidFeatureFileInput()
protected FeatureFileInput CreateSimpleFeatureFileInput(string featureFileContent)
{
- return new FeatureFileInput(
- @"C:\Temp\Dummy.feature",
- @"Dummy.feature",
- null,
- new StringReader(featureFileContent)
- );
+ return new FeatureFileInput(@"Dummy.feature") {FeatureFileContent = featureFileContent};
}
protected FeatureFileInput CreateSimpleInvalidFeatureFileInput()
@@ -67,5 +70,15 @@ protected FeatureFileInput CreateSimpleInvalidFeatureFileInput()
AndXXX the keyword is misspelled
");
}
+
+ protected TestGenerator CreateTestGenerator()
+ {
+ return CreateTestGenerator(net35CSProjectSettings);
+ }
+
+ protected TestGenerator CreateTestGenerator(ProjectSettings projectSettings)
+ {
+ return new TestGenerator(new GeneratorConfiguration(), projectSettings, TestHeaderWriterStub.Object);
+ }
}
}
View
98 GeneratorTests/TestHeaderWriterTests.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+using TechTalk.SpecFlow.Generator;
+using Should;
+
+namespace GeneratorTests
+{
+ [TestFixture]
+ public class TestHeaderWriterTests : TestGeneratorTestsBase
+ {
+ private TestHeaderWriter CreateTestHeaderWriter()
+ {
+ return new TestHeaderWriter();
+ }
+
+ [Test]
+ public void Should_return_version_from_a_cs_file_with_specific_generator_version()
+ {
+ var testHeaderWriter = CreateTestHeaderWriter();
+ var result = testHeaderWriter.DetectGeneratedTestVersion(@"// ------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by SpecFlow (http://www.specflow.org/).
+// SpecFlow Version:1.6.0.0
+// SpecFlow Generator Version:1.5.0.0
+// Runtime Version:4.0.30319.225
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+// ------------------------------------------------------------------------------
+#region Designer generated code
+namespace Bowling.Specflow
+{
+}
+#endregion
+");
+
+ result.ShouldNotBeNull();
+ result.ToString().ShouldEqual("1.5.0.0");
+ }
+
+ [Test]
+ public void Should_return_version_from_a_vb_file_with_specific_generator_version()
+ {
+ var testHeaderWriter = CreateTestHeaderWriter();
+ var result = testHeaderWriter.DetectGeneratedTestVersion(@"'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by SpecFlow (http://www.specflow.org/).
+' SpecFlow Version:1.3.2.0
+' SpecFlow Generator Version:1.5.0.0
+' Runtime Version:2.0.50727.4927
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+");
+
+ result.ShouldNotBeNull();
+ result.ToString().ShouldEqual("1.5.0.0");
+ }
+
+ [Test]
+ public void Should_return_version_from_a_cs_file_with_specflow_version()
+ {
+ var testHeaderWriter = CreateTestHeaderWriter();
+ var result = testHeaderWriter.DetectGeneratedTestVersion(@"// ------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by SpecFlow (http://www.specflow.org/).
+// SpecFlow Version:1.6.0.0
+// Runtime Version:4.0.30319.225
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+// ------------------------------------------------------------------------------
+#region Designer generated code
+namespace Bowling.Specflow
+{
+}
+#endregion
+");
+
+ result.ShouldNotBeNull();
+ result.ToString().ShouldEqual("1.6.0.0");
+ }
+
+ [Test]
+ public void Should_return_null_from_other_files()
+ {
+ var testHeaderWriter = CreateTestHeaderWriter();
+ var result = testHeaderWriter.DetectGeneratedTestVersion(@"not-a-generated-file");
+
+ result.ShouldBeNull();
+ }
+ }
+}
View
79 IdeIntegration/IdeIntegration/GeneratorServices.cs
@@ -0,0 +1,79 @@
+using System;
+using TechTalk.SpecFlow.Generator;
+using TechTalk.SpecFlow.Generator.Interfaces;
+
+namespace TechTalk.SpecFlow.IdeIntegration
+{
+ public interface IGeneratorServices
+ {
+ void InvalidateConfiguration();
+ void InvalidateSettings();
+ ITestGenerator CreateTestGenerator();
+ }
+
+ public abstract class GeneratorServices : IGeneratorServices
+ {
+ private readonly bool enableConfigurationCache = true;
+ private readonly bool enableSettingsCache = true;
+ private SpecFlowConfigurationHolder configurationHolder = null;
+ private ProjectSettings projectSettings = null;
+
+ protected GeneratorServices(bool enableConfigurationCache, bool enableSettingsCache)
+ {
+ this.enableConfigurationCache = enableConfigurationCache;
+ this.enableSettingsCache = enableSettingsCache;
+ }
+
+ public void InvalidateConfiguration()
+ {
+ configurationHolder = null;
+ }
+
+ public void InvalidateSettings()
+ {
+ projectSettings = null;
+ }
+
+ protected abstract SpecFlowConfigurationHolder GetConfigurationHolder();
+ protected abstract ProjectSettings GetProjectSettings();
+
+ private SpecFlowConfigurationHolder GetConfigurationHolderCached()
+ {
+ if (!enableConfigurationCache)
+ return GetConfigurationHolder();
+
+ var result = configurationHolder;
+
+ if (result == null)
+ configurationHolder = result = GetConfigurationHolder();
+
+ return result;
+ }
+
+ private ProjectSettings GetProjectSettingsCached()
+ {
+ if (!enableSettingsCache)
+ return GetProjectSettings();
+
+ var result = projectSettings;
+
+ if (result == null)
+ projectSettings = result = GetProjectSettings();
+
+ return result;
+ }
+
+ private ITestGeneratorFactory GetTestGeneratorFactory()
+ {
+ //TODO: create it in new AppDomain if neccessary
+ return new TestGeneratorFactory();
+ }
+
+ public ITestGenerator CreateTestGenerator()
+ {
+ var testGeneratorFactory = GetTestGeneratorFactory();
+
+ return testGeneratorFactory.CreateGenerator(GetConfigurationHolderCached(), GetProjectSettingsCached());
+ }
+ }
+}
View
14 IdeIntegration/IdeIntegration/Properties/AssemblyInfo.cs
@@ -0,0 +1,14 @@
+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("IdeIntegration")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("cc8b7d62-50d3-4816-9c05-32ade055bd3e")]
+
View
67 IdeIntegration/IdeIntegration/TechTalk.SpecFlow.IdeIntegration.csproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{44D52C1B-0ABC-44B6-8EB8-0F754E264226}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>TechTalk.SpecFlow.IdeIntegration</RootNamespace>
+ <AssemblyName>TechTalk.SpecFlow.IdeIntegration</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\..\specflow.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\CommonAssemblyInfo.cs">
+ <Link>Properties\CommonAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\..\VersionInfo.cs">
+ <Link>Properties\VersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="GeneratorServices.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Generator\TechTalk.SpecFlow.Generator.csproj">
+ <Project>{453D8014-B6CD-4E86-80A8-D59F59092334}</Project>
+ <Name>TechTalk.SpecFlow.Generator</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
56 IdeIntegration/Vs2010Integration/Generator/VsGeneratorServices.cs
@@ -0,0 +1,56 @@
+using System;
+using EnvDTE;
+using TechTalk.SpecFlow.Generator;
+using TechTalk.SpecFlow.Generator.Interfaces;
+using TechTalk.SpecFlow.IdeIntegration;
+using TechTalk.SpecFlow.Vs2010Integration.LanguageService;
+using TechTalk.SpecFlow.Vs2010Integration.Utils;
+
+namespace TechTalk.SpecFlow.Vs2010Integration.Generator
+{
+ internal class VsGeneratorServices : GeneratorServices
+ {
+ private readonly Project project;
+
+ public VsGeneratorServices(Project project) : base(true, false)
+ {
+ this.project = project;
+ }
+
+ protected override SpecFlowConfigurationHolder GetConfigurationHolder()
+ {
+ return DteProjectReader.LoadConfigHolderFromProject(project);
+ }
+
+ protected override ProjectSettings GetProjectSettings()
+ {
+ ProjectPlatformSettings projectPlatformSettings;
+ var tergetLanguage = VsProjectScope.GetTargetLanguage(project);
+ switch (tergetLanguage)
+ {
+ case ProgrammingLanguage.CSharp:
+ projectPlatformSettings = new ProjectPlatformSettings
+ {
+ Language = GenerationTargetLanguage.CSharp,
+ LanguageVersion = new Version("3.0"),
+ Platform = GenerationTargetPlatform.DotNet,
+ PlatformVersion = new Version("3.5"),
+ };
+ break;
+ case ProgrammingLanguage.VB:
+ projectPlatformSettings = new ProjectPlatformSettings
+ {
+ Language = GenerationTargetLanguage.VB,
+ LanguageVersion = new Version("9.0"),
+ Platform = GenerationTargetPlatform.DotNet,
+ PlatformVersion = new Version("3.5"),
+ };
+ break;
+ default:
+ throw new NotSupportedException("target language not supported");
+ }
+
+ return new ProjectSettings(VsxHelper.GetProjectFolder(project), VsxHelper.GetProjectDefaultNamespace(project), projectPlatformSettings);
+ }
+ }
+}
View
6 IdeIntegration/Vs2010Integration/LanguageService/NoProjectScope.cs
@@ -1,6 +1,7 @@
using System;
using TechTalk.SpecFlow.BindingSkeletons;
using TechTalk.SpecFlow.Generator.Configuration;
+using TechTalk.SpecFlow.IdeIntegration;
using TechTalk.SpecFlow.Parser;
using TechTalk.SpecFlow.Bindings;
using TechTalk.SpecFlow.Vs2010Integration.GherkinFileEditor;
@@ -41,6 +42,11 @@ public IStepDefinitionSkeletonProvider StepDefinitionSkeletonProvider
get { return null; }
}
+ public IGeneratorServices GeneratorServices
+ {
+ get { return null; }
+ }
+
public NoProjectScope(GherkinFileEditorClassifications classifications, IVisualStudioTracer visualStudioTracer, IIntegrationOptionsProvider integrationOptionsProvider)
{
GherkinTextBufferParser = new GherkinTextBufferParser(this, visualStudioTracer);
View
10 IdeIntegration/Vs2010Integration/LanguageService/ProjectFeatureFilesTracker.cs
@@ -5,6 +5,7 @@
using System.Linq;
using EnvDTE;
using TechTalk.SpecFlow.Generator;
+using TechTalk.SpecFlow.Generator.Interfaces;
using TechTalk.SpecFlow.Parser;
using TechTalk.SpecFlow.Parser.SyntaxElements;
using TechTalk.SpecFlow.Vs2010Integration.Utils;
@@ -94,7 +95,14 @@ private void AnalyzeCodeBehind(FeatureFileInfo featureFileInfo, ProjectItem proj
if (codeBehindItem != null)
{
string codeBehind = VsxHelper.GetFileContent(codeBehindItem);
- featureFileInfo.GeneratorVersion = SpecFlowGenerator.GetGeneratedFileSpecFlowVersion(new StringReader(codeBehind));
+ using (var testGenerator = vsProjectScope.GeneratorServices.CreateTestGenerator())
+ {
+ featureFileInfo.GeneratorVersion = testGenerator.DetectGeneratedTestVersion(
+ new FeatureFileInput(featureFileInfo.ProjectRelativePath)
+ {
+ GeneratedTestFileContent = codeBehind
+ });
+ }
}
}
View
2 IdeIntegration/Vs2010Integration/LanguageService/ProjectScope.cs
@@ -1,6 +1,7 @@
using System;
using TechTalk.SpecFlow.BindingSkeletons;
using TechTalk.SpecFlow.Generator.Configuration;
+using TechTalk.SpecFlow.IdeIntegration;
using TechTalk.SpecFlow.Parser;
using TechTalk.SpecFlow.Bindings;
using TechTalk.SpecFlow.Vs2010Integration.GherkinFileEditor;
@@ -20,6 +21,7 @@ public interface IProjectScope : IDisposable
IBindingMatchService BindingMatchService { get; }
IStepDefinitionSkeletonProvider StepDefinitionSkeletonProvider { get; }
IIntegrationOptionsProvider IntegrationOptionsProvider { get; }
+ IGeneratorServices GeneratorServices { get; }
event EventHandler SpecFlowProjectConfigurationChanged;
event EventHandler GherkinDialectServicesChanged;
View
7 IdeIntegration/Vs2010Integration/LanguageService/VsProjectScope.cs
@@ -4,8 +4,10 @@
using EnvDTE;
using TechTalk.SpecFlow.BindingSkeletons;
using TechTalk.SpecFlow.Generator.Configuration;
+using TechTalk.SpecFlow.IdeIntegration;
using TechTalk.SpecFlow.Parser;
using TechTalk.SpecFlow.Bindings;
+using TechTalk.SpecFlow.Vs2010Integration.Generator;
using TechTalk.SpecFlow.Vs2010Integration.GherkinFileEditor;
using TechTalk.SpecFlow.Vs2010Integration.Options;
using TechTalk.SpecFlow.Vs2010Integration.Tracing;
@@ -24,6 +26,7 @@ public class VsProjectScope : IProjectScope
private readonly GherkinScopeAnalyzer analyzer = null;
public GherkinFileEditorClassifications Classifications { get; private set; }
public GherkinProcessingScheduler GherkinProcessingScheduler { get; private set; }
+ public IGeneratorServices GeneratorServices { get; private set; }
private bool initialized = false;
@@ -124,6 +127,8 @@ internal VsProjectScope(Project project, DteWithEvents dteWithEvents, GherkinFil
// analyzer = new GherkinScopeAnalyzer(this, visualStudioTracer);
GherkinProcessingScheduler = new GherkinProcessingScheduler(visualStudioTracer, integrationOptions.EnableAnalysis);
+
+ GeneratorServices = new VsGeneratorServices(project);
}
private void EnsureInitialized()
@@ -248,6 +253,8 @@ private void OnSpecFlowProjectConfigurationChanged()
if (SpecFlowProjectConfigurationChanged != null)
SpecFlowProjectConfigurationChanged(this, EventArgs.Empty);
+ GeneratorServices.InvalidateConfiguration();
+
ConfirmReGenerateFilesOnConfigChange();
}
View
17 IdeIntegration/Vs2010Integration/Properties/AssemblyInfo.cs
@@ -1,27 +1,12 @@
using System;
using System.Reflection;
-using System.Resources;
-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("GherkinFileClassifier")]
+[assembly: AssemblyTitle("TechTalk.SpecFlow.Vs2010Integration")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("GherkinFileClassifier")]
-[assembly: AssemblyCopyright("")]
-[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)]
-[assembly: CLSCompliant(false)]
-[assembly: NeutralResourcesLanguage("en-US")]
// Version information for an assembly consists of the following four values:
//
View
70 IdeIntegration/Vs2010Integration/SingleFileGenerator/SpecFlowSingleFileGenerator.cs
@@ -2,12 +2,10 @@
using System.CodeDom.Compiler;
using System.IO;
using System.Runtime.InteropServices;
-using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
-using TechTalk.SpecFlow.Generator;
using TechTalk.SpecFlow.Generator.Interfaces;
-using TechTalk.SpecFlow.Vs2010Integration.LanguageService;
+using TechTalk.SpecFlow.Vs2010Integration.Generator;
using TechTalk.SpecFlow.Vs2010Integration.Tracing;
using TechTalk.SpecFlow.Vs2010Integration.Utils;
using TechTalk.SpecFlow.VsIntegration.Common;
@@ -36,34 +34,27 @@ protected override void RefreshMsTestWindow()
//the automatic refresh of the test window causes problems in VS2010 -> skip
}
- private ITestGeneratorFactory GetTestGeneratorFactory()
- {
- //TODO: create it in new AppDomain if neccessary
- return new TestGeneratorFactory();
- }
-
private TestGeneratorResult generationResult = null;
protected override string GenerateCode(string inputFileContent)
{
- ITestGeneratorFactory testGeneratorFactory = GetTestGeneratorFactory();
-
- var configHolder = DteProjectReader.LoadConfigHolderFromProject(CurrentProject);
- var testGenerator = testGeneratorFactory.CreateGenerator(configHolder);
+ var generatorServices = new VsGeneratorServices(CurrentProject);
- string projectFolder = VsxHelper.GetProjectFolder(CurrentProject);
- var fullPath = Path.GetFullPath(Path.Combine(projectFolder, CodeFilePath));
- FeatureFileInput featureFileInput =
- new FeatureFileInput(fullPath,
- FileSystemHelper.GetRelativePath(fullPath, projectFolder),
- null, //TODO
- new StringReader(inputFileContent));
-
- generationResult = testGenerator.GenerateTestFile(featureFileInput, GetGeneratorSettings(CurrentProject));
- if (!generationResult.Success)
- return null;
+ using (var testGenerator = generatorServices.CreateTestGenerator())
+ {
+ string projectFolder = VsxHelper.GetProjectFolder(CurrentProject);
+ var fullPath = Path.GetFullPath(Path.Combine(projectFolder, CodeFilePath));
+ FeatureFileInput featureFileInput =
+ new FeatureFileInput(FileSystemHelper.GetRelativePath(fullPath, projectFolder))
+ {
+ FeatureFileContent = inputFileContent
+ };
+ generationResult = testGenerator.GenerateTestFile(featureFileInput, new GenerationSettings());
+ if (!generationResult.Success)
+ return null;
- return generationResult.GeneratedTestCode;
+ return generationResult.GeneratedTestCode;
+ }
}
protected override string GenerateError(IVsGeneratorProgress pGenerateProgress, Exception ex)
@@ -82,34 +73,5 @@ protected override string GenerateError(IVsGeneratorProgress pGenerateProgress,
}
return base.GenerateError(pGenerateProgress, ex);
}
-
-
- private GenerationSettings GetGeneratorSettings(Project project)
- {
- var tergetLanguage = VsProjectScope.GetTargetLanguage(CurrentProject);
- switch (tergetLanguage)
- {
- case ProgrammingLanguage.CSharp:
- return new GenerationSettings
- {
- TargetLanguage = Generator.GenerationTargetLanguage.CSharp,
- TargetLanguageVersion = new Version("3.0"),
- TargetPlatform = GenerationTargetPlatform.DotNet,
- TargetPlatformVersion = new Version("3.5"),
- ProjectDefaultNamespace = VsxHelper.GetProjectDefaultNamespace(project)
- };
- case ProgrammingLanguage.VB:
- return new GenerationSettings
- {
- TargetLanguage = Generator.GenerationTargetLanguage.VB,
- TargetLanguageVersion = new Version("9.0"),
- TargetPlatform = GenerationTargetPlatform.DotNet,
- TargetPlatformVersion = new Version("3.5"),
- ProjectDefaultNamespace = VsxHelper.GetProjectDefaultNamespace(project)
- };
- default:
- throw new NotSupportedException("target language not supported");
- }
- }
}
}
View
8 IdeIntegration/Vs2010Integration/TechTalk.SpecFlow.Vs2010Integration.csproj
@@ -159,6 +159,9 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\..\CommonAssemblyInfo.cs">
+ <Link>CommonAssemblyInfo.cs</Link>
+ </Compile>
<Compile Include="..\..\Runtime\ProgrammingLanguage.cs">
<Link>BindingSkeletons\ProgrammingLanguage.cs</Link>
</Compile>
@@ -210,6 +213,7 @@
<Compile Include="LanguageService\GherkinBufferServiceManager.cs" />
<Compile Include="LanguageService\NoProjectScope.cs" />
<Compile Include="LanguageService\VsProjectScope.cs" />
+ <Compile Include="Generator\VsGeneratorServices.cs" />
<Compile Include="StepSuggestions\BoundStepSuggestions.cs" />
<Compile Include="StepSuggestions\INativeSuggestionItemFactory.cs" />
<Compile Include="StepSuggestions\IStepSuggestion.cs" />
@@ -325,6 +329,10 @@
<Project>{C0AF4A43-0C3B-47C7-86DE-79FB632B1453}</Project>
<Name>TechTalk.SpecFlow.Utils</Name>
</ProjectReference>
+ <ProjectReference Include="..\IdeIntegration\TechTalk.SpecFlow.IdeIntegration.csproj">
+ <Project>{44D52C1B-0ABC-44B6-8EB8-0F754E264226}</Project>
+ <Name>TechTalk.SpecFlow.IdeIntegration</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
View
22 TechTalk.SpecFlow.sln
@@ -89,6 +89,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{605573AA
IdeIntegration\NuGetIntegration\SpecFlow.nuspec = IdeIntegration\NuGetIntegration\SpecFlow.nuspec
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TechTalk.SpecFlow.IdeIntegration", "IdeIntegration\IdeIntegration\TechTalk.SpecFlow.IdeIntegration.csproj", "{44D52C1B-0ABC-44B6-8EB8-0F754E264226}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -412,8 +414,8 @@ Global
{97C30FCC-3093-4430-93DC-D671C656C404}.Release|x86.ActiveCfg = Release|Any CPU
{97C30FCC-3093-4430-93DC-D671C656C404}.VS2010IntegrationTest|Any CPU.ActiveCfg = Release|Any CPU
{97C30FCC-3093-4430-93DC-D671C656C404}.VS2010IntegrationTest|Any CPU.Build.0 = Release|Any CPU
- {97C30FCC-3093-4430-93DC-D671C656C404}.VS2010IntegrationTest|Mixed Platforms.ActiveCfg = Release|Any CPU
- {97C30FCC-3093-4430-93DC-D671C656C404}.VS2010IntegrationTest|Mixed Platforms.Build.0 = Release|Any CPU
+ {97C30FCC-3093-4430-93DC-D671C656C404}.VS2010IntegrationTest|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {97C30FCC-3093-4430-93DC-D671C656C404}.VS2010IntegrationTest|Mixed Platforms.Build.0 = Debug|Any CPU
{97C30FCC-3093-4430-93DC-D671C656C404}.VS2010IntegrationTest|x86.ActiveCfg = Release|Any CPU
{E00271E7-F422-42B9-89D0-E29C96C90CE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E00271E7-F422-42B9-89D0-E29C96C90CE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -430,6 +432,21 @@ Global
{E00271E7-F422-42B9-89D0-E29C96C90CE2}.VS2010IntegrationTest|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E00271E7-F422-42B9-89D0-E29C96C90CE2}.VS2010IntegrationTest|Mixed Platforms.Build.0 = Debug|Any CPU
{E00271E7-F422-42B9-89D0-E29C96C90CE2}.VS2010IntegrationTest|x86.ActiveCfg = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Release|Any CPU.Build.0 = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.Release|x86.ActiveCfg = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.VS2010IntegrationTest|Any CPU.ActiveCfg = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.VS2010IntegrationTest|Any CPU.Build.0 = Release|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.VS2010IntegrationTest|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.VS2010IntegrationTest|Mixed Platforms.Build.0 = Debug|Any CPU
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226}.VS2010IntegrationTest|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -453,5 +470,6 @@ Global
{199D2315-F5BD-463C-B16A-BE31A845792B} = {55E45533-9AAA-41AB-B44F-7530799C9337}
{96294E6F-8875-4D12-8577-4EC83E60BD6C} = {55E45533-9AAA-41AB-B44F-7530799C9337}
{605573AA-9C90-442B-B54B-1243A36A3E18} = {55E45533-9AAA-41AB-B44F-7530799C9337}
+ {44D52C1B-0ABC-44B6-8EB8-0F754E264226} = {55E45533-9AAA-41AB-B44F-7530799C9337}
EndGlobalSection
EndGlobal
View
1 Utils/TechTalk.SpecFlow.Utils.csproj
@@ -48,6 +48,7 @@
<Compile Include="CodeDomProviderLanguage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RegexSampler.cs" />
+ <Compile Include="TempFile.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
View
73 Utils/TempFile.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace TechTalk.SpecFlow.Utils
+{
+ // this class is based on the class found at http://www.vcskicks.com/code-snippet/temp-file-class.php
+
+ public class TempFile : IDisposable
+ {
+ private readonly string _tmpfile;
+
+ public TempFile()
+ : this(string.Empty)
+ { }
+
+ public TempFile(string extension)
+ {
+ _tmpfile = Path.GetTempFileName();
+ if (!string.IsNullOrEmpty(extension))
+ {
+ string newTmpFile = _tmpfile + extension;
+
+ // create tmp-File with new extension ...
+ File.Create(newTmpFile).Dispose();
+ // delete old tmp-File
+ File.Delete(_tmpfile);
+
+ // use new tmp-File
+ _tmpfile = newTmpFile;
+ }
+ }
+
+ public void SetContent(string fileContent)
+ {
+ using (StreamWriter writer = new StreamWriter(FullPath, false, Encoding.UTF8))
+ {
+ writer.Write(fileContent);
+ }
+ }
+
+ public string FullPath
+ {
+ get { return _tmpfile; }
+ }
+
+ public string FileName
+ {
+ get { return Path.GetFileName(FullPath); }
+ }
+
+ public string FolderName
+ {
+ get { return Path.GetDirectoryName(FullPath); }
+ }
+
+ void IDisposable.Dispose()
+ {
+ try
+ {
+ if (!string.IsNullOrEmpty(_tmpfile) && File.Exists(_tmpfile))
+ File.Delete(_tmpfile);
+ }
+ catch(Exception ex)
+ {
+ Debug.WriteLine(ex, "TempFile.Dispose");
+ }
+ }
+ }
+}
View
46 lib/MiniDi/MiniDi.cs
@@ -27,22 +27,22 @@ namespace MiniDi
[Serializable]
public class ObjectContainerException : Exception
{
- public ObjectContainerException()
+ public ObjectContainerException(string message, IEnumerable<Type> resolutionPath) : base(GetMessage(message, resolutionPath))
{
}
- public ObjectContainerException(string message) : base(message)
+ protected ObjectContainerException(
+ SerializationInfo info,
+ StreamingContext context) : base(info, context)
{
}
- public ObjectContainerException(string message, Exception inner) : base(message, inner)
+ static private string GetMessage(string message, IEnumerable<Type> resolutionPath)
{
- }
+ if (resolutionPath == null || !resolutionPath.Any())
+ return message;
- protected ObjectContainerException(
- SerializationInfo info,
- StreamingContext context) : base(info, context)
- {
+ return string.Format("{0} (resolution path: {1})", message, string.Join("->", resolutionPath.Select(t => t.FullName).ToArray()));
}
}
@@ -131,7 +131,7 @@ private void RegisterTypeAs(Type implementationType, Type interfaceType)
private void AssertNotResolved(Type interfaceType)
{
if (resolvedObjects.ContainsKey(interfaceType))
- throw new ObjectContainerException("An object have been resolved for this interface already.");
+ throw new ObjectContainerException("An object have been resolved for this interface already.", null);
}
private void ClearRegistrations(Type interfaceType)
@@ -183,10 +183,15 @@ public T Resolve<T>()
private object Resolve(Type typeToResolve)
{
+ return Resolve(typeToResolve, Enumerable.Empty<Type>());
+ }
+
+ private object Resolve(Type typeToResolve, IEnumerable<Type> resolutionPath)
+ {
object resolvedObject;
if (!resolvedObjects.TryGetValue(typeToResolve, out resolvedObject))
{
- resolvedObject = CreateObjectFor(typeToResolve);
+ resolvedObject = CreateObjectFor(typeToResolve, resolutionPath);
resolvedObjects.Add(typeToResolve, resolvedObject);
}
Debug.Assert(typeToResolve.IsInstanceOfType(resolvedObject));
@@ -246,8 +251,11 @@ private object GetPooledObject(Type registeredType)
return null;
}
- private object CreateObjectFor(Type typeToResolve)
+ private object CreateObjectFor(Type typeToResolve, IEnumerable<Type> resolutionPath)
{
+ if (typeToResolve.IsPrimitive || typeToResolve == typeof(string))
+ throw new ObjectContainerException("Primitive types cannot be resolved: " + typeToResolve.FullName, resolutionPath);
+
var registrationResult = GetRegistrationResult(typeToResolve);
if (registrationResult != null && registrationResult.IsInstanceRegistration)
@@ -264,41 +272,41 @@ private object CreateObjectFor(Type typeToResolve)
if (obj == null)
{
if (registeredType.IsInterface)
- throw new ObjectContainerException("Interface cannot be resolved: " + typeToResolve.FullName);
+ throw new ObjectContainerException("Interface cannot be resolved: " + typeToResolve.FullName, resolutionPath);
- obj = CreateObject(registeredType);
+ obj = CreateObject(registeredType, resolutionPath);
objectPool.Add(registeredType, obj);
}
return obj;
}
- private object CreateObject(Type type)
+ private object CreateObject(Type type, IEnumerable<Type> resolutionPath)
{
var ctors = type.GetConstructors();
object obj;
if (ctors.Length == 1)
{
ConstructorInfo ctor = ctors[0];
- var args = ResolveArguments(ctor.GetParameters());
+ var args = ResolveArguments(ctor.GetParameters(), resolutionPath.Concat(new[] { type }));
obj = ctor.Invoke(args);
}
else if (ctors.Length == 0)
{
- throw new ObjectContainerException("Class must have a public constructor! " + type.FullName);
+ throw new ObjectContainerException("Class must have a public constructor! " + type.FullName, resolutionPath);
}
else
{
- throw new ObjectContainerException("Multiple public constructors are not supported! " + type.FullName);
+ throw new ObjectContainerException("Multiple public constructors are not supported! " + type.FullName, resolutionPath);
}
return obj;
}
- private object[] ResolveArguments(IEnumerable<ParameterInfo> parameters)
+ private object[] ResolveArguments(IEnumerable<ParameterInfo> parameters, IEnumerable<Type> resolutionPath)
{
- return parameters.Select(p => Resolve(p.ParameterType)).ToArray();
+ return parameters.Select(p => Resolve(p.ParameterType, resolutionPath)).ToArray();
}
#endregion

0 comments on commit 46ac55f

Please sign in to comment.