Support getting line for diagnostic
This commit is contained in:
parent
e07d5cb7cb
commit
dc35ba4698
|
@ -3,6 +3,7 @@
|
||||||
#define PORYGONLANG_DIAGNOSTICSHOLDER_HPP
|
#define PORYGONLANG_DIAGNOSTICSHOLDER_HPP
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
#include "DiagnosticSeverity.hpp"
|
#include "DiagnosticSeverity.hpp"
|
||||||
#include "DiagnosticCode.hpp"
|
#include "DiagnosticCode.hpp"
|
||||||
#include "Diagnostic.hpp"
|
#include "Diagnostic.hpp"
|
||||||
|
@ -13,9 +14,21 @@ namespace Porygon::Diagnostics {
|
||||||
class DiagnosticsHolder {
|
class DiagnosticsHolder {
|
||||||
bool _hasErrors;
|
bool _hasErrors;
|
||||||
vector<Diagnostic> _diagnostics;
|
vector<Diagnostic> _diagnostics;
|
||||||
|
vector<size_t> _lineStarts;
|
||||||
|
vector<size_t> _lineLength;
|
||||||
public:
|
public:
|
||||||
DiagnosticsHolder() {
|
explicit DiagnosticsHolder(const u16string& str) {
|
||||||
_hasErrors = false;
|
_hasErrors = false;
|
||||||
|
_lineStarts = vector<size_t>{0};
|
||||||
|
size_t lineLength = 0;
|
||||||
|
for (size_t i = 0; i < str.size(); i++){
|
||||||
|
lineLength++;
|
||||||
|
if (str[i] == '\n'){
|
||||||
|
_lineStarts.push_back(i + 1);
|
||||||
|
_lineLength.push_back(lineLength);
|
||||||
|
lineLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~DiagnosticsHolder() {
|
~DiagnosticsHolder() {
|
||||||
|
@ -37,6 +50,29 @@ namespace Porygon::Diagnostics {
|
||||||
int DiagnosticsCount();
|
int DiagnosticsCount();
|
||||||
|
|
||||||
Diagnostic *GetDiagnosticAt(int position);
|
Diagnostic *GetDiagnosticAt(int position);
|
||||||
|
|
||||||
|
size_t GetLineFromPosition(size_t i){
|
||||||
|
size_t topLimit = _lineStarts.size() - 1;
|
||||||
|
size_t bottomLimit = 0;
|
||||||
|
while (true){
|
||||||
|
if (bottomLimit == topLimit){
|
||||||
|
return bottomLimit;
|
||||||
|
}
|
||||||
|
size_t half = (topLimit - bottomLimit) / 2;
|
||||||
|
size_t pos = _lineStarts[half];
|
||||||
|
size_t length = _lineLength[half];
|
||||||
|
if (pos < i && pos + length > i){
|
||||||
|
return half;
|
||||||
|
}
|
||||||
|
if (pos > i){
|
||||||
|
bottomLimit = half;
|
||||||
|
} else if (pos < i){
|
||||||
|
topLimit = half;
|
||||||
|
} else{
|
||||||
|
return half;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,7 @@
|
||||||
#include "Binder/Binder.hpp"
|
#include "Binder/Binder.hpp"
|
||||||
|
|
||||||
Porygon::Script* Porygon::Script::Create(const u16string& script) {
|
Porygon::Script* Porygon::Script::Create(const u16string& script) {
|
||||||
auto s = new Script();
|
return new Script(script);
|
||||||
s -> Parse(script);
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string To_UTF16(const string &s)
|
std::u16string To_UTF16(const string &s)
|
||||||
|
@ -24,11 +22,13 @@ Porygon::Script *Porygon::Script::Create(const string &script) {
|
||||||
return Script::Create(To_UTF16(script));
|
return Script::Create(To_UTF16(script));
|
||||||
}
|
}
|
||||||
|
|
||||||
Porygon::Script::Script() {
|
Porygon::Script::Script(const u16string& s) {
|
||||||
Diagnostics = new Diagnostics::DiagnosticsHolder();
|
Diagnostics = new Diagnostics::DiagnosticsHolder(s);
|
||||||
_boundScript = nullptr;
|
_boundScript = nullptr;
|
||||||
_scriptVariables = new unordered_map<uint32_t, shared_ptr<EvalValue>>(0);
|
_scriptVariables = new unordered_map<uint32_t, shared_ptr<EvalValue>>(0);
|
||||||
_evaluator = new Evaluator(this -> _scriptVariables);
|
_evaluator = new Evaluator(this -> _scriptVariables);
|
||||||
|
|
||||||
|
this -> Parse(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalValue* Porygon::Script::Evaluate() {
|
EvalValue* Porygon::Script::Evaluate() {
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Porygon{
|
||||||
Binder::BoundScriptStatement* _boundScript;
|
Binder::BoundScriptStatement* _boundScript;
|
||||||
shared_ptr<ScriptType> _returnType;
|
shared_ptr<ScriptType> _returnType;
|
||||||
|
|
||||||
explicit Script();
|
explicit Script(const u16string&);
|
||||||
void Parse(const u16string& script);
|
void Parse(const u16string& script);
|
||||||
public:
|
public:
|
||||||
static Script* Create(const u16string& script);
|
static Script* Create(const u16string& script);
|
||||||
|
|
|
@ -23,8 +23,24 @@ TEST_CASE( "Diagnostic invalid token", "[integration]" ) {
|
||||||
CHECK(diags[0].GetCode() == Diagnostics::DiagnosticCode::UnexpectedToken);
|
CHECK(diags[0].GetCode() == Diagnostics::DiagnosticCode::UnexpectedToken);
|
||||||
CHECK(diags[0].GetStartPosition() == 3);
|
CHECK(diags[0].GetStartPosition() == 3);
|
||||||
CHECK(diags[0].GetLength() == 1);
|
CHECK(diags[0].GetLength() == 1);
|
||||||
|
CHECK(script->Diagnostics->GetLineFromPosition(diags[0].GetStartPosition()) == 0);
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Get diagnostic line", "[integration]" ) {
|
||||||
|
auto script = Script::Create(uR"(
|
||||||
|
1 +/ 1
|
||||||
|
)");
|
||||||
|
REQUIRE(script->Diagnostics -> HasErrors());
|
||||||
|
auto diags = script->Diagnostics -> GetDiagnostics();
|
||||||
|
REQUIRE(diags.size() == 1);
|
||||||
|
CHECK(diags[0].GetCode() == Diagnostics::DiagnosticCode::UnexpectedToken);
|
||||||
|
CHECK(diags[0].GetStartPosition() == 4);
|
||||||
|
CHECK(diags[0].GetLength() == 1);
|
||||||
|
CHECK(script->Diagnostics->GetLineFromPosition(diags[0].GetStartPosition()) == 1);
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue