ls-server-data-unittest.cc 7.52 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 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 {
16
  SourceFileMap::Scope file_map_scope{""};
17 18 19 20 21 22
  LanguageServerData::Scope server_data_scope;

  void Compile(const std::string& source) {
    TorqueCompilerOptions options;
    options.output_directory = "";
    options.collect_language_server_data = true;
23
    options.force_assert_statements = true;
24

25
    TorqueCompilerResult result = CompileTorque(source, options);
26
    SourceFileMap::Get() = *result.source_file_map;
27
    LanguageServerData::Get() = std::move(result.language_server_data);
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
  }
};

}  // 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.
45
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
46 47 48 49 50 51 52 53 54 55
  auto maybe_position = LanguageServerData::FindDefinition(id, {4, 19});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 7}}));

  // Find the defintion for type 'T2' of argument 'b' on line 4.
  maybe_position = LanguageServerData::FindDefinition(id, {4, 26});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {3, 5}, {3, 7}}));
}

56 57 58 59 60 61 62 63 64 65 66
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.
67
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
68 69 70 71 72
  auto maybe_position = LanguageServerData::FindDefinition(id, {3, 16});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 7}}));
}

73 74
TEST(LanguageServer, GotoTypeDefinitionNoDataForFile) {
  LanguageServerData::Scope server_data_scope;
75
  SourceFileMap::Scope file_scope("");
76 77 78 79 80 81
  SourceId test_id = SourceFileMap::AddSource("test.tq");

  // Regression test, this step should not crash.
  EXPECT_FALSE(LanguageServerData::FindDefinition(test_id, {0, 0}));
}

82 83 84 85
// 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)
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
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() 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.
101
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
102 103 104 105
  auto maybe_position = LanguageServerData::FindDefinition(id, {6, 18});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {5, 19}, {5, 26}}));
}
106
#endif
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

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() {\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.
124
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
125 126 127 128 129
  auto maybe_position = LanguageServerData::FindDefinition(id, {6, 25});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {7, 8}, {7, 15}}));
}

130 131 132 133
// 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)
134 135 136 137 138 139 140 141 142 143 144
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.
145
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
146 147 148 149
  auto maybe_position = LanguageServerData::FindDefinition(id, {3, 33});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 11}}));
}
150
#endif
151

152 153 154 155 156 157 158 159 160 161 162 163
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.
164
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  auto maybe_position = LanguageServerData::FindDefinition(id, {3, 7});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 26}, {2, 30}}));
}

TEST(LanguageServer, GotoLabelDefinitionInTryBlockGoto) {
  const std::string source =
      "type void;\n"
      "type never;\n"
      "macro Bar() {\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.
183
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  auto maybe_position = LanguageServerData::FindDefinition(id, {3, 13});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {4, 8}, {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() {\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.
205
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
206 207 208 209 210
  auto maybe_position = LanguageServerData::FindDefinition(id, {6, 30});
  ASSERT_TRUE(maybe_position.has_value());
  EXPECT_EQ(*maybe_position, (SourcePosition{id, {7, 8}, {7, 15}}));
}

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
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);

227
  const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
228 229 230 231
  const auto& symbols = LanguageServerData::SymbolsForSourceId(id);
  ASSERT_FALSE(symbols.empty());
}

232 233 234
}  // namespace torque
}  // namespace internal
}  // namespace v8