Record table type alias property locations (#1046)

For table type aliases, records the location of the property in the
alias declaration.

This is an alternate solution to the particular case noted in #802.
Instead of tracking the type alias definition for FTVs, it tracks it for
the encompassing property instead.

Note that we still don't have positions in the following case:

```
type Func = () -> ()
```

Closes #802 (Although not completely...)
This commit is contained in:
JohnnyMorganz 2023-11-02 16:14:51 +00:00 committed by GitHub
parent 5622474b6a
commit 1a9159daff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 3 deletions

View File

@ -374,6 +374,7 @@ struct Property
bool deprecated = false; bool deprecated = false;
std::string deprecatedSuggestion; std::string deprecatedSuggestion;
std::optional<Location> location = std::nullopt; std::optional<Location> location = std::nullopt;
std::optional<Location> typeLocation = std::nullopt;
Tags tags; Tags tags;
std::optional<std::string> documentationSymbol; std::optional<std::string> documentationSymbol;
@ -381,7 +382,7 @@ struct Property
// TODO: Kill all constructors in favor of `Property::rw(TypeId read, TypeId write)` and friends. // TODO: Kill all constructors in favor of `Property::rw(TypeId read, TypeId write)` and friends.
Property(); Property();
Property(TypeId readTy, bool deprecated = false, const std::string& deprecatedSuggestion = "", std::optional<Location> location = std::nullopt, Property(TypeId readTy, bool deprecated = false, const std::string& deprecatedSuggestion = "", std::optional<Location> location = std::nullopt,
const Tags& tags = {}, const std::optional<std::string>& documentationSymbol = std::nullopt); const Tags& tags = {}, const std::optional<std::string>& documentationSymbol = std::nullopt, std::optional<Location> typeLocation = std::nullopt);
// DEPRECATED: Should only be called in non-RWP! We assert that the `readTy` is not nullopt. // DEPRECATED: Should only be called in non-RWP! We assert that the `readTy` is not nullopt.
// TODO: Kill once we don't have non-RWP. // TODO: Kill once we don't have non-RWP.

View File

@ -604,10 +604,11 @@ FunctionType::FunctionType(TypeLevel level, Scope* scope, std::vector<TypeId> ge
Property::Property() {} Property::Property() {}
Property::Property(TypeId readTy, bool deprecated, const std::string& deprecatedSuggestion, std::optional<Location> location, const Tags& tags, Property::Property(TypeId readTy, bool deprecated, const std::string& deprecatedSuggestion, std::optional<Location> location, const Tags& tags,
const std::optional<std::string>& documentationSymbol) const std::optional<std::string>& documentationSymbol, std::optional<Location> typeLocation)
: deprecated(deprecated) : deprecated(deprecated)
, deprecatedSuggestion(deprecatedSuggestion) , deprecatedSuggestion(deprecatedSuggestion)
, location(location) , location(location)
, typeLocation(typeLocation)
, tags(tags) , tags(tags)
, documentationSymbol(documentationSymbol) , documentationSymbol(documentationSymbol)
, readTy(readTy) , readTy(readTy)

View File

@ -5403,7 +5403,7 @@ TypeId TypeChecker::resolveTypeWorker(const ScopePtr& scope, const AstType& anno
std::optional<TableIndexer> tableIndexer; std::optional<TableIndexer> tableIndexer;
for (const auto& prop : table->props) for (const auto& prop : table->props)
props[prop.name.value] = {resolveType(scope, *prop.type)}; props[prop.name.value] = {resolveType(scope, *prop.type), /* deprecated: */ false, {}, std::nullopt, {}, std::nullopt, prop.location};
if (const auto& indexer = table->indexer) if (const auto& indexer = table->indexer)
tableIndexer = TableIndexer(resolveType(scope, *indexer->indexType), resolveType(scope, *indexer->resultType)); tableIndexer = TableIndexer(resolveType(scope, *indexer->indexType), resolveType(scope, *indexer->resultType));

View File

@ -1037,4 +1037,27 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "alias_expands_to_bare_reference_to_imported_
LUAU_REQUIRE_NO_ERRORS(result); LUAU_REQUIRE_NO_ERRORS(result);
} }
TEST_CASE_FIXTURE(Fixture, "table_types_record_the_property_locations")
{
CheckResult result = check(R"(
type Table = {
create: () -> ()
}
local x: Table
)");
LUAU_REQUIRE_NO_ERRORS(result);
auto ty = requireTypeAlias("Table");
auto ttv = Luau::get<Luau::TableType>(ty);
REQUIRE(ttv);
auto propIt = ttv->props.find("create");
REQUIRE(propIt != ttv->props.end());
CHECK_EQ(propIt->second.location, std::nullopt);
CHECK_EQ(propIt->second.typeLocation, Location({2, 12}, {2, 18}));
}
TEST_SUITE_END(); TEST_SUITE_END();