Beispiel #1
0
        private AchievementScriptInterpreter Parse(string input, bool expectedSuccess = true)
        {
            var tokenizer = Tokenizer.CreateTokenizer(input);
            var parser    = new AchievementScriptInterpreter();

            if (expectedSuccess)
            {
                if (!parser.Run(tokenizer))
                {
                    Assert.That(parser.ErrorMessage, Is.Null);
                    Assert.Fail("AchievementScriptInterpreter.Run failed with no error message");
                }
            }
            else
            {
                Assert.That(parser.Run(tokenizer), Is.False);
                Assert.That(parser.ErrorMessage, Is.Not.Null);
            }

            return(parser);
        }
Beispiel #2
0
        private Achievement Evaluate(string input, string expectedError = null)
        {
            var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input));
            var parser    = new AchievementScriptInterpreter();

            if (expectedError == null)
            {
                if (!parser.Run(tokenizer))
                {
                    Assert.That(parser.ErrorMessage, Is.Null);
                    Assert.Fail("AchievementScriptInterpreter.Run failed with no error message");
                }
            }
            else
            {
                Assert.That(parser.Run(tokenizer), Is.False);
                Assert.That(parser.ErrorMessage, Is.Not.Null.And.EqualTo(expectedError));
            }

            return(parser.Achievements.FirstOrDefault());
        }
Beispiel #3
0
        private static string Evaluate(string input)
        {
            var script    = "achievement(\"title\", \"desc\", 5,\n" + input + "\n)";
            var tokenizer = Tokenizer.CreateTokenizer(script);
            var parser    = new AchievementScriptInterpreter();

            if (parser.Run(tokenizer))
            {
                var achievement = parser.Achievements.First();
                var builder     = new AchievementBuilder(achievement);
                return(builder.RequirementsDebugString);
            }

            return(parser.Error.InnermostError.Message);
        }
Beispiel #4
0
        public void TestScopedVariable()
        {
            var script = "function ItemInInventory(id) => any_of(range(0x1200, 0x1208, step=2), addr => word(addr) == id)\n" +
                         "achievement(\"title\", \"desc\", 5, ItemInInventory(17))";
            var tokenizer = Tokenizer.CreateTokenizer(script);
            var parser    = new AchievementScriptInterpreter();

            if (!parser.Run(tokenizer))
            {
                Assert.Fail(parser.ErrorMessage);
            }

            var achievement = parser.Achievements.First();
            var builder     = new AchievementBuilder(achievement);

            Assert.That(builder.RequirementsDebugString, Is.EqualTo(
                            "word(0x001200) == 17 || word(0x001202) == 17 || word(0x001204) == 17 || word(0x001206) == 17 || word(0x001208) == 17"));
        }
Beispiel #5
0
        public void TestPredicateWithDefaultParameter()
        {
            var script = "function p(addr, id=17) => byte(addr) == id\n" +
                         "achievement(\"title\", \"desc\", 5, any_of([1, 2, 3], p))";
            var tokenizer = Tokenizer.CreateTokenizer(script);
            var parser    = new AchievementScriptInterpreter();

            if (!parser.Run(tokenizer))
            {
                Assert.Fail(parser.ErrorMessage);
            }

            var achievement = parser.Achievements.First();
            var builder     = new AchievementBuilder(achievement);

            Assert.That(builder.RequirementsDebugString, Is.EqualTo(
                            "byte(0x000001) == 17 || byte(0x000002) == 17 || byte(0x000003) == 17"));
        }
Beispiel #6
0
        protected override void OnUpdateSyntax(ContentChangedEventArgs e)
        {
            var parser = new AchievementScriptParser();

            _parsedContent = parser.Parse(Tokenizer.CreateTokenizer(e.Content));

            if (e.IsAborted)
            {
                return;
            }

            var interpreter = new AchievementScriptInterpreter();

            interpreter.Run(_parsedContent, out _scope);

            if (e.IsAborted)
            {
                return;
            }

            ServiceRepository.Instance.FindService <IBackgroundWorkerService>().InvokeOnUiThread(() =>
            {
                ErrorsToolWindow.References.Clear();
                foreach (var error in _parsedContent.Errors)
                {
                    string message = error.Message;

                    var innerError = error;
                    if (innerError.InnerError != null)
                    {
                        do
                        {
                            innerError = innerError.InnerError;
                        } while (innerError.InnerError != null);

                        if (error.Line != innerError.Line || error.Column != innerError.Column)
                        {
                            message += String.Format(" (called from {0}:{1})", error.Line, error.Column);
                        }
                    }

                    ErrorsToolWindow.References.Add(new CodeReferenceViewModel
                    {
                        StartLine   = innerError.Line,
                        StartColumn = innerError.Column,
                        EndLine     = innerError.EndLine,
                        EndColumn   = innerError.EndColumn,
                        Message     = message
                    });
                }
            });

            if (e.IsAborted)
            {
                return;
            }

            if (e.IsWhitespaceOnlyChange)
            {
                return;
            }

            // wait a short while before updating the editor list
            ServiceRepository.Instance.FindService <ITimerService>().Schedule(() =>
            {
                if (e.IsAborted)
                {
                    return;
                }

                _owner.PopulateEditorList(interpreter);
            }, TimeSpan.FromMilliseconds(700));

            base.OnUpdateSyntax(e);
        }
Beispiel #7
0
        public void RegressionTest(string scriptFileName)
        {
            if (scriptFileName == "No scripts found.")
            {
                return;
            }

            var outputFileName   = scriptFileName.Substring(0, scriptFileName.Length - 9) + ".updated.txt";
            var expectedFileName = scriptFileName.Substring(0, scriptFileName.Length - 9) + ".txt";

            var interpreter = new AchievementScriptInterpreter();

            interpreter.Run(Tokenizer.CreateTokenizer(File.Open(scriptFileName, FileMode.Open)));

            Assert.IsNull(interpreter.ErrorMessage);

            var mockFileSystemService = new Mock <IFileSystemService>();

            mockFileSystemService.Setup(s => s.CreateFile(It.IsAny <string>())).Returns((string path) => File.Create(path));

            var localAchievements = new LocalAchievements(outputFileName, mockFileSystemService.Object);

            localAchievements.Title = Path.GetFileNameWithoutExtension(scriptFileName);
            foreach (var achievement in interpreter.Achievements)
            {
                localAchievements.Replace(null, achievement);
            }
            localAchievements.Commit("Author");

            if (interpreter.Leaderboards.Any())
            {
                using (var file = File.Open(outputFileName, FileMode.Append))
                {
                    using (var fileWriter = new StreamWriter(file))
                    {
                        fileWriter.WriteLine("=== Leaderboards ===");
                        foreach (var leaderboard in interpreter.Leaderboards)
                        {
                            fileWriter.Write("0:");
                            fileWriter.Write("\"STA:");
                            fileWriter.Write(leaderboard.Start);
                            fileWriter.Write("::CAN:");
                            fileWriter.Write(leaderboard.Cancel);
                            fileWriter.Write("::SUB:");
                            fileWriter.Write(leaderboard.Submit);
                            fileWriter.Write("::VAL:");
                            fileWriter.Write(leaderboard.Value);
                            fileWriter.Write("\":");
                            fileWriter.Write(leaderboard.Format);
                            fileWriter.Write(":\"");
                            fileWriter.Write(leaderboard.Title);
                            fileWriter.Write("\":\"");
                            fileWriter.Write(leaderboard.Description);
                            fileWriter.WriteLine("\"");
                        }
                    }
                }
            }

            if (!String.IsNullOrEmpty(interpreter.RichPresence))
            {
                using (var file = File.Open(outputFileName, FileMode.Append))
                {
                    using (var fileWriter = new StreamWriter(file))
                    {
                        fileWriter.WriteLine("=== Rich Presence ===");
                        fileWriter.WriteLine(interpreter.RichPresence);
                    }
                }
            }

            Assert.IsTrue(File.Exists(expectedFileName), expectedFileName + " not found");

            FileAssert.AreEqual(expectedFileName, outputFileName);

            File.Delete(outputFileName);
        }
Beispiel #8
0
        public void RegressionTest(string scriptFileName, string scriptPath)
        {
            if (scriptFileName == NoScriptsError)
            {
                return;
            }

            var parts = scriptPath.Split('\\');
            int i     = 0;

            if (!Path.IsPathRooted(scriptPath))
            {
                scriptPath = Path.Combine(RegressionDir, scriptPath);
            }
            else
            {
                while (parts[i] != "Regressions")
                {
                    ++i;
                    Assert.That(i < parts.Length);
                }

                ++i;
                Assert.That(i < parts.Length);
            }

            if (parts[i] == "scripts")
            {
                ++i;
            }

            var expectedFileName = Path.GetFileNameWithoutExtension(scriptPath);

            while (i < parts.Length - 1)
            {
                expectedFileName += "-" + parts[i];
                ++i;
            }

            expectedFileName = Path.Combine(RegressionDir, "results", expectedFileName + ".txt");
            var outputFileName = Path.ChangeExtension(expectedFileName, ".updated.txt");

            var interpreter = new AchievementScriptInterpreter();
            var content     = File.ReadAllText(scriptPath);

            interpreter.Run(Tokenizer.CreateTokenizer(content));

            if (!String.IsNullOrEmpty(interpreter.ErrorMessage))
            {
                using (var file = File.Open(outputFileName, FileMode.Create))
                {
                    using (var fileWriter = new StreamWriter(file))
                        fileWriter.Write(interpreter.ErrorMessage);
                }

                if (!File.Exists(expectedFileName))
                {
                    Assert.IsNull(interpreter.ErrorMessage);
                }
            }
            else
            {
                var mockFileSystemService = new Mock <IFileSystemService>();
                mockFileSystemService.Setup(s => s.CreateFile(It.IsAny <string>())).Returns((string path) => File.Create(path));

                var localAchievements = new LocalAssets(outputFileName, mockFileSystemService.Object);
                localAchievements.Title = Path.GetFileNameWithoutExtension(scriptFileName);
                foreach (var achievement in interpreter.Achievements)
                {
                    localAchievements.Replace(null, achievement);
                }
                foreach (var leaderboard in interpreter.Leaderboards)
                {
                    localAchievements.Replace(null, leaderboard);
                }
                localAchievements.Commit("Author", null, null);

                if (!String.IsNullOrEmpty(interpreter.RichPresence))
                {
                    using (var file = File.Open(outputFileName, FileMode.Append))
                    {
                        using (var fileWriter = new StreamWriter(file))
                        {
                            fileWriter.WriteLine("=== Rich Presence ===");

                            var minimumVersion = Double.Parse(localAchievements.Version, System.Globalization.NumberFormatInfo.InvariantInfo);
                            if (minimumVersion < 0.80)
                            {
                                interpreter.RichPresenceBuilder.DisableBuiltInMacros = true;

                                if (minimumVersion < 0.79)
                                {
                                    interpreter.RichPresenceBuilder.DisableLookupCollapsing = true;
                                }

                                fileWriter.WriteLine(interpreter.RichPresenceBuilder.ToString());
                            }
                            else
                            {
                                fileWriter.WriteLine(interpreter.RichPresence);
                            }
                        }
                    }
                }

                Assert.IsTrue(File.Exists(expectedFileName), expectedFileName + " not found");
            }

            var expectedFileContents = File.ReadAllText(expectedFileName);
            var outputFileContents   = File.ReadAllText(outputFileName);

            // file didn't match, report first difference
            if (expectedFileContents != outputFileContents)
            {
                var expectedFileTokenizer = Tokenizer.CreateTokenizer(expectedFileContents);
                var outputFileTokenizer   = Tokenizer.CreateTokenizer(outputFileContents);

                var line = 1;
                do
                {
                    var expectedFileLine = expectedFileTokenizer.ReadTo('\n').TrimRight();
                    var outputFileLine   = outputFileTokenizer.ReadTo('\n').TrimRight();

                    if (expectedFileLine != outputFileLine)
                    {
                        Assert.AreEqual(expectedFileLine.ToString(), outputFileLine.ToString(), "Line " + line);
                    }

                    expectedFileTokenizer.Advance();
                    outputFileTokenizer.Advance();

                    ++line;
                } while (expectedFileTokenizer.NextChar != '\0' || outputFileTokenizer.NextChar != '\0');

                // failed to find differing line, fallback to nunit assertion
                FileAssert.AreEqual(expectedFileName, outputFileName);
            }

            // file matched, delete temporary file
            File.Delete(outputFileName);
        }
Beispiel #9
0
        protected override void OnUpdateSyntax(ContentChangedEventArgs e)
        {
            bool needsUpdate = false;

            // parse immediately so we can update the syntax highlighting
            var tokenizer = Tokenizer.CreateTokenizer(e.Content);

            if (_parsedContent == null || e.Type == ContentChangeType.Refresh)
            {
                _parsedContent               = new ExpressionGroupCollection();
                _parsedContent.Scope         = new InterpreterScope(AchievementScriptInterpreter.GetGlobalScope());
                _parsedContent.Scope.Context = new AchievementScriptContext();

                lock (_parsedContent)
                {
                    _parsedContent.Parse(tokenizer);
                    needsUpdate = true;
                }
            }
            else if (e.Type == ContentChangeType.Update)
            {
                lock (_parsedContent)
                {
                    needsUpdate = _parsedContent.Update(tokenizer, e.AffectedLines);
                }

                if (!needsUpdate && !e.IsAborted)
                {
                    UpdateErrorList();
                }
            }

            if (needsUpdate && !e.IsAborted)
            {
                // running the script can take a lot of time, push that work onto a background thread and show progress bar
                UpdateProgress(1, 0);

                // make sure to at least show the script file in the editor list
                if (!_owner.Editors.Any())
                {
                    _owner.PopulateEditorList(null);
                }

                ServiceRepository.Instance.FindService <IBackgroundWorkerService>().RunAsync(() =>
                {
                    if (!e.IsAborted)
                    {
                        // run the script
                        var callback    = new ScriptInterpreterCallback(this, e);
                        var interpreter = new AchievementScriptInterpreter();

                        bool hadErrors, hasErrors;
                        lock (_parsedContent)
                        {
                            hadErrors = _parsedContent.HasEvaluationErrors;
                            hasErrors = !interpreter.Run(_parsedContent, callback);
                        }

                        if (!e.IsAborted)
                        {
                            UpdateProgress(100, 0);

                            // if any errors were added or removed, update the highlighting
                            if (hasErrors != hadErrors)
                            {
                                UpdateSyntaxHighlighting(e);
                            }

                            // report any errors
                            UpdateErrorList();

                            if (!e.IsAborted)
                            {
                                // update the editor list
                                _owner.PopulateEditorList(interpreter);
                            }
                        }
                    }

                    // make sure the progress bar is hidden
                    UpdateProgress(0, 0);
                });
            }

            base.OnUpdateSyntax(e);
        }