Changeset 56333 in webkit


Ignore:
Timestamp:
Mar 22, 2010 7:37:53 AM (14 years ago)
Author:
eric@webkit.org
Message:

2010-03-22 Jedrzej Nowacki <jedrzej.nowacki@nokia.com>

Reviewed by Kenneth Rohde Christiansen.

Add support for syntax checking in the QtScript API.

New class was created; the QScriptSyntaxCheckResult which main
responsibility is to provide results of the ECMA Script code
syntax check. The class is not fully functional as the JSC C API
doesn't expose an error column number, but it is a good start point
for a future development.

[Qt] QtScript functionality should be extended by syntax checking.
https://bugs.webkit.org/show_bug.cgi?id=36123

  • qt/api/QtScript.pro:
  • qt/api/qscriptengine.cpp: (QScriptEngine::checkSyntax):
  • qt/api/qscriptengine.h:
  • qt/api/qscriptengine_p.cpp: (QScriptEnginePrivate::checkSyntax):
  • qt/api/qscriptengine_p.h:
  • qt/api/qscriptsyntaxcheckresult.cpp: Added. (QScriptSyntaxCheckResult::QScriptSyntaxCheckResult): (QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult): (QScriptSyntaxCheckResult::operator=): (QScriptSyntaxCheckResult::state): (QScriptSyntaxCheckResult::errorLineNumber): (QScriptSyntaxCheckResult::errorColumnNumber): (QScriptSyntaxCheckResult::errorMessage):
  • qt/api/qscriptsyntaxcheckresult.h: Added.
  • qt/api/qscriptsyntaxcheckresult_p.cpp: Added. (QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate): (QScriptSyntaxCheckResultPrivate::errorMessage): (QScriptSyntaxCheckResultPrivate::errorLineNumber):
  • qt/api/qscriptsyntaxcheckresult_p.h: Added. (QScriptSyntaxCheckResultPrivate::get): (QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate): (QScriptSyntaxCheckResultPrivate::state): (QScriptSyntaxCheckResultPrivate::errorColumnNumber):
  • qt/tests/qscriptengine/tst_qscriptengine.cpp: (tst_QScriptEngine::checkSyntax_data): (tst_QScriptEngine::checkSyntax):
Location:
trunk/JavaScriptCore
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r56320 r56333  
     12010-03-22  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
     2
     3        Reviewed by Kenneth Rohde Christiansen.
     4
     5        Add support for syntax checking in the QtScript API.
     6
     7        New class was created; the QScriptSyntaxCheckResult which main
     8        responsibility is to provide results of the ECMA Script code
     9        syntax check. The class is not fully functional as the JSC C API
     10        doesn't expose an error column number, but it is a good start point
     11        for a future development.
     12
     13        [Qt] QtScript functionality should be extended by syntax checking.
     14        https://bugs.webkit.org/show_bug.cgi?id=36123
     15
     16        * qt/api/QtScript.pro:
     17        * qt/api/qscriptengine.cpp:
     18        (QScriptEngine::checkSyntax):
     19        * qt/api/qscriptengine.h:
     20        * qt/api/qscriptengine_p.cpp:
     21        (QScriptEnginePrivate::checkSyntax):
     22        * qt/api/qscriptengine_p.h:
     23        * qt/api/qscriptsyntaxcheckresult.cpp: Added.
     24        (QScriptSyntaxCheckResult::QScriptSyntaxCheckResult):
     25        (QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult):
     26        (QScriptSyntaxCheckResult::operator=):
     27        (QScriptSyntaxCheckResult::state):
     28        (QScriptSyntaxCheckResult::errorLineNumber):
     29        (QScriptSyntaxCheckResult::errorColumnNumber):
     30        (QScriptSyntaxCheckResult::errorMessage):
     31        * qt/api/qscriptsyntaxcheckresult.h: Added.
     32        * qt/api/qscriptsyntaxcheckresult_p.cpp: Added.
     33        (QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate):
     34        (QScriptSyntaxCheckResultPrivate::errorMessage):
     35        (QScriptSyntaxCheckResultPrivate::errorLineNumber):
     36        * qt/api/qscriptsyntaxcheckresult_p.h: Added.
     37        (QScriptSyntaxCheckResultPrivate::get):
     38        (QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate):
     39        (QScriptSyntaxCheckResultPrivate::state):
     40        (QScriptSyntaxCheckResultPrivate::errorColumnNumber):
     41        * qt/tests/qscriptengine/tst_qscriptengine.cpp:
     42        (tst_QScriptEngine::checkSyntax_data):
     43        (tst_QScriptEngine::checkSyntax):
     44
    1452010-03-21  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
    246
  • trunk/JavaScriptCore/qt/api/QtScript.pro

    r56320 r56333  
    2525            $$PWD/qscriptstring.cpp \
    2626            $$PWD/qscriptprogram.cpp \
     27            $$PWD/qscriptsyntaxcheckresult.cpp \
    2728
    2829HEADERS +=  $$PWD/qtscriptglobal.h \
     
    3637            $$PWD/qscriptprogram.h \
    3738            $$PWD/qscriptprogram_p.h \
     39            $$PWD/qscriptsyntaxcheckresult.h \
    3840
    3941
  • trunk/JavaScriptCore/qt/api/qscriptengine.cpp

    r56320 r56333  
    2424#include "qscriptengine_p.h"
    2525#include "qscriptprogram_p.h"
     26#include "qscriptsyntaxcheckresult_p.h"
    2627#include "qscriptvalue_p.h"
    2728
     
    4142QScriptEngine::~QScriptEngine()
    4243{
     44}
     45
     46/*!
     47  Checks the syntax of the given \a program. Returns a
     48  QScriptSyntaxCheckResult object that contains the result of the check.
     49*/
     50QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program)
     51{
     52    // FIXME This is not optimal.
     53    // The JSC C API needs a context to perform a syntax check, it means that a QScriptEnginePrivate
     54    // had to be created. This function is static so we have to create QScriptEnginePrivate for each
     55    // call. We can't remove the "static" for compatibility reason, at least up to Qt5.
     56    // QScriptSyntaxCheckResultPrivate takes ownership of newly created engine. The engine will be
     57    // kept as long as it is needed for lazy evaluation of properties of
     58    // the QScriptSyntaxCheckResultPrivate.
     59    QScriptEnginePrivate* engine = new QScriptEnginePrivate(/* q_ptr */ 0);
     60    return QScriptSyntaxCheckResultPrivate::get(engine->checkSyntax(program));
    4361}
    4462
  • trunk/JavaScriptCore/qt/api/qscriptengine.h

    r56320 r56333  
    2323#include "qscriptprogram.h"
    2424#include "qscriptstring.h"
     25#include "qscriptsyntaxcheckresult.h"
    2526#include <QtCore/qobject.h>
    2627#include <QtCore/qshareddata.h>
     
    3839    ~QScriptEngine();
    3940
     41    static QScriptSyntaxCheckResult checkSyntax(const QString& program);
    4042    QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1);
    4143    QScriptValue evaluate(const QScriptProgram& program);
  • trunk/JavaScriptCore/qt/api/qscriptengine_p.cpp

    r56320 r56333  
    4040}
    4141
     42QScriptSyntaxCheckResultPrivate* QScriptEnginePrivate::checkSyntax(const QString& program)
     43{
     44    JSValueRef exception;
     45    if (JSCheckScriptSyntax(m_context, QScriptConverter::toString(program), /* url */ 0, /* starting line */ 1, &exception))
     46        return new QScriptSyntaxCheckResultPrivate(this);
     47    JSValueProtect(m_context, exception);
     48    return new QScriptSyntaxCheckResultPrivate(this, const_cast<JSObjectRef>(exception));
     49}
     50
    4251/*!
    4352    Evaluates program and returns the result of the evaluation.
  • trunk/JavaScriptCore/qt/api/qscriptengine_p.h

    r56320 r56333  
    2424#include "qscriptengine.h"
    2525#include "qscriptstring_p.h"
     26#include "qscriptsyntaxcheckresult_p.h"
    2627#include "qscriptvalue.h"
    2728#include <JavaScriptCore/JavaScript.h>
     
    3031
    3132class QScriptEngine;
     33class QScriptSyntaxCheckResultPrivate;
    3234
    3335class QScriptEnginePrivate : public QSharedData {
     
    3941    ~QScriptEnginePrivate();
    4042
     43    QScriptSyntaxCheckResultPrivate* checkSyntax(const QString& program);
    4144    QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber);
    4245    QScriptValuePrivate* evaluate(const QScriptProgramPrivate* program);
  • trunk/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp

    r56320 r56333  
    2020#include "qscriptengine.h"
    2121#include "qscriptprogram.h"
     22#include "qscriptsyntaxcheckresult.h"
    2223#include "qscriptvalue.h"
    2324#include <QtTest/qtest.h>
     
    4041    void undefinedValue();
    4142    void evaluateProgram();
     43    void checkSyntax_data();
     44    void checkSyntax();
    4245};
    4346
     
    176179}
    177180
     181void tst_QScriptEngine::checkSyntax_data()
     182{
     183    QTest::addColumn<QString>("code");
     184    QTest::addColumn<int>("expectedState");
     185    QTest::addColumn<int>("errorLineNumber");
     186    QTest::addColumn<int>("errorColumnNumber");
     187    QTest::addColumn<QString>("errorMessage");
     188
     189    QTest::newRow("0")
     190        << QString("0") << int(QScriptSyntaxCheckResult::Valid)
     191        << -1 << -1 << "";
     192    QTest::newRow("if (")
     193        << QString("if (\n") << int(QScriptSyntaxCheckResult::Intermediate)
     194        << 1 << 4 << "";
     195    QTest::newRow("if else")
     196        << QString("\nif else") << int(QScriptSyntaxCheckResult::Error)
     197        << 2 << 4 << "SyntaxError: Parse error";
     198    QTest::newRow("{if}")
     199            << QString("{\n{\nif\n}\n") << int(QScriptSyntaxCheckResult::Error)
     200        << 4 << 1 << "SyntaxError: Parse error";
     201    QTest::newRow("foo[")
     202        << QString("foo[") << int(QScriptSyntaxCheckResult::Error)
     203        << 1 << 4 << "SyntaxError: Parse error";
     204    QTest::newRow("foo['bar']")
     205        << QString("foo['bar']") << int(QScriptSyntaxCheckResult::Valid)
     206        << -1 << -1 << "";
     207
     208    QTest::newRow("/*")
     209        << QString("/*") << int(QScriptSyntaxCheckResult::Intermediate)
     210        << 1 << 1 << "Unclosed comment at end of file";
     211    QTest::newRow("/*\nMy comment")
     212        << QString("/*\nMy comment") << int(QScriptSyntaxCheckResult::Intermediate)
     213        << 1 << 1 << "Unclosed comment at end of file";
     214    QTest::newRow("/*\nMy comment */\nfoo = 10")
     215        << QString("/*\nMy comment */\nfoo = 10") << int(QScriptSyntaxCheckResult::Valid)
     216        << -1 << -1 << "";
     217    QTest::newRow("foo = 10 /*")
     218        << QString("foo = 10 /*") << int(QScriptSyntaxCheckResult::Intermediate)
     219        << -1 << -1 << "";
     220    QTest::newRow("foo = 10; /*")
     221        << QString("foo = 10; /*") << int(QScriptSyntaxCheckResult::Intermediate)
     222        << 1 << 11 << "Expected `end of file'";
     223    QTest::newRow("foo = 10 /* My comment */")
     224        << QString("foo = 10 /* My comment */") << int(QScriptSyntaxCheckResult::Valid)
     225        << -1 << -1 << "";
     226
     227    QTest::newRow("/=/")
     228        << QString("/=/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
     229    QTest::newRow("/=/g")
     230        << QString("/=/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
     231    QTest::newRow("/a/")
     232        << QString("/a/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
     233    QTest::newRow("/a/g")
     234        << QString("/a/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
     235}
     236
     237void tst_QScriptEngine::checkSyntax()
     238{
     239    QFETCH(QString, code);
     240    QFETCH(int, expectedState);
     241    QFETCH(int, errorLineNumber);
     242    QFETCH(int, errorColumnNumber);
     243    QFETCH(QString, errorMessage);
     244
     245    QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(code);
     246
     247    // assignment
     248    {
     249        QScriptSyntaxCheckResult copy = result;
     250        QCOMPARE(copy.state(), result.state());
     251        QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
     252        QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
     253        QCOMPARE(copy.errorMessage(), result.errorMessage());
     254    }
     255    {
     256        QScriptSyntaxCheckResult copy(result);
     257        QCOMPARE(copy.state(), result.state());
     258        QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
     259        QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
     260        QCOMPARE(copy.errorMessage(), result.errorMessage());
     261    }
     262
     263    if (expectedState == QScriptSyntaxCheckResult::Intermediate)
     264        QEXPECT_FAIL("", "QScriptSyntaxCheckResult::state() doesn't return the Intermediate state", Abort);
     265    QCOMPARE(result.state(), QScriptSyntaxCheckResult::State(expectedState));
     266    QCOMPARE(result.errorLineNumber(), errorLineNumber);
     267    if (expectedState != QScriptSyntaxCheckResult::Valid && errorColumnNumber != 1)
     268            QEXPECT_FAIL("", "QScriptSyntaxCheckResult::errorColumnNumber() doesn't return correct value", Continue);
     269    QCOMPARE(result.errorColumnNumber(), errorColumnNumber);
     270    QCOMPARE(result.errorMessage(), errorMessage);
     271}
     272
     273
    178274QTEST_MAIN(tst_QScriptEngine)
    179275#include "tst_qscriptengine.moc"
Note: See TracChangeset for help on using the changeset viewer.