Support getting line for diagnostic

This commit is contained in:
Deukhoofd 2019-06-18 17:14:18 +02:00
parent e07d5cb7cb
commit dc35ba4698
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
4 changed files with 59 additions and 7 deletions

View File

@ -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;
}
}
}
}; };
} }

View File

@ -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() {

View File

@ -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);

View File

@ -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