Как использовать ErrorListener для IronRuby - PullRequest
2 голосов
/ 17 февраля 2012

У меня есть программа на C # для выполнения сценария IronRuby.Но прежде чем сделать это, я хотел бы сначала скомпилировать файл, чтобы увидеть, есть ли ошибки.Но, похоже, ErrorListener не работает хорошо.Что-то не так с моим кодом?

class Program
{
    static void Main(string[] args)
    {
        try
        {
            ScriptEngine engine = null;
            engine = Ruby.CreateEngine();

            ScriptSource sc = engine.CreateScriptSourceFromFile("MainForm.rb");
            ErrorListener errLis = new MyErrorListener();
            sc.Compile(errLis);
    }
}

class MyErrorListener : ErrorListener
{
    public override void ErrorReported(ScriptSource source, string message, Microsoft.Scripting.SourceSpan span, int errorCode, Microsoft.Scripting.Severity severity)
    {
        Console.WriteLine(message);
    }
}

Файл Ruby:

require "mscorlib"
require "System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
require "System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

include System::Windows::Forms
dfasdf error here
class MainForm < Form
def initialize()
    self.InitializeComponent()
end

def InitializeComponent()
    # 
    # MainForm
    # 
    self.Name = "MainForm"
    self.Text = "HelloRubyWin"
end
end

Ответы [ 2 ]

1 голос
/ 01 марта 2012

То, что вы пытаетесь сделать, похоже, на самом деле не работает. Не уверен, что это ошибка или нет.

Чтобы обойти это, просто выполните код внутри блока try / catch и найдите MissingMethodExecption. Обратите внимание, что это также не поможет, если синтаксическая ошибка находится внутри метода, поскольку IronRuby (или любой другой динамический язык) ничего не делает с «вложенным» кодом, пока он фактически не выполнит его.

Так что в целом, я думаю, вы не получите много пользы от того, что вы пытаетесь сделать.

Пример кода try / catch:

ScriptEngine engine = null;
engine = Ruby.CreateEngine(x => { x.ExceptionDetail = true; });         

ScriptSource sc = engine.CreateScriptSourceFromFile("MainForm.rb");
ErrorListener errLis = new MyErrorListener();
sc.Compile(errLis);

try
{
    dynamic d = sc.Execute();
}
catch (MissingMethodException e)
{
    Console.WriteLine("Syntax error!");
}
0 голосов
/ 25 августа 2012

Я исследовал эту проблему и, наконец, нашел решение, которое сначала напишет ваш класс ErrorListener в следующем Manger.

public class IronRubyErrors : ErrorListener
{
    public string Message { get; set; }
    public int ErrorCode { get; set; }
    public Severity sev { get; set; }
    public SourceSpan Span { get; set; }
    public override void ErrorReported(ScriptSource source, string message, Microsoft.Scripting.SourceSpan span, int errorCode, Microsoft.Scripting.Severity severity)
    {
        Message = message;
        ErrorCode = errorCode;
        sev = severity;
        Span = span;
    }
}

тогда

var rubyEngine = Ruby.CreateEngine();
ScriptSource src = rubyEngine.CreateScriptSourceFromFile("test.rb");
IronRubyErrors error = new IronRubyErrors();
src.Compile(error);
if (error.ErrorCode != 0)
{
    MessageBox.Show(string.Format("Discription {0} \r\nError at Line No.{1} and Column No{2}", error.Message, error.span.Start.Line, error.span.Start.Column));
}

try
{
    if (error.ErrorCode == 0)
    {
        var res = src.Execute();
    }
}
catch (MissingMethodException ex)
{
    MessageBox.Show(ex.Message);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

Поскольку Ironruby - это DLR, он компилируется в RunTime, если символы, не являющиеся ключевыми словами IronRuby, такие как (~, `, ^ и т. Д.) ИЛИ вы создали любую синтаксическую ошибку, кроме Error, будет зафиксирована в методе компиляции ScriptSource и объект класса ErrorListener будет заполнен, и мы найдем ErrorCode и т. д., если вы использовали метод, который не определен в библиотеке Ruby, например, вы ввели метод для преобразования чисел, например,

    @abc.to_

, что неверно, тогда оно будет перехвачено в блоке MissingMethodException

Правильный метод

    @abc.to_f

и если вы получили ошибку «Другое», то это (например, «Делить на исключение нуля»), то это будет зафиксировано в блоке исключений

...