Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,87 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/torque/earley-parser.h"
#include <optional>
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace torque {
namespace {
template <int op(int, int)>
std::optional<ParseResult> MakeBinop(ParseResultIterator* child_results) {
// Ideally, we would want to use int as a result type here instead of
// std::string. This is possible, but requires adding int to the list of
// supported ParseResult types in torque-parser.cc. To avoid changing that
// code, we use std::string here, which is already used in the Torque parser.
auto a = child_results->NextAs<std::string>();
auto b = child_results->NextAs<std::string>();
return ParseResult{std::to_string(op(std::stoi(a), std::stoi(b)))};
}
int plus(int a, int b) { return a + b; }
int minus(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
} // namespace
struct SimpleArithmeticGrammar : Grammar {
static bool MatchWhitespace(InputPosition* pos) {
while (MatchChar(std::isspace, pos)) {
}
return true;
}
static bool MatchInteger(InputPosition* pos) {
InputPosition current = *pos;
MatchString("-", &current);
if (MatchChar(std::isdigit, &current)) {
while (MatchChar(std::isdigit, &current)) {
}
*pos = current;
return true;
}
return false;
}
SimpleArithmeticGrammar() : Grammar(&sum_expression) {
SetWhitespace(MatchWhitespace);
}
Symbol integer = {Rule({Pattern(MatchInteger)}, YieldMatchedInput)};
Symbol atomic_expression = {Rule({&integer}),
Rule({Token("("), &sum_expression, Token(")")})};
Symbol mul_expression = {
Rule({&atomic_expression}),
Rule({&mul_expression, Token("*"), &atomic_expression}, MakeBinop<mul>)};
Symbol sum_expression = {
Rule({&mul_expression}),
Rule({&sum_expression, Token("+"), &mul_expression}, MakeBinop<plus>),
Rule({&sum_expression, Token("-"), &mul_expression}, MakeBinop<minus>)};
};
TEST(EarleyParser, SimpleArithmetic) {
SimpleArithmeticGrammar grammar;
SourceFileMap::Scope source_file_map("");
CurrentSourceFile::Scope current_source_file{
SourceFileMap::AddSource("dummy_filename")};
std::string result1 =
grammar.Parse("-5 - 5 + (3 + 5) * 2")->Cast<std::string>();
ASSERT_EQ("6", result1);
std::string result2 = grammar.Parse("((-1 + (1) * 2 + 3 - 4 * 5 + -6 * 7))")
->Cast<std::string>();
ASSERT_EQ("-58", result2);
}
} // namespace torque
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,124 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/torque/ls/json-parser.h"
#include "src/torque/ls/json.h"
#include "src/torque/source-positions.h"
#include "src/torque/utils.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock-support.h"
namespace v8 {
namespace internal {
namespace torque {
namespace ls {
TEST(LanguageServerJson, TestJsonPrimitives) {
const JsonValue true_result = ParseJson("true").value;
ASSERT_EQ(true_result.tag, JsonValue::BOOL);
EXPECT_EQ(true_result.ToBool(), true);
const JsonValue false_result = ParseJson("false").value;
ASSERT_EQ(false_result.tag, JsonValue::BOOL);
EXPECT_EQ(false_result.ToBool(), false);
const JsonValue null_result = ParseJson("null").value;
ASSERT_EQ(null_result.tag, JsonValue::IS_NULL);
const JsonValue number = ParseJson("42").value;
ASSERT_EQ(number.tag, JsonValue::NUMBER);
EXPECT_EQ(number.ToNumber(), 42);
}
TEST(LanguageServerJson, TestJsonStrings) {
const JsonValue basic = ParseJson("\"basic\"").value;
ASSERT_EQ(basic.tag, JsonValue::STRING);
EXPECT_EQ(basic.ToString(), "basic");
const JsonValue singleQuote = ParseJson("\"'\"").value;
ASSERT_EQ(singleQuote.tag, JsonValue::STRING);
EXPECT_EQ(singleQuote.ToString(), "'");
}
TEST(LanguageServerJson, TestJsonArrays) {
const JsonValue empty_array = ParseJson("[]").value;
ASSERT_EQ(empty_array.tag, JsonValue::ARRAY);
EXPECT_EQ(empty_array.ToArray().size(), (size_t)0);
const JsonValue number_array = ParseJson("[1, 2, 3, 4]").value;
ASSERT_EQ(number_array.tag, JsonValue::ARRAY);
const JsonArray& array = number_array.ToArray();
ASSERT_EQ(array.size(), (size_t)4);
ASSERT_EQ(array[1].tag, JsonValue::NUMBER);
EXPECT_EQ(array[1].ToNumber(), 2);
const JsonValue string_array_object = ParseJson("[\"a\", \"b\"]").value;
ASSERT_EQ(string_array_object.tag, JsonValue::ARRAY);
const JsonArray& string_array = string_array_object.ToArray();
ASSERT_EQ(string_array.size(), (size_t)2);
ASSERT_EQ(string_array[1].tag, JsonValue::STRING);
EXPECT_EQ(string_array[1].ToString(), "b");
}
TEST(LanguageServerJson, TestJsonObjects) {
const JsonValue empty_object = ParseJson("{}").value;
ASSERT_EQ(empty_object.tag, JsonValue::OBJECT);
EXPECT_EQ(empty_object.ToObject().size(), (size_t)0);
const JsonValue primitive_fields =
ParseJson("{ \"flag\": true, \"id\": 5}").value;
EXPECT_EQ(primitive_fields.tag, JsonValue::OBJECT);
const JsonValue& flag = primitive_fields.ToObject().at("flag");
ASSERT_EQ(flag.tag, JsonValue::BOOL);
EXPECT_TRUE(flag.ToBool());
const JsonValue& id = primitive_fields.ToObject().at("id");
ASSERT_EQ(id.tag, JsonValue::NUMBER);
EXPECT_EQ(id.ToNumber(), 5);
const JsonValue& complex_fields =
ParseJson("{ \"array\": [], \"object\": { \"name\": \"torque\" } }")
.value;
ASSERT_EQ(complex_fields.tag, JsonValue::OBJECT);
const JsonValue& array = complex_fields.ToObject().at("array");
ASSERT_EQ(array.tag, JsonValue::ARRAY);
EXPECT_EQ(array.ToArray().size(), (size_t)0);
const JsonValue& object = complex_fields.ToObject().at("object");
ASSERT_EQ(object.tag, JsonValue::OBJECT);
ASSERT_EQ(object.ToObject().at("name").tag, JsonValue::STRING);
EXPECT_EQ(object.ToObject().at("name").ToString(), "torque");
}
// These tests currently fail on Windows as there seems to be a linking
// issue with exceptions enabled for Torque.
// TODO(szuend): Remove the OS check when errors are reported differently,
// or the issue is resolved.
// TODO(almuthanna): These tests were skipped because they cause a crash when
// they are ran on Fuchsia. This issue should be solved later on
// Ticket: https://crbug.com/1028617
#if !defined(V8_OS_WIN) && !defined(V8_TARGET_OS_FUCHSIA)
using ::testing::HasSubstr;
TEST(LanguageServerJson, ParserError) {
JsonParserResult result = ParseJson("{]");
ASSERT_TRUE(result.error.has_value());
EXPECT_THAT(result.error->message,
HasSubstr("Parser Error: unexpected token"));
}
TEST(LanguageServerJson, LexerError) {
JsonParserResult result = ParseJson("{ noquoteskey: null }");
ASSERT_TRUE(result.error.has_value());
EXPECT_THAT(result.error->message, HasSubstr("Lexer Error: unknown token"));
}
#endif
} // namespace ls
} // namespace torque
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,246 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/torque/ls/json.h"
#include "src/torque/ls/message-handler.h"
#include "src/torque/ls/message.h"
#include "src/torque/server-data.h"
#include "src/torque/source-positions.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace torque {
namespace ls {
TEST(LanguageServerMessage, InitializeRequest) {
InitializeRequest request;
request.set_id(5);
request.set_method("initialize");
request.params();
bool writer_called = false;
HandleMessage(std::move(request.GetJsonValue()), [&](JsonValue raw_response) {
InitializeResponse response(std::move(raw_response));
// Check that the response id matches up with the request id, and that
// the language server signals its support for definitions.
EXPECT_EQ(response.id(), 5);
EXPECT_TRUE(response.result().capabilities().definitionProvider());
EXPECT_TRUE(response.result().capabilities().documentSymbolProvider());
writer_called = true;
});
EXPECT_TRUE(writer_called);
}
TEST(LanguageServerMessage,
RegisterDynamicCapabilitiesAfterInitializedNotification) {
Request<bool> notification;
notification.set_method("initialized");
bool writer_called = false;
HandleMessage(std::move(notification.GetJsonValue()), [&](JsonValue
raw_request) {
RegistrationRequest request(std::move(raw_request));
ASSERT_EQ(request.method(), "client/registerCapability");
ASSERT_EQ(request.params().registrations_size(), (size_t)1);
Registration registration = request.params().registrations(0);
ASSERT_EQ(registration.method(), "workspace/didChangeWatchedFiles");
auto options =
registration
.registerOptions<DidChangeWatchedFilesRegistrationOptions>();
ASSERT_EQ(options.watchers_size(), (size_t)1);
writer_called = true;
});
EXPECT_TRUE(writer_called);
}
TEST(LanguageServerMessage, GotoDefinitionUnkownFile) {
SourceFileMap::Scope source_file_map_scope("");
GotoDefinitionRequest request;
request.set_id(42);
request.set_method("textDocument/definition");
request.params().textDocument().set_uri("file:///unknown.tq");
bool writer_called = false;
HandleMessage(std::move(request.GetJsonValue()), [&](JsonValue raw_response) {
GotoDefinitionResponse response(std::move(raw_response));
EXPECT_EQ(response.id(), 42);
EXPECT_TRUE(response.IsNull("result"));
writer_called = true;
});
EXPECT_TRUE(writer_called);
}
TEST(LanguageServerMessage, GotoDefinition) {
SourceFileMap::Scope source_file_map_scope("");
SourceId test_id = SourceFileMap::AddSource("file://test.tq");
SourceId definition_id = SourceFileMap::AddSource("file://base.tq");
LanguageServerData::Scope server_data_scope;
LanguageServerData::AddDefinition(
{test_id, LineAndColumn::WithUnknownOffset(1, 0),
LineAndColumn::WithUnknownOffset(1, 10)},
{definition_id, LineAndColumn::WithUnknownOffset(4, 1),
LineAndColumn::WithUnknownOffset(4, 5)});
// First, check an unknown definition. The result must be null.
GotoDefinitionRequest request;
request.set_id(42);
request.set_method("textDocument/definition");
request.params().textDocument().set_uri("file://test.tq");
request.params().position().set_line(2);
request.params().position().set_character(0);
bool writer_called = false;
HandleMessage(std::move(request.GetJsonValue()), [&](JsonValue raw_response) {
GotoDefinitionResponse response(std::move(raw_response));
EXPECT_EQ(response.id(), 42);
EXPECT_TRUE(response.IsNull("result"));
writer_called = true;
});
EXPECT_TRUE(writer_called);
// Second, check a known defintion.
request = GotoDefinitionRequest();
request.set_id(43);
request.set_method("textDocument/definition");
request.params().textDocument().set_uri("file://test.tq");
request.params().position().set_line(1);
request.params().position().set_character(5);
writer_called = false;
HandleMessage(std::move(request.GetJsonValue()), [&](JsonValue raw_response) {
GotoDefinitionResponse response(std::move(raw_response));
EXPECT_EQ(response.id(), 43);
ASSERT_FALSE(response.IsNull("result"));
Location location = response.result();
EXPECT_EQ(location.uri(), "file://base.tq");
EXPECT_EQ(location.range().start().line(), 4);
EXPECT_EQ(location.range().start().character(), 1);
EXPECT_EQ(location.range().end().line(), 4);
EXPECT_EQ(location.range().end().character(), 5);
writer_called = true;
});
EXPECT_TRUE(writer_called);
}
TEST(LanguageServerMessage, CompilationErrorSendsDiagnostics) {
DiagnosticsFiles::Scope diagnostic_files_scope;
LanguageServerData::Scope server_data_scope;
TorqueMessages::Scope messages_scope;
SourceFileMap::Scope source_file_map_scope("");
TorqueCompilerResult result;
{ Error("compilation failed somehow"); }
result.messages = std::move(TorqueMessages::Get());
result.source_file_map = SourceFileMap::Get();
bool writer_called = false;
CompilationFinished(std::move(result), [&](JsonValue raw_response) {
PublishDiagnosticsNotification notification(std::move(raw_response));
EXPECT_EQ(notification.method(), "textDocument/publishDiagnostics");
ASSERT_FALSE(notification.IsNull("params"));
EXPECT_EQ(notification.params().uri(), "<unknown>");
ASSERT_GT(notification.params().diagnostics_size(), static_cast<size_t>(0));
Diagnostic diagnostic = notification.params().diagnostics(0);
EXPECT_EQ(diagnostic.severity(), Diagnostic::kError);
EXPECT_EQ(diagnostic.message(), "compilation failed somehow");
writer_called = true;
});
EXPECT_TRUE(writer_called);
}
TEST(LanguageServerMessage, LintErrorSendsDiagnostics) {
DiagnosticsFiles::Scope diagnostic_files_scope;
TorqueMessages::Scope messages_scope;
LanguageServerData::Scope server_data_scope;
SourceFileMap::Scope sourc_file_map_scope("");
SourceId test_id = SourceFileMap::AddSource("file://test.tq");
// No compilation errors but two lint warnings.
{
SourcePosition pos1{test_id, LineAndColumn::WithUnknownOffset(0, 0),
LineAndColumn::WithUnknownOffset(0, 1)};
SourcePosition pos2{test_id, LineAndColumn::WithUnknownOffset(1, 0),
LineAndColumn::WithUnknownOffset(1, 1)};
Lint("lint error 1").Position(pos1);
Lint("lint error 2").Position(pos2);
}
TorqueCompilerResult result;
result.messages = std::move(TorqueMessages::Get());
result.source_file_map = SourceFileMap::Get();
bool writer_called = false;
CompilationFinished(std::move(result), [&](JsonValue raw_response) {
PublishDiagnosticsNotification notification(std::move(raw_response));
EXPECT_EQ(notification.method(), "textDocument/publishDiagnostics");
ASSERT_FALSE(notification.IsNull("params"));
EXPECT_EQ(notification.params().uri(), "file://test.tq");
ASSERT_EQ(notification.params().diagnostics_size(), static_cast<size_t>(2));
Diagnostic diagnostic1 = notification.params().diagnostics(0);
EXPECT_EQ(diagnostic1.severity(), Diagnostic::kWarning);
EXPECT_EQ(diagnostic1.message(), "lint error 1");
Diagnostic diagnostic2 = notification.params().diagnostics(1);
EXPECT_EQ(diagnostic2.severity(), Diagnostic::kWarning);
EXPECT_EQ(diagnostic2.message(), "lint error 2");
writer_called = true;
});
EXPECT_TRUE(writer_called);
}
TEST(LanguageServerMessage, CleanCompileSendsNoDiagnostics) {
LanguageServerData::Scope server_data_scope;
SourceFileMap::Scope sourc_file_map_scope("");
TorqueCompilerResult result;
result.source_file_map = SourceFileMap::Get();
CompilationFinished(std::move(result), [](JsonValue raw_response) {
FAIL() << "Sending unexpected response!";
});
}
TEST(LanguageServerMessage, NoSymbolsSendsEmptyResponse) {
LanguageServerData::Scope server_data_scope;
SourceFileMap::Scope sourc_file_map_scope("");
DocumentSymbolRequest request;
request.set_id(42);
request.set_method("textDocument/documentSymbol");
request.params().textDocument().set_uri("file://test.tq");
bool writer_called = false;
HandleMessage(std::move(request.GetJsonValue()), [&](JsonValue raw_response) {
DocumentSymbolResponse response(std::move(raw_response));
EXPECT_EQ(response.id(), 42);
EXPECT_EQ(response.result_size(), static_cast<size_t>(0));
writer_called = true;
});
EXPECT_TRUE(writer_called);
}
} // namespace ls
} // namespace torque
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,262 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/torque/server-data.h"
#include "src/torque/torque-compiler.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace torque {
namespace {
struct TestCompiler {
SourceFileMap::Scope file_map_scope{""};
LanguageServerData::Scope server_data_scope;
void Compile(const std::string& source) {
TorqueCompilerOptions options;
options.output_directory = "";
options.collect_language_server_data = true;
options.force_assert_statements = true;
TorqueCompilerResult result = CompileTorque(source, options);
SourceFileMap::Get() = *result.source_file_map;
LanguageServerData::Get() = std::move(result.language_server_data);
}
};
} // namespace
TEST(LanguageServer, GotoTypeDefinition) {
const std::string source =
"type void;\n"
"type never;\n"
"type T1 generates 'TNode<Object>';\n"
"type T2 generates 'TNode<Object>';\n"
"macro SomeMacro(a: T1, b: T2): T1 { return a; }";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for type 'T1' of argument 'a' on line 4.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(4, 19));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 5),
LineAndColumn::WithUnknownOffset(2, 7)}));
// Find the defintion for type 'T2' of argument 'b' on line 4.
maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(4, 26));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(3, 5),
LineAndColumn::WithUnknownOffset(3, 7)}));
}
TEST(LanguageServer, GotoTypeDefinitionExtends) {
const std::string source =
"type void;\n"
"type never;\n"
"type T1 generates 'TNode<T1>';\n"
"type T2 extends T1 generates 'TNode<T2>';";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'T1' of the extends clause on line 3.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(3, 16));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 5),
LineAndColumn::WithUnknownOffset(2, 7)}));
}
TEST(LanguageServer, GotoTypeDefinitionNoDataForFile) {
LanguageServerData::Scope server_data_scope;
SourceFileMap::Scope file_scope("");
SourceId test_id = SourceFileMap::AddSource("test.tq");
// Regression test, this step should not crash.
EXPECT_FALSE(LanguageServerData::FindDefinition(
test_id, LineAndColumn::WithUnknownOffset(0, 0)));
}
// TODO(almuthanna): This test was skipped because it causes a crash when it is
// ran on Fuchsia. This issue should be solved later on
// Ticket: https://crbug.com/1028617
#if !defined(V8_TARGET_OS_FUCHSIA)
TEST(LanguageServer, GotoLabelDefinitionInSignature) {
const std::string source =
"type void;\n"
"type never;\n"
"macro Foo(): never labels Fail {\n"
" goto Fail;\n"
"}\n"
"macro Bar(): void labels Bailout {\n"
" Foo() otherwise Bailout;\n"
"}\n";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'Bailout' of the otherwise clause on line 6.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(6, 18));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(5, 25),
LineAndColumn::WithUnknownOffset(5, 32)}));
}
#endif
TEST(LanguageServer, GotoLabelDefinitionInTryBlock) {
const std::string source =
"type void;\n"
"type never;\n"
"macro Foo(): never labels Fail {\n"
" goto Fail;\n"
"}\n"
"macro Bar(): void {\n"
" try { Foo() otherwise Bailout; }\n"
" label Bailout {}\n"
"}\n";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'Bailout' of the otherwise clause on line 6.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(6, 25));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(7, 8),
LineAndColumn::WithUnknownOffset(7, 15)}));
}
// TODO(almuthanna): This test was skipped because it causes a crash when it is
// ran on Fuchsia. This issue should be solved later on
// Ticket: https://crbug.com/1028617
#if !defined(V8_TARGET_OS_FUCHSIA)
TEST(LanguageServer, GotoDefinitionClassSuperType) {
const std::string source =
"type void;\n"
"type never;\n"
"type Tagged generates 'TNode<Object>' constexpr 'ObjectPtr';\n"
"extern class HeapObject extends Tagged {}";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'Tagged' of the 'extends' on line 3.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(3, 33));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 5),
LineAndColumn::WithUnknownOffset(2, 11)}));
}
#endif
TEST(LanguageServer, GotoLabelDefinitionInSignatureGotoStmt) {
const std::string source =
"type void;\n"
"type never;\n"
"macro Foo(): never labels Fail {\n"
" goto Fail;\n"
"}\n";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'Fail' of the goto statement on line 3.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(3, 7));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 26),
LineAndColumn::WithUnknownOffset(2, 30)}));
}
TEST(LanguageServer, GotoLabelDefinitionInTryBlockGoto) {
const std::string source =
"type void;\n"
"type never;\n"
"macro Bar(): void {\n"
" try { goto Bailout; }\n"
" label Bailout {}\n"
"}\n";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'Bailout' of the goto statement on line 3.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(3, 13));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(4, 8),
LineAndColumn::WithUnknownOffset(4, 15)}));
}
TEST(LanguageServer, GotoLabelDefinitionGotoInOtherwise) {
const std::string source =
"type void;\n"
"type never;\n"
"macro Foo(): never labels Fail {\n"
" goto Fail;\n"
"}\n"
"macro Bar(): void {\n"
" try { Foo() otherwise goto Bailout; }\n"
" label Bailout {}\n"
"}\n";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'Bailout' of the otherwise clause on line 6.
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
auto maybe_position = LanguageServerData::FindDefinition(
id, LineAndColumn::WithUnknownOffset(6, 30));
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position,
(SourcePosition{id, LineAndColumn::WithUnknownOffset(7, 8),
LineAndColumn::WithUnknownOffset(7, 15)}));
}
TEST(LanguageServer, SymbolsArePopulated) {
// Small test to ensure that the GlobalContext is correctly set in
// the LanguageServerData class and declarables are sorted into the
// SymbolsMap.
const std::string source = R"(
type void;
type never;
macro Foo(): never labels Fail {
goto Fail;
}
)";
TestCompiler compiler;
compiler.Compile(source);
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
const auto& symbols = LanguageServerData::SymbolsForSourceId(id);
ASSERT_FALSE(symbols.empty());
}
} // namespace torque
} // namespace internal
} // namespace v8

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <optional>
#include "src/torque/utils.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace torque {
TEST(TorqueUtils, FileUriDecodeIllegal) {
EXPECT_EQ(FileUriDecode("http://wrong.scheme"), std::nullopt);
EXPECT_EQ(FileUriDecode("file://wrong-escape%"), std::nullopt);
EXPECT_EQ(FileUriDecode("file://another-wrong-escape%a"), std::nullopt);
EXPECT_EQ(FileUriDecode("file://no-hex-escape%0g"), std::nullopt);
}
TEST(TorqueUtils, FileUriDecode) {
#ifdef V8_OS_WIN
EXPECT_EQ(FileUriDecode("file:///c%3A/torque/base.tq").value(),
"c:/torque/base.tq");
EXPECT_EQ(FileUriDecode("file:///d%3a/lower/hex.txt").value(),
"d:/lower/hex.txt");
#else
EXPECT_EQ(FileUriDecode("file:///some/src/file.tq").value(),
"/some/src/file.tq");
#endif
}
} // namespace torque
} // namespace internal
} // namespace v8