diff --git a/Installer/ImportGherkinParser/Program.cs b/Installer/ImportGherkinParser/Program.cs index 3eef643d8..ed15f0f1a 100644 --- a/Installer/ImportGherkinParser/Program.cs +++ b/Installer/ImportGherkinParser/Program.cs @@ -92,6 +92,7 @@ private static void CreateSignedParser(string gherkinParserFullPath, Version ver new Dictionary() { {"se", "sv"}, + {"lu", "lb-LU"}, }; private class KeywordTranslation diff --git a/Languages.xml b/Languages.xml index 49511835a..f04357e95 100644 --- a/Languages.xml +++ b/Languages.xml @@ -219,8 +219,11 @@ Forgatókönyv Forgatókönyv vázlat Példák - Ha + Amennyiben + Adott Majd + Ha + Amikor Akkor És De @@ -250,8 +253,11 @@ Forgatókönyv Forgatókönyv vázlat Példák - Ha + Amennyiben + Adott Majd + Ha + Amikor Akkor És De @@ -262,8 +268,11 @@ Forgatókönyv Forgatókönyv vázlat Példák - Ha + Amennyiben + Adott Majd + Ha + Amikor Akkor És De @@ -328,6 +337,20 @@ Ir Bet + + Funktionalitéit + Hannergrond + Szenario + Plang vum Szenario + Beispiller + ugeholl + wann + dann + an + a + awer + + Funkcionalitāte Fīča @@ -427,8 +450,12 @@ Структура сценария Значения Допустим + Дано + Пусть Если + Когда То + Тогда И К тому же Но @@ -452,8 +479,11 @@ Forgatókönyv Forgatókönyv vázlat Példák - Ha + Amennyiben + Adott Majd + Ha + Amikor Akkor És De @@ -464,8 +494,11 @@ Forgatókönyv Forgatókönyv vázlat Példák - Ha + Amennyiben + Adott Majd + Ha + Amikor Akkor És De @@ -504,9 +537,14 @@ Припустимо Припустимо, що Нехай + Дано Якщо + Коли То + Тоді І + А також + Та Але diff --git a/Parser/GherkinBuilder/BackgroundBuilder.cs b/Parser/GherkinBuilder/BackgroundBuilder.cs index 08996185e..ac1170a37 100644 --- a/Parser/GherkinBuilder/BackgroundBuilder.cs +++ b/Parser/GherkinBuilder/BackgroundBuilder.cs @@ -10,9 +10,9 @@ internal class BackgroundBuilder : IStepProcessor private readonly FilePosition position; private readonly IList steps = new List(); - public BackgroundBuilder(string text, FilePosition position) + public BackgroundBuilder(string name, string description, FilePosition position) { - this.text = text; + this.text = TextHelper.GetText(name, description); this.position = position; } diff --git a/Parser/GherkinBuilder/ExampleBuilder.cs b/Parser/GherkinBuilder/ExampleBuilder.cs index 23eefe135..1e077bca9 100644 --- a/Parser/GherkinBuilder/ExampleBuilder.cs +++ b/Parser/GherkinBuilder/ExampleBuilder.cs @@ -11,9 +11,9 @@ internal class ExampleBuilder : ITableProcessor private readonly FilePosition position; private readonly TableBuilder tableBuilder = new TableBuilder(); - public ExampleBuilder(string text, FilePosition position) + public ExampleBuilder(string name, string description, FilePosition position) { - this.text = text; + this.text = TextHelper.GetText(name, description); this.position = position; } diff --git a/Parser/GherkinBuilder/FeatureBuilder.cs b/Parser/GherkinBuilder/FeatureBuilder.cs index a6f41d9ba..a6ef6c73e 100644 --- a/Parser/GherkinBuilder/FeatureBuilder.cs +++ b/Parser/GherkinBuilder/FeatureBuilder.cs @@ -1,43 +1,41 @@ using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using TechTalk.SpecFlow.Parser.SyntaxElements; namespace TechTalk.SpecFlow.Parser.GherkinBuilder { internal class FeatureBuilder { - private readonly string text; - private readonly Tags tags; + private string title; + private string description; + private string sourceFilePath; + private Tags tags; private readonly IList scenarios = new List(); private BackgroundBuilder background = null; - public FeatureBuilder(string text, Tags tags) + public string SourceFilePath { - this.text = text; - this.tags = tags; + get { return sourceFilePath; } + set { sourceFilePath = value; } } - private static readonly Regex firstLineRe = new Regex(@"^(?[^\r\n]*)[\r\n]+(?.*)", RegexOptions.Singleline); + public void SetHeader(string title, string description, Tags tags) + { + this.title = title; + this.description = description; + this.tags = tags; + } public Feature GetResult() { - string title = text; - string description = null; - - var match = firstLineRe.Match(text); - if (match.Success) - { - title = match.Groups["firstline"].Value; - description = match.Groups["rest"].Value; - } - - return new Feature( + var feature = new Feature( title, tags, description, background == null ? null : background.GetResult(), scenarios.Select(sb => sb.GetResult()).ToArray()); + feature.SourceFile = sourceFilePath; + return feature; } public void AddScenario(IScenarioBuilder scenarioBuilder) diff --git a/Parser/GherkinBuilder/GherkinListener.cs b/Parser/GherkinBuilder/GherkinListener.cs index b6c874906..16703fa28 100644 --- a/Parser/GherkinBuilder/GherkinListener.cs +++ b/Parser/GherkinBuilder/GherkinListener.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.Linq; using gherkin; using java.util; @@ -13,7 +12,7 @@ internal class GherkinListener : Listener { public GherkinListener(I18n languageService) { - _i18n = languageService; + i18n = languageService; Errors = new List(); } @@ -32,7 +31,8 @@ public void RegisterError(ErrorDetail errorDetail) Errors.Add(errorDetail); } - private FeatureBuilder featureBuilder; + private readonly FeatureBuilder featureBuilder = new FeatureBuilder(); + public Feature GetResult() { return featureBuilder.GetResult(); @@ -49,7 +49,7 @@ private Tags FlushTags() private IStepProcessor stepProcessor; private ITableProcessor tableProcessor; private IExampleProcessor exampleProcessor; - private I18n _i18n; + private readonly I18n i18n; public void tag(string name, int i) { @@ -57,59 +57,64 @@ public void tag(string name, int i) tags.Add(new Tag(nameWithoutAt)); } - public void comment(string str, int i) + public void comment(string comment, int line) + { + } + + public void location(string uri, int offset) { + featureBuilder.SourceFilePath = uri; } - public void feature(string keyword, string content, int line_number) + public void feature(string keyword, string name, string description, int line) { - featureBuilder = new FeatureBuilder(content, FlushTags()); + featureBuilder.SetHeader(name, description, FlushTags()); } - public void background(string keyword, string content, int line_number) + public void background(string keyword, string name, string description, int line) { - var background = new BackgroundBuilder(content, new FilePosition(line_number, 1)); + var background = new BackgroundBuilder(name, description, new FilePosition(line)); stepProcessor = background; featureBuilder.AddBackground(background); } - public void scenario(string keyword, string content, int line_number) + public void scenario(string keyword, string name, string description, int line) { - var currentScenario = new ScenarioBuilder(content, FlushTags(), new FilePosition(line_number, 1)); + var currentScenario = new ScenarioBuilder(name, description, FlushTags(), new FilePosition(line)); stepProcessor = currentScenario; featureBuilder.AddScenario(currentScenario); } - public void scenarioOutline(string keyword, string content, int line_number) + public void scenarioOutline(string keyword, string name, string description, int line) { - var currentScenario = new ScenarioOutlineBuilder(content, FlushTags(), new FilePosition(line_number, 1)); + var currentScenario = new ScenarioOutlineBuilder(name, description, FlushTags(), new FilePosition(line)); stepProcessor = currentScenario; exampleProcessor = currentScenario; featureBuilder.AddScenario(currentScenario); } - public void examples(string keyword, string content, int line_number) + public void examples(string keyword, string name, string description, int line) { - var exampleBuilder = new ExampleBuilder(content, new FilePosition(line_number, 1)); + var exampleBuilder = new ExampleBuilder(name, description, new FilePosition(line)); tableProcessor = exampleBuilder; exampleProcessor.ProcessExample(exampleBuilder); } - public void step(string keyword, string content, int line_number) + public void step(string keyword, string text, int line) { - stepBuilder = new StepBuilder(keyword, content, new FilePosition(line_number, 1), _i18n); + stepBuilder = new StepBuilder(keyword, text, new FilePosition(line), i18n); tableProcessor = stepBuilder; stepProcessor.ProcessStep(stepBuilder); } - public void row(List list, int line_number) + public void row(List list, int line) { string[] rows = new string[list.size()]; list.toArray(rows); - tableProcessor.ProcessTableRow(rows, line_number); + tableProcessor.ProcessTableRow(rows, line); } - public void pyString(string content, int line_number) + public void pyString(string content, int line) { stepBuilder.SetMultilineArg(content); } @@ -119,12 +124,11 @@ public void eof() } - public void syntaxError(string str1, string str2, List l, int line_number) + public void syntaxError(string state, string eventName, List legalEvents, int line) { - string message = "Parse error. Found " + str1 + " when expecting one of: " + - "TODO" + ". (Current state: " + str2 + ")."; + string message = string.Format("Parser error on line {2}. State: {0}, Event: {1}", state, eventName, line); - RegisterError(line_number, null, message); + RegisterError(line, null, message); } } } diff --git a/Parser/GherkinBuilder/ScenarioBuilder.cs b/Parser/GherkinBuilder/ScenarioBuilder.cs index 5a6f6b2b2..af9442b97 100644 --- a/Parser/GherkinBuilder/ScenarioBuilder.cs +++ b/Parser/GherkinBuilder/ScenarioBuilder.cs @@ -6,14 +6,14 @@ namespace TechTalk.SpecFlow.Parser.GherkinBuilder { internal class ScenarioBuilder : IScenarioBuilder { - private readonly string name; + private readonly string title; private readonly FilePosition position; private readonly Tags tags; private readonly IList steps = new List(); - public ScenarioBuilder(string name, Tags tags, FilePosition position) + public ScenarioBuilder(string name, string description, Tags tags, FilePosition position) { - this.name = name; + this.title = TextHelper.GetText(name, description); this.position = position; this.tags = tags; } @@ -25,7 +25,7 @@ public void ProcessStep(StepBuilder step) public Scenario GetResult() { - return new Scenario(name, tags, new ScenarioSteps(steps.Select(s => s.GetResult()).ToArray())) { FilePosition = position }; + return new Scenario(title, tags, new ScenarioSteps(steps.Select(s => s.GetResult()).ToArray())) { FilePosition = position }; } } } \ No newline at end of file diff --git a/Parser/GherkinBuilder/ScenarioOutlineBuilder.cs b/Parser/GherkinBuilder/ScenarioOutlineBuilder.cs index f25e694b4..be423e443 100644 --- a/Parser/GherkinBuilder/ScenarioOutlineBuilder.cs +++ b/Parser/GherkinBuilder/ScenarioOutlineBuilder.cs @@ -7,15 +7,15 @@ namespace TechTalk.SpecFlow.Parser.GherkinBuilder { internal class ScenarioOutlineBuilder : IScenarioBuilder, IExampleProcessor { - private readonly string name; + private readonly string title; private readonly Tags tags; private readonly FilePosition position; private readonly IList steps = new List(); private readonly IList examples = new List(); - public ScenarioOutlineBuilder(string name, Tags tags, FilePosition position) + public ScenarioOutlineBuilder(string name, string description, Tags tags, FilePosition position) { - this.name = name; + this.title = TextHelper.GetText(name, description); this.tags = tags; this.position = position; } @@ -37,7 +37,7 @@ public Scenario GetResult() }); return new ScenarioOutline( - name, + title, tags, new ScenarioSteps(steps.Select(step => step.GetResult()).ToArray()), new Examples(examples.Select(example => example.GetResult()).ToArray())) { FilePosition = position }; diff --git a/Parser/GherkinBuilder/TableBuilder.cs b/Parser/GherkinBuilder/TableBuilder.cs index 75183bad0..4bdd46ab0 100644 --- a/Parser/GherkinBuilder/TableBuilder.cs +++ b/Parser/GherkinBuilder/TableBuilder.cs @@ -17,7 +17,7 @@ public Table GetResult() public void ProcessTableRow(string[] cells, int lineNumber) { var row = new Row(cells.Select(c => new Cell(c)).ToArray()); - row.FilePosition = new FilePosition(lineNumber, 1); + row.FilePosition = new FilePosition(lineNumber); if (tableRows.Count > 0 && tableRows[0].Cells.Length != row.Cells.Length) { diff --git a/Parser/GherkinBuilder/TextHelper.cs b/Parser/GherkinBuilder/TextHelper.cs new file mode 100644 index 000000000..2ef7fa3cd --- /dev/null +++ b/Parser/GherkinBuilder/TextHelper.cs @@ -0,0 +1,15 @@ +using System; + +namespace TechTalk.SpecFlow.Parser.GherkinBuilder +{ + public static class TextHelper + { + public static string GetText(string name, string description) + { + if (string.IsNullOrEmpty(description)) + return name; + + return string.Concat(name, Environment.NewLine, description); + } + } +} \ No newline at end of file diff --git a/Parser/SpecFlowLangParser.cs b/Parser/SpecFlowLangParser.cs index 38714ea6f..b2a7bc015 100644 --- a/Parser/SpecFlowLangParser.cs +++ b/Parser/SpecFlowLangParser.cs @@ -22,14 +22,7 @@ public SpecFlowLangParser(CultureInfo defaultLanguage) this.defaultLanguage = defaultLanguage; } - public Feature Parse(TextReader featureFileReader, string sourceFileName) - { - var feature = Parse(featureFileReader); - feature.SourceFile = Path.GetFullPath(sourceFileName); - return feature; - } - - public Feature Parse(TextReader featureFileReader) + public Feature Parse(TextReader featureFileReader, string sourceFilePath) { var fileContent = featureFileReader.ReadToEnd(); @@ -37,7 +30,7 @@ public Feature Parse(TextReader featureFileReader) I18n languageService = new I18n(language.CompatibleGherkinLanguage ?? language.Language); var gherkinListener = new GherkinListener(languageService); - Feature feature = Parse(fileContent, gherkinListener, languageService); + Feature feature = Parse(fileContent, sourceFilePath, gherkinListener, languageService); if (gherkinListener.Errors.Count > 0) throw new SpecFlowParserException(gherkinListener.Errors); @@ -48,12 +41,12 @@ public Feature Parse(TextReader featureFileReader) return feature; } - private Feature Parse(string fileContent, GherkinListener gherkinListener, I18n languageService) + private Feature Parse(string fileContent, string sourceFilePath, GherkinListener gherkinListener, I18n languageService) { try { Lexer lexer = languageService.lexer(gherkinListener); - lexer.scan(fileContent); + lexer.scan(fileContent, sourceFilePath, 0); return gherkinListener.GetResult(); } catch(SpecFlowParserException specFlowParserException) diff --git a/Parser/SyntaxElements/FilePosition.cs b/Parser/SyntaxElements/FilePosition.cs index 5adb01439..5c1ca87a0 100644 --- a/Parser/SyntaxElements/FilePosition.cs +++ b/Parser/SyntaxElements/FilePosition.cs @@ -15,10 +15,15 @@ public FilePosition() { } + public FilePosition(int line) + : this(line, 1) // default if the colum is not specified/available + { + } + public FilePosition(int line, int column) { Line = line; - Column = column; //NOTE: this is always 1 now since it is not provided by gherkin... + Column = column; } } } \ No newline at end of file diff --git a/Parser/TechTalk.SpecFlow.Parser.csproj b/Parser/TechTalk.SpecFlow.Parser.csproj index fbe90559a..05968a9b7 100644 --- a/Parser/TechTalk.SpecFlow.Parser.csproj +++ b/Parser/TechTalk.SpecFlow.Parser.csproj @@ -79,6 +79,7 @@ + diff --git a/Tests/ParserTests/SuccessfulGenerationTest.cs b/Tests/ParserTests/SuccessfulGenerationTest.cs index fe82050e7..59d4db070 100644 --- a/Tests/ParserTests/SuccessfulGenerationTest.cs +++ b/Tests/ParserTests/SuccessfulGenerationTest.cs @@ -134,7 +134,7 @@ public void CanGenerateFromFile(string fileName) SpecFlowLangParser parser = new SpecFlowLangParser(new CultureInfo("en-US")); using (var reader = new StreamReader(fileName)) { - Feature feature = parser.Parse(reader); + Feature feature = parser.Parse(reader, null); Assert.IsNotNull(feature); string generatedCode = GenerateCodeFromFeature(feature); diff --git a/Tests/ParserTests/SuccessfulMbUnitGenerationTest.cs b/Tests/ParserTests/SuccessfulMbUnitGenerationTest.cs index ec2a39577..f9dd9c866 100644 --- a/Tests/ParserTests/SuccessfulMbUnitGenerationTest.cs +++ b/Tests/ParserTests/SuccessfulMbUnitGenerationTest.cs @@ -81,7 +81,7 @@ public void CanGenerateFromFile(string fileName) var parser = new SpecFlowLangParser(new CultureInfo("en-US")); using (var reader = new StreamReader(fileName)) { - Feature feature = parser.Parse(reader); + Feature feature = parser.Parse(reader, null); Assert.IsNotNull(feature); string generatedCode = GenerateCodeFromFeature(feature); diff --git a/Tests/ParserTests/SuccessfulParsingTest.cs b/Tests/ParserTests/SuccessfulParsingTest.cs index b84b6001b..402a04bbe 100644 --- a/Tests/ParserTests/SuccessfulParsingTest.cs +++ b/Tests/ParserTests/SuccessfulParsingTest.cs @@ -36,6 +36,13 @@ public void CanParseGermanFeature() CanParseFile(Path.Combine(folder, "german.feature")); } + [Test] + public void CanParseHungarianFeature() + { + var folder = Path.GetFullPath(Path.Combine(TestFileHelper.GetProjectLocation(), "TestFiles")); + CanParseFile(Path.Combine(folder, "hungarian.feature")); + } + [Test] public void CanParseSwedishFeature() { @@ -141,8 +148,11 @@ public void CanParseFile(string fileName) SpecFlowLangParser parser = new SpecFlowLangParser(new CultureInfo("en-US")); using (var reader = new StreamReader(fileName)) { - Feature feature = parser.Parse(reader); + Feature feature = parser.Parse(reader, fileName); Assert.IsNotNull(feature); + Assert.AreEqual(fileName, feature.SourceFile); + + feature.SourceFile = null; // cleanup source file to make the test run from other folders too // to regenerate the expected result file: //SerializeFeature(feature, fileName + ".xml"); diff --git a/Tests/ParserTests/SuccessfulXUnitGenerationTest.cs b/Tests/ParserTests/SuccessfulXUnitGenerationTest.cs index e3f313b97..d00d31c65 100644 --- a/Tests/ParserTests/SuccessfulXUnitGenerationTest.cs +++ b/Tests/ParserTests/SuccessfulXUnitGenerationTest.cs @@ -134,7 +134,7 @@ public void CanGenerateFromFile(string fileName) SpecFlowLangParser parser = new SpecFlowLangParser(new CultureInfo("en-US")); using (var reader = new StreamReader(fileName)) { - Feature feature = parser.Parse(reader); + Feature feature = parser.Parse(reader, null); Assert.IsNotNull(feature); string generatedCode = GenerateCodeFromFeature(feature); diff --git a/Tests/ParserTests/TestFiles/hungarian.feature b/Tests/ParserTests/TestFiles/hungarian.feature index cdbcfe478..2f99c6ce2 100644 --- a/Tests/ParserTests/TestFiles/hungarian.feature +++ b/Tests/ParserTests/TestFiles/hungarian.feature @@ -5,7 +5,7 @@ Jellemző: Összeadás két szám összegét szeretném kiszámoltatni. Forgatókönyv vázlat: Két szám összeadása - Ha beütök a számológépbe egy -est + Amennyiben beütök a számológépbe egy -est És beütök a számológépbe egy -est Majd megnyomom az gombot Akkor eredményül -t kell kapnom diff --git a/Tests/RuntimeTests/ExecutionTestBase.cs b/Tests/RuntimeTests/ExecutionTestBase.cs index 66117a40b..6a6c76e25 100644 --- a/Tests/RuntimeTests/ExecutionTestBase.cs +++ b/Tests/RuntimeTests/ExecutionTestBase.cs @@ -153,7 +153,7 @@ public void CanGenerateFromFile(string fileName) SpecFlowLangParser parser = new SpecFlowLangParser(new CultureInfo("en-US")); using (var reader = new StreamReader(fileName)) { - Feature feature = parser.Parse(reader); + Feature feature = parser.Parse(reader, null); Assert.IsNotNull(feature); ExecuteTests(feature, fileName); diff --git a/changelog.txt b/changelog.txt index 4719a62f4..cefdc4c29 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,11 @@ +1.3.1 - ??? + +New features: ++ Using standard Gherkin parser (http://github.com/aslakhellesoy/gherkin) v2.0.1 + +Fixed issues: ++ NullReference exception when using BeforeTestRun event (Issue 41) + 1.3.0 - 2010/05/05 New features: diff --git a/lib/gherkin/Gherkin.dll b/lib/gherkin/Gherkin.dll index 0ae5c722d..045322970 100644 Binary files a/lib/gherkin/Gherkin.dll and b/lib/gherkin/Gherkin.dll differ diff --git a/lib/gherkin/Gherkin.pdb b/lib/gherkin/Gherkin.pdb index bde81784a..d56bbbbef 100644 Binary files a/lib/gherkin/Gherkin.pdb and b/lib/gherkin/Gherkin.pdb differ diff --git a/lib/gherkin/gherkin-1.0.24.dll b/lib/gherkin/gherkin-1.0.24.dll deleted file mode 100644 index 0c56d9b52..000000000 Binary files a/lib/gherkin/gherkin-1.0.24.dll and /dev/null differ diff --git a/lib/gherkin/gherkin-2.0.1.dll b/lib/gherkin/gherkin-2.0.1.dll new file mode 100644 index 000000000..3810086cb Binary files /dev/null and b/lib/gherkin/gherkin-2.0.1.dll differ