diff --git a/Analysis/include/Luau/Type.h b/Analysis/include/Luau/Type.h index 9b8564fb8..959ec49a8 100644 --- a/Analysis/include/Luau/Type.h +++ b/Analysis/include/Luau/Type.h @@ -374,6 +374,7 @@ struct Property bool deprecated = false; std::string deprecatedSuggestion; std::optional location = std::nullopt; + std::optional typeLocation = std::nullopt; Tags tags; std::optional documentationSymbol; @@ -381,7 +382,7 @@ struct Property // TODO: Kill all constructors in favor of `Property::rw(TypeId read, TypeId write)` and friends. Property(); Property(TypeId readTy, bool deprecated = false, const std::string& deprecatedSuggestion = "", std::optional location = std::nullopt, - const Tags& tags = {}, const std::optional& documentationSymbol = std::nullopt); + const Tags& tags = {}, const std::optional& documentationSymbol = std::nullopt, std::optional typeLocation = std::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. diff --git a/Analysis/src/Type.cpp b/Analysis/src/Type.cpp index 1859131bf..2f98e85a3 100644 --- a/Analysis/src/Type.cpp +++ b/Analysis/src/Type.cpp @@ -604,10 +604,11 @@ FunctionType::FunctionType(TypeLevel level, Scope* scope, std::vector ge Property::Property() {} Property::Property(TypeId readTy, bool deprecated, const std::string& deprecatedSuggestion, std::optional location, const Tags& tags, - const std::optional& documentationSymbol) + const std::optional& documentationSymbol, std::optional typeLocation) : deprecated(deprecated) , deprecatedSuggestion(deprecatedSuggestion) , location(location) + , typeLocation(typeLocation) , tags(tags) , documentationSymbol(documentationSymbol) , readTy(readTy) diff --git a/Analysis/src/TypeInfer.cpp b/Analysis/src/TypeInfer.cpp index a29b1e06e..1ff8b30b9 100644 --- a/Analysis/src/TypeInfer.cpp +++ b/Analysis/src/TypeInfer.cpp @@ -5403,7 +5403,7 @@ TypeId TypeChecker::resolveTypeWorker(const ScopePtr& scope, const AstType& anno std::optional tableIndexer; 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) tableIndexer = TableIndexer(resolveType(scope, *indexer->indexType), resolveType(scope, *indexer->resultType)); diff --git a/tests/TypeInfer.aliases.test.cpp b/tests/TypeInfer.aliases.test.cpp index 3f6d90fa9..de273e98b 100644 --- a/tests/TypeInfer.aliases.test.cpp +++ b/tests/TypeInfer.aliases.test.cpp @@ -1037,4 +1037,27 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "alias_expands_to_bare_reference_to_imported_ 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(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();