/*
 * Copyright 2021 Google LLC.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/private/SkSLIRNode.h"
#include "include/sksl/DSL.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"

#include "tests/Test.h"

#include <limits>

using namespace SkSL::dsl;

#if defined(__GNUC__) || defined(__clang__)

class ExpectErrorLineNumber : public SkSL::ErrorReporter {
public:
    ExpectErrorLineNumber(skiatest::Reporter* reporter, const char* msg, int line)
        : fMsg(msg)
        , fLine(line)
        , fReporter(reporter)
        , fOldReporter(&GetErrorReporter()) {
        SetErrorReporter(this);
    }

    ~ExpectErrorLineNumber() override {
        REPORTER_ASSERT(fReporter, !fMsg);
        SetErrorReporter(fOldReporter);
    }

    void handleError(std::string_view msg, SkSL::PositionInfo pos) override {
        REPORTER_ASSERT(fReporter, msg == fMsg,
                "Error mismatch: expected:\n%sbut received:\n%.*s", fMsg, (int)msg.length(),
                msg.data());
        REPORTER_ASSERT(fReporter, pos.line() == fLine,
                "Line number mismatch: expected %d, but received %d\n", fLine, pos.line());
        SkSL::ThreadContext::Compiler().handleError(msg, pos);
        fMsg = nullptr;
    }

private:
    const char* fMsg;
    int fLine;
    skiatest::Reporter* fReporter;
    ErrorReporter* fOldReporter;
};

DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLErrorLineNumbers, r, ctxInfo) {
    Start(ctxInfo.directContext()->priv().getGpu()->shaderCompiler());
    {
        ExpectErrorLineNumber error(r, "type mismatch: '+' cannot operate on 'float', 'bool'",
                                    __LINE__ + 1);
        (Float(1) + true).release();
    }

    {
        Var a(kBool_Type);
        DSLWriter::MarkDeclared(a);
        ExpectErrorLineNumber error(r, "type mismatch: '=' cannot operate on 'bool', 'float'",
                                    __LINE__ + 1);
        (a = 5.0f).release();
    }

    {
        Var a(Array(kInt_Type, 5));
        DSLWriter::MarkDeclared(a);
        ExpectErrorLineNumber error(r, "expected 'int', but found 'bool'", __LINE__ + 1);
        (a[true]).release();
    }

    {
        Var a(Array(kInt_Type, 5));
        DSLWriter::MarkDeclared(a);
        ExpectErrorLineNumber error(r, "'++' cannot operate on 'int[5]'", __LINE__ + 1);
        (++a).release();
    }

    {
        ExpectErrorLineNumber error(r, "expected 'bool', but found 'int'", __LINE__ + 1);
        Do(Discard(), 5).release();
    }

    {
        ExpectErrorLineNumber error(r, "expected 'bool', but found 'int'", __LINE__ + 1);
        For(DSLStatement(), 5, DSLExpression(), Block()).release();
    }

    {
        ExpectErrorLineNumber error(r, "expected 'bool', but found 'int'", __LINE__ + 1);
        If(5, Discard()).release();
    }

    {
        ExpectErrorLineNumber error(r, "expected 'bool', but found 'int'", __LINE__ + 1);
        While(5, Discard()).release();
    }

    {
        ExpectErrorLineNumber error(r, "no match for abs(bool)", __LINE__ + 1);
        Abs(true).release();
    }
    End();
}

#endif // defined(__GNUC__) || defined(__clang__)
