diff --git a/ast/Helpers.h b/ast/Helpers.h index a67df9e95d..b46f4ad629 100644 --- a/ast/Helpers.h +++ b/ast/Helpers.h @@ -244,36 +244,37 @@ class MK { core::make_type(core::Symbols::String(), value)); } - static ExpressionPtr Method(core::LocOffsets loc, core::LocOffsets declLoc, core::NameRef name, - MethodDef::ARGS_store args, ExpressionPtr rhs, + static ExpressionPtr Method(core::LocOffsets loc, core::LocOffsets declLoc, core::LocOffsets nameLoc, + core::NameRef name, MethodDef::ARGS_store args, ExpressionPtr rhs, MethodDef::Flags flags = MethodDef::Flags()) { if (args.empty() || (!isa_tree(args.back()) && !isa_tree(args.back()))) { auto blkLoc = core::LocOffsets::none(); args.emplace_back(make_expression(blkLoc, MK::Local(blkLoc, core::Names::blkArg()))); } - return make_expression(loc, declLoc, core::Symbols::todoMethod(), name, std::move(args), + return make_expression(loc, declLoc, nameLoc, core::Symbols::todoMethod(), name, std::move(args), std::move(rhs), flags); } - static ExpressionPtr SyntheticMethod(core::LocOffsets loc, core::LocOffsets declLoc, core::NameRef name, - MethodDef::ARGS_store args, ExpressionPtr rhs, + static ExpressionPtr SyntheticMethod(core::LocOffsets loc, core::LocOffsets declLoc, core::LocOffsets nameLoc, + core::NameRef name, MethodDef::ARGS_store args, ExpressionPtr rhs, MethodDef::Flags flags = MethodDef::Flags()) { flags.isRewriterSynthesized = true; - return Method(loc, declLoc, name, std::move(args), std::move(rhs), flags); + return Method(loc, declLoc, nameLoc, name, std::move(args), std::move(rhs), flags); } - static ExpressionPtr SyntheticMethod0(core::LocOffsets loc, core::LocOffsets declLoc, core::NameRef name, - ExpressionPtr rhs, MethodDef::Flags flags = MethodDef::Flags()) { + static ExpressionPtr SyntheticMethod0(core::LocOffsets loc, core::LocOffsets declLoc, core::LocOffsets nameLoc, + core::NameRef name, ExpressionPtr rhs, + MethodDef::Flags flags = MethodDef::Flags()) { MethodDef::ARGS_store args; - return SyntheticMethod(loc, declLoc, name, std::move(args), std::move(rhs), flags); + return SyntheticMethod(loc, declLoc, nameLoc, name, std::move(args), std::move(rhs), flags); } - static ExpressionPtr SyntheticMethod1(core::LocOffsets loc, core::LocOffsets declLoc, core::NameRef name, - ExpressionPtr arg0, ExpressionPtr rhs, + static ExpressionPtr SyntheticMethod1(core::LocOffsets loc, core::LocOffsets declLoc, core::LocOffsets nameLoc, + core::NameRef name, ExpressionPtr arg0, ExpressionPtr rhs, MethodDef::Flags flags = MethodDef::Flags()) { MethodDef::ARGS_store args; args.emplace_back(std::move(arg0)); - return SyntheticMethod(loc, declLoc, name, std::move(args), std::move(rhs), flags); + return SyntheticMethod(loc, declLoc, nameLoc, name, std::move(args), std::move(rhs), flags); } static ExpressionPtr ClassOrModule(core::LocOffsets loc, core::LocOffsets declLoc, ExpressionPtr name, diff --git a/ast/TreeCopying.cc b/ast/TreeCopying.cc index 35d4102872..8f74847217 100644 --- a/ast/TreeCopying.cc +++ b/ast/TreeCopying.cc @@ -44,7 +44,7 @@ ExpressionPtr deepCopy(const void *avoid, const Tag tag, const void *tree, bool case Tag::MethodDef: { auto *exp = reinterpret_cast(tree); - return make_expression(exp->loc, exp->declLoc, exp->symbol, exp->name, + return make_expression(exp->loc, exp->declLoc, exp->nameLoc, exp->symbol, exp->name, deepCopyVec(avoid, exp->args), deepCopy(avoid, exp->rhs), exp->flags); } diff --git a/ast/Trees.cc b/ast/Trees.cc index ae2fe1267b..8eae791d6a 100644 --- a/ast/Trees.cc +++ b/ast/Trees.cc @@ -164,9 +164,10 @@ ClassDef::ClassDef(core::LocOffsets loc, core::LocOffsets declLoc, core::ClassOr _sanityCheck(); } -MethodDef::MethodDef(core::LocOffsets loc, core::LocOffsets declLoc, core::MethodRef symbol, core::NameRef name, - ARGS_store args, ExpressionPtr rhs, Flags flags) - : loc(loc), declLoc(declLoc), symbol(symbol), rhs(std::move(rhs)), args(std::move(args)), name(name), flags(flags) { +MethodDef::MethodDef(core::LocOffsets loc, core::LocOffsets declLoc, core::LocOffsets nameLoc, core::MethodRef symbol, + core::NameRef name, ARGS_store args, ExpressionPtr rhs, Flags flags) + : loc(loc), declLoc(declLoc), nameLoc(nameLoc), symbol(symbol), rhs(std::move(rhs)), args(std::move(args)), + name(name), flags(flags) { categoryCounterInc("trees", "methoddef"); histogramInc("trees.methodDef.args", this->args.size()); _sanityCheck(); diff --git a/ast/Trees.h b/ast/Trees.h index 738b9ecc7e..bce8bcabad 100644 --- a/ast/Trees.h +++ b/ast/Trees.h @@ -388,6 +388,9 @@ EXPRESSION(MethodDef) { /// The range for the method declaration, including 'def' and ending /// after the closing ')' after the parameter list. core::LocOffsets declLoc; + /// The range for the name of the method itself in the method declaration, + /// excluding 'def' and the parameter list '(...)'. + core::LocOffsets nameLoc; /// Reference to the method data. core::MethodRef symbol; @@ -401,8 +404,8 @@ EXPRESSION(MethodDef) { using Flags = core::FoundMethod::Flags; Flags flags; - MethodDef(core::LocOffsets loc, core::LocOffsets declLoc, core::MethodRef symbol, core::NameRef name, - ARGS_store args, ExpressionPtr rhs, Flags flags); + MethodDef(core::LocOffsets loc, core::LocOffsets declLoc, core::LocOffsets nameLoc, core::MethodRef symbol, + core::NameRef name, ARGS_store args, ExpressionPtr rhs, Flags flags); ExpressionPtr deepCopy() const; @@ -412,7 +415,7 @@ EXPRESSION(MethodDef) { void _sanityCheck(); }; -CheckSize(MethodDef, 64, 8); +CheckSize(MethodDef, 72, 8); EXPRESSION(If) { public: diff --git a/ast/desugar/Desugar.cc b/ast/desugar/Desugar.cc index 27401c9ddf..065692069c 100644 --- a/ast/desugar/Desugar.cc +++ b/ast/desugar/Desugar.cc @@ -300,8 +300,9 @@ ExpressionPtr validateRBIBody(DesugarContext dctx, ExpressionPtr body) { return body; } -ExpressionPtr buildMethod(DesugarContext dctx, core::LocOffsets loc, core::LocOffsets declLoc, core::NameRef name, - unique_ptr &argnode, unique_ptr &body, bool isSelf) { +ExpressionPtr buildMethod(DesugarContext dctx, core::LocOffsets loc, core::LocOffsets declLoc, core::LocOffsets nameLoc, + core::NameRef name, unique_ptr &argnode, unique_ptr &body, + bool isSelf) { // Reset uniqueCounter within this scope (to keep numbers small) uint32_t uniqueCounter = 1; DesugarContext dctx1(dctx.ctx, uniqueCounter, dctx.enclosingBlockArg, declLoc, name); @@ -320,7 +321,7 @@ ExpressionPtr buildMethod(DesugarContext dctx, core::LocOffsets loc, core::LocOf ExpressionPtr desugaredBody = desugarBody(dctx2, loc, body, std::move(destructures)); desugaredBody = validateRBIBody(dctx2, move(desugaredBody)); - auto mdef = MK::Method(loc, declLoc, name, std::move(args), std::move(desugaredBody)); + auto mdef = MK::Method(loc, declLoc, nameLoc, name, std::move(args), std::move(desugaredBody)); cast_tree(mdef)->flags.isSelfMethod = isSelf; return mdef; } @@ -1515,8 +1516,8 @@ ExpressionPtr node2TreeImpl(DesugarContext dctx, unique_ptr what) }, [&](parser::DefMethod *method) { bool isSelf = false; - ExpressionPtr res = - buildMethod(dctx, method->loc, method->declLoc, method->name, method->args, method->body, isSelf); + ExpressionPtr res = buildMethod(dctx, method->loc, method->declLoc, method->nameLoc, method->name, + method->args, method->body, isSelf); result = std::move(res); }, [&](parser::DefS *method) { @@ -1528,8 +1529,8 @@ ExpressionPtr node2TreeImpl(DesugarContext dctx, unique_ptr what) } } bool isSelf = true; - ExpressionPtr res = - buildMethod(dctx, method->loc, method->declLoc, method->name, method->args, method->body, isSelf); + ExpressionPtr res = buildMethod(dctx, method->loc, method->declLoc, method->nameLoc, method->name, + method->args, method->body, isSelf); result = std::move(res); }, [&](parser::SClass *sclass) { diff --git a/cfg/CFG.cc b/cfg/CFG.cc index 7027acb1f7..0eea3a5a3d 100644 --- a/cfg/CFG.cc +++ b/cfg/CFG.cc @@ -241,7 +241,18 @@ string CFG::toString(const core::GlobalState &gs) const { string CFG::toTextualString(const core::GlobalState &gs, optional file) const { fmt::memory_buffer buf; string symbolName = this->symbol.showFullName(gs); - fmt::format_to(std::back_inserter(buf), "method {} {{\n\n", symbolName); + if (file) { + auto method = this->symbol.data(gs); + if (method->nameLoc.exists() && !method->nameLoc.empty()) { + fmt::format_to(std::back_inserter(buf), "method @ {} {} {{\n\n", + core::Loc(file.value(), method->nameLoc).showRawLineColumn(gs), symbolName); + } else { + fmt::format_to(std::back_inserter(buf), "method @ {} (full) {} {{\n\n", method->loc().showRawLineColumn(gs), + symbolName); + } + } else { + fmt::format_to(std::back_inserter(buf), "method {} {{\n\n", symbolName); + } for (auto &basicBlock : this->basicBlocks) { if (!basicBlock->backEdges.empty()) { fmt::format_to(std::back_inserter(buf), "# backedges\n"); @@ -379,16 +390,7 @@ string BasicBlock::toTextualString(const core::GlobalState &gs, optionalexprs) { string positionText = ""; if (file) { - if (exp.loc.exists() && !exp.loc.empty()) { - auto lineCol = core::Loc(file.value(), exp.loc).position(gs); - positionText = - lineCol.first.line == lineCol.second.line - ? fmt::format(" @ {}:{}-{}", lineCol.first.line, lineCol.first.column, lineCol.second.column) - : fmt::format(" @ {}:{}-{}:{}", lineCol.first.line, lineCol.first.column, lineCol.second.line, - lineCol.second.column); - } else { - positionText = " @ <>"; - } + positionText = fmt::format(" @ {}", core::Loc(file.value(), exp.loc).showRawLineColumn(gs)); } fmt::format_to(std::back_inserter(buf), " {}{} = {}\n", exp.bind.toString(gs, cfg), positionText, diff --git a/class_flatten/class_flatten.cc b/class_flatten/class_flatten.cc index 0e9dbe2918..df7c789176 100644 --- a/class_flatten/class_flatten.cc +++ b/class_flatten/class_flatten.cc @@ -111,9 +111,9 @@ class ClassFlattenWalk { ast::MethodDef::ARGS_store args; args.emplace_back(ast::make_expression(blkLoc, blkLocalVar)); - auto init = - ast::make_expression(classDef->declLoc, classDef->declLoc, sym, core::Names::staticInit(), - std::move(args), std::move(inits), ast::MethodDef::Flags()); + auto init = ast::make_expression(classDef->declLoc, classDef->declLoc, core::LocOffsets::none(), + sym, core::Names::staticInit(), std::move(args), + std::move(inits), ast::MethodDef::Flags()); ast::cast_tree_nonnull(init).flags.isRewriterSynthesized = false; ast::cast_tree_nonnull(init).flags.isSelfMethod = true; diff --git a/core/FoundDefinitions.h b/core/FoundDefinitions.h index 5a3ba2c41b..e73f7f4453 100644 --- a/core/FoundDefinitions.h +++ b/core/FoundDefinitions.h @@ -142,6 +142,7 @@ struct FoundMethod final { core::NameRef name; core::LocOffsets loc; core::LocOffsets declLoc; + core::LocOffsets nameLoc; std::vector parsedArgs; core::ArityHash arityHash; struct Flags { @@ -161,7 +162,7 @@ struct FoundMethod final { std::string toString(const core::GlobalState &gs, const FoundDefinitions &foundDefs, uint32_t id) const; }; -CheckSize(FoundMethod, 56, 8); +CheckSize(FoundMethod, 64, 8); struct FoundModifier { enum class Kind : uint8_t { diff --git a/core/GlobalState.cc b/core/GlobalState.cc index de181662a8..594d592c2c 100644 --- a/core/GlobalState.cc +++ b/core/GlobalState.cc @@ -127,7 +127,7 @@ struct MethodBuilder { }; MethodBuilder enterMethod(GlobalState &gs, ClassOrModuleRef klass, NameRef name) { - return MethodBuilder{gs, gs.enterMethodSymbol(Loc::none(), klass, name)}; + return MethodBuilder{gs, gs.enterMethodSymbol(Loc::none(), klass, name, LocOffsets::none())}; } struct ParentLinearizationInformation { @@ -303,7 +303,8 @@ void GlobalState::initEmpty() { ClassOrModuleRef klass; klass = synthesizeClass(core::Names::Constants::NoSymbol(), 0); ENFORCE(klass == Symbols::noClassOrModule()); - MethodRef method = enterMethodSymbol(Loc::none(), Symbols::noClassOrModule(), Names::noMethod()); + MethodRef method = + enterMethodSymbol(Loc::none(), Symbols::noClassOrModule(), Names::noMethod(), LocOffsets::none()); ENFORCE(method == Symbols::noMethod()); FieldRef field = enterFieldSymbol(Loc::none(), Symbols::noClassOrModule(), Names::noFieldOrStaticField()); ENFORCE(field == Symbols::noField()); @@ -581,7 +582,7 @@ void GlobalState::initEmpty() { method = enterMethod(*this, Symbols::Class(), Names::new_()).repeatedArg(Names::args()).build(); ENFORCE(method == Symbols::Class_new()); - method = enterMethodSymbol(Loc::none(), Symbols::noClassOrModule(), Names::TodoMethod()); + method = enterMethodSymbol(Loc::none(), Symbols::noClassOrModule(), Names::TodoMethod(), LocOffsets::none()); enterMethodArgumentSymbol(Loc::none(), method, Names::args()); ENFORCE(method == Symbols::todoMethod()); @@ -887,7 +888,7 @@ void GlobalState::installIntrinsics() { break; } auto countBefore = methodsUsed(); - auto method = enterMethodSymbol(Loc::none(), symbol, entry.method); + auto method = enterMethodSymbol(Loc::none(), symbol, entry.method, LocOffsets::none()); method.data(*this)->intrinsicOffset = offset + Method::FIRST_VALID_INTRINSIC_OFFSET; if (countBefore != methodsUsed()) { auto &blkArg = enterMethodArgumentSymbol(Loc::none(), method, Names::blkArg()); @@ -1192,7 +1193,7 @@ TypeArgumentRef GlobalState::enterTypeArgument(Loc loc, MethodRef owner, NameRef return result; } -MethodRef GlobalState::enterMethodSymbol(Loc loc, ClassOrModuleRef owner, NameRef name) { +MethodRef GlobalState::enterMethodSymbol(Loc loc, ClassOrModuleRef owner, NameRef name, LocOffsets nameLoc) { ClassOrModuleData ownerScope = owner.dataAllowingNone(*this); histogramInc("symbol_enter_by_name", ownerScope->members().size()); @@ -1211,6 +1212,7 @@ MethodRef GlobalState::enterMethodSymbol(Loc loc, ClassOrModuleRef owner, NameRe MethodData data = result.dataAllowingNone(*this); data->name = name; + data->nameLoc = nameLoc; data->owner = owner; data->addLoc(*this, loc); DEBUG_ONLY(categoryCounterInc("symbols", "method")); @@ -1225,7 +1227,7 @@ MethodRef GlobalState::enterNewMethodOverload(Loc sigLoc, MethodRef original, co core::Loc loc = num == 0 ? original.data(*this)->loc() : sigLoc; // use original Loc for main overload so that we get right jump-to-def for it. auto owner = original.data(*this)->owner; - auto res = enterMethodSymbol(loc, owner, name); + auto res = enterMethodSymbol(loc, owner, name, original.data(*this)->nameLoc); bool newMethod = res != original; const auto &resArguments = res.data(*this)->arguments; ENFORCE(newMethod || !resArguments.empty(), "must be at least the block arg"); @@ -2342,7 +2344,8 @@ const vector> &GlobalState::getFiles() const { MethodRef GlobalState::staticInitForClass(ClassOrModuleRef klass, Loc loc) { auto prevCount = methodsUsed(); - auto sym = enterMethodSymbol(loc, klass.data(*this)->singletonClass(*this), core::Names::staticInit()); + auto sym = enterMethodSymbol(loc, klass.data(*this)->singletonClass(*this), core::Names::staticInit(), + klass.data(*this)->loc().offsets()); if (prevCount != methodsUsed()) { auto blkLoc = core::Loc::none(loc.file()); auto &blkSym = enterMethodArgumentSymbol(blkLoc, sym, core::Names::blkArg()); @@ -2361,7 +2364,7 @@ MethodRef GlobalState::lookupStaticInitForClass(ClassOrModuleRef klass, bool all MethodRef GlobalState::staticInitForFile(Loc loc) { auto nm = freshNameUnique(core::UniqueNameKind::Namer, core::Names::staticInit(), loc.file().id()); auto prevCount = this->methodsUsed(); - auto sym = enterMethodSymbol(loc, core::Symbols::rootSingleton(), nm); + auto sym = enterMethodSymbol(loc, core::Symbols::rootSingleton(), nm, LocOffsets::none()); if (prevCount != this->methodsUsed()) { auto blkLoc = core::Loc::none(loc.file()); auto &blkSym = this->enterMethodArgumentSymbol(blkLoc, sym, core::Names::blkArg()); diff --git a/core/GlobalState.h b/core/GlobalState.h index 1040d86a83..6edef4a0ac 100644 --- a/core/GlobalState.h +++ b/core/GlobalState.h @@ -102,7 +102,7 @@ class GlobalState final { ClassOrModuleRef enterClassSymbol(Loc loc, ClassOrModuleRef owner, NameRef name); TypeMemberRef enterTypeMember(Loc loc, ClassOrModuleRef owner, NameRef name, Variance variance); TypeArgumentRef enterTypeArgument(Loc loc, MethodRef owner, NameRef name, Variance variance); - MethodRef enterMethodSymbol(Loc loc, ClassOrModuleRef owner, NameRef name); + MethodRef enterMethodSymbol(Loc loc, ClassOrModuleRef owner, NameRef name, LocOffsets nameLoc); MethodRef enterNewMethodOverload(Loc loc, MethodRef original, core::NameRef originalName, uint32_t num, const std::vector &argsToKeep); FieldRef enterFieldSymbol(Loc loc, ClassOrModuleRef owner, NameRef name); diff --git a/core/Loc.cc b/core/Loc.cc index 875eebaff1..65bc077899 100644 --- a/core/Loc.cc +++ b/core/Loc.cc @@ -235,6 +235,18 @@ string Loc::showRaw(const GlobalState &gs) const { return fmt::format("Loc {{file={} start={}:{} end={}:{}}}", path, start.line, start.column, end.line, end.column); } +string Loc::showRawLineColumn(const core::GlobalState &gs) const { + if (!this->exists()) { + return "<>"; + } + if (this->empty()) { + return "<_>"; + } + auto [start, end] = this->position(gs); + return start.line == end.line ? fmt::format("{}:{}-{}", start.line, start.column, end.column) + : fmt::format("{}:{}-{}:{}", start.line, start.column, end.line, end.column); +} + string Loc::filePosToString(const GlobalState &gs, bool showFull) const { stringstream buf; if (!file().exists()) { diff --git a/core/Loc.h b/core/Loc.h index 5a2c5cec34..ff40b76ba1 100644 --- a/core/Loc.h +++ b/core/Loc.h @@ -99,6 +99,7 @@ class Loc final { return toStringWithTabs(gs); } std::string showRaw(const GlobalState &gs) const; + std::string showRawLineColumn(const GlobalState &gs) const; std::string filePosToString(const GlobalState &gs, bool showFull = false) const; std::optional source(const GlobalState &gs) const; diff --git a/core/Symbols.cc b/core/Symbols.cc index f8f123ad07..d5b3034c61 100644 --- a/core/Symbols.cc +++ b/core/Symbols.cc @@ -1840,7 +1840,7 @@ void ClassOrModule::recordRequiredAncestorInternal(GlobalState &gs, ClassOrModul // We store the required ancestors into a fake property called `` auto ancestors = this->findMethod(gs, prop); if (!ancestors.exists()) { - ancestors = gs.enterMethodSymbol(ancestor.loc, this->ref(gs), prop); + ancestors = gs.enterMethodSymbol(ancestor.loc, this->ref(gs), prop, LocOffsets::none()); ancestors.data(gs)->locs_.clear(); // Remove the original location // Create the return type tuple to store RequiredAncestor.symbol @@ -2140,7 +2140,8 @@ void Method::sanityCheck(const GlobalState &gs) const { return; } MethodRef current = this->ref(gs); - MethodRef current2 = const_cast(gs).enterMethodSymbol(this->loc(), this->owner, this->name); + MethodRef current2 = + const_cast(gs).enterMethodSymbol(this->loc(), this->owner, this->name, this->nameLoc); ENFORCE_NO_TIMER(current == current2); for (auto &tp : typeArguments()) { diff --git a/core/Symbols.h b/core/Symbols.h index f6efe5b9cd..c4792795b1 100644 --- a/core/Symbols.h +++ b/core/Symbols.h @@ -152,6 +152,7 @@ class Method final { ClassOrModuleRef owner; NameRef name; + core::LocOffsets nameLoc; ClassOrModuleRef rebind; Flags flags; // We store an offset into the intrinsic table used by calls.cc; the only @@ -188,7 +189,7 @@ class Method final { InlinedVector locs_; std::unique_ptr> typeArgs; }; -CheckSize(Method, 136, 8); +CheckSize(Method, 144, 8); // Contains a field or a static field class Field final { diff --git a/core/serialize/serialize.cc b/core/serialize/serialize.cc index 056ba30488..5b17dcd616 100644 --- a/core/serialize/serialize.cc +++ b/core/serialize/serialize.cc @@ -1241,6 +1241,7 @@ void SerializerImpl::pickle(Pickler &p, const ast::ExpressionPtr &what) { auto &c = ast::cast_tree_nonnull(what); pickle(p, c.loc); pickle(p, c.declLoc); + pickle(p, c.nameLoc); uint8_t flags; static_assert(sizeof(flags) == sizeof(c.flags)); // Can replace this with std::bit_cast in C++20 @@ -1518,6 +1519,7 @@ ast::ExpressionPtr SerializerImpl::unpickleExpr(serialize::UnPickler &p, const G case ast::Tag::MethodDef: { auto loc = unpickleLocOffsets(p); auto declLoc = unpickleLocOffsets(p); + auto nameLoc = unpickleLocOffsets(p); auto flagsU1 = p.getU1(); ast::MethodDef::Flags flags; static_assert(sizeof(flags) == sizeof(flagsU1)); @@ -1531,7 +1533,7 @@ ast::ExpressionPtr SerializerImpl::unpickleExpr(serialize::UnPickler &p, const G for (auto &arg : args) { arg = unpickleExpr(p, gs); } - auto ret = ast::MK::SyntheticMethod(loc, declLoc, name, std::move(args), std::move(rhs)); + auto ret = ast::MK::SyntheticMethod(loc, declLoc, nameLoc, name, std::move(args), std::move(rhs)); { auto &method = ast::cast_tree_nonnull(ret); diff --git a/namer/namer.cc b/namer/namer.cc index 8c0c41339d..97a39d7ff3 100644 --- a/namer/namer.cc +++ b/namer/namer.cc @@ -200,6 +200,7 @@ class SymbolFinder { foundMethod.name = method.name; foundMethod.loc = method.loc; foundMethod.declLoc = method.declLoc; + foundMethod.nameLoc = method.nameLoc; foundMethod.flags = method.flags; foundMethod.parsedArgs = ast::ArgParsing::parseArgs(method.args); foundMethod.arityHash = ast::ArgParsing::hashArgs(ctx, foundMethod.parsedArgs); @@ -338,6 +339,7 @@ class SymbolFinder { foundMethod.name = fromName; foundMethod.loc = send.loc; foundMethod.declLoc = send.loc; + foundMethod.nameLoc = send.loc; foundMethod.arityHash = core::ArityHash::aliasMethodHash(); foundDefs->addMethod(move(foundMethod)); } @@ -816,7 +818,7 @@ class SymbolDefiner { auto &parsedArgs = method.parsedArgs; auto symTableSize = ctx.state.methodsUsed(); auto declLoc = ctx.locAt(method.declLoc); - auto sym = ctx.state.enterMethodSymbol(declLoc, owner, method.name); + auto sym = ctx.state.enterMethodSymbol(declLoc, owner, method.name, method.nameLoc); const bool isNewSymbol = symTableSize != ctx.state.methodsUsed(); if (!isNewSymbol) { // See if this is == to the method we're defining now, or if we have a redefinition error. @@ -828,7 +830,7 @@ class SymbolDefiner { paramMismatchErrors(ctx.withOwner(sym), declLoc, parsedArgs); ctx.state.mangleRenameSymbol(sym, method.name); // Re-enter a new symbol. - sym = ctx.state.enterMethodSymbol(declLoc, owner, method.name); + sym = ctx.state.enterMethodSymbol(declLoc, owner, method.name, method.nameLoc); } else { // ...unless it's an intrinsic, because we allow multiple incompatible definitions of those in code // TODO(jvilk): Wouldn't this always fail since `!sym.exists()`? @@ -1022,8 +1024,8 @@ class SymbolDefiner { symbolData->flags.isSealed = true; auto classOfKlass = symbolData->singletonClass(ctx); - auto sealedSubclasses = - ctx.state.enterMethodSymbol(ctx.locAt(mod.loc), classOfKlass, core::Names::sealedSubclasses()); + auto sealedSubclasses = ctx.state.enterMethodSymbol( + ctx.locAt(mod.loc), classOfKlass, core::Names::sealedSubclasses(), core::LocOffsets::none()); auto &blkArg = ctx.state.enterMethodArgumentSymbol(core::Loc::none(), sealedSubclasses, core::Names::blkArg()); blkArg.flags.isBlock = true; diff --git a/parser/Builder.cc b/parser/Builder.cc index 942a5339d1..399da3b648 100644 --- a/parser/Builder.cc +++ b/parser/Builder.cc @@ -846,11 +846,12 @@ class Builder::Impl { core::LocOffsets declLoc = head->loc.join(maybe_loc(args)); core::LocOffsets loc = head->loc.join(body->loc); std::string name = head->name.toString(gs_); + auto nameLoc = head->nameLoc; checkEndlessSetter(name, declLoc); checkReservedForNumberedParameters(name, declLoc); - return make_unique(loc, declLoc, gs_.enterNameUTF8(name), std::move(args), std::move(body)); + return make_unique(loc, declLoc, nameLoc, gs_.enterNameUTF8(name), std::move(args), std::move(body)); } unique_ptr defEndlessSingleton(unique_ptr defHead, unique_ptr args, const token *equal, @@ -863,7 +864,8 @@ class Builder::Impl { checkEndlessSetter(name, declLoc); checkReservedForNumberedParameters(name, declLoc); - return make_unique(loc, declLoc, std::move(head->definee), head->name, std::move(args), std::move(body)); + return make_unique(loc, declLoc, std::move(head->definee), head->nameLoc, head->name, std::move(args), + std::move(body)); } unique_ptr defMethod(unique_ptr defHead, unique_ptr args, unique_ptr body, @@ -872,10 +874,11 @@ class Builder::Impl { core::LocOffsets declLoc = head->loc.join(maybe_loc(args)); core::LocOffsets loc = head->loc.join(tokLoc(end)); std::string name = head->name.toString(gs_); + auto nameLoc = head->nameLoc; checkReservedForNumberedParameters(name, declLoc); - return make_unique(loc, declLoc, gs_.enterNameUTF8(name), std::move(args), std::move(body)); + return make_unique(loc, declLoc, nameLoc, gs_.enterNameUTF8(name), std::move(args), std::move(body)); } unique_ptr defModule(const token *module, unique_ptr name, unique_ptr body, const token *end_) { @@ -886,8 +889,9 @@ class Builder::Impl { unique_ptr defnHead(const token *def, const token *name) { core::LocOffsets declLoc = tokLoc(def, name); + auto nameLoc = tokLoc(name); - return make_unique(declLoc, gs_.enterNameUTF8(name->view())); + return make_unique(declLoc, nameLoc, gs_.enterNameUTF8(name->view())); } unique_ptr def_sclass(const token *class_, const token *lshft_, unique_ptr expr, unique_ptr body, @@ -898,19 +902,20 @@ class Builder::Impl { } unique_ptr defnHeadError(const token *def) { - return make_unique(tokLoc(def), core::Names::methodDefNameMissing()); + return make_unique(tokLoc(def), core::LocOffsets::none(), core::Names::methodDefNameMissing()); } unique_ptr defsHead(const token *def, unique_ptr definee, const token *dot, const token *name) { core::LocOffsets declLoc = tokLoc(def, name); - return make_unique(declLoc, std::move(definee), gs_.enterNameUTF8(name->view())); + return make_unique(declLoc, std::move(definee), tokLoc(name), gs_.enterNameUTF8(name->view())); } unique_ptr defsHeadError(const token *def, unique_ptr definee, const token *dot) { core::LocOffsets declLoc = tokLoc(def, dot); - return make_unique(declLoc, std::move(definee), core::Names::methodDefNameMissing()); + return make_unique(declLoc, std::move(definee), core::LocOffsets::none(), + core::Names::methodDefNameMissing()); } unique_ptr defSingleton(unique_ptr defHead, unique_ptr args, unique_ptr body, @@ -924,7 +929,8 @@ class Builder::Impl { } checkReservedForNumberedParameters(head->name.toString(gs_), declLoc); - return make_unique(loc, declLoc, std::move(head->definee), head->name, std::move(args), std::move(body)); + return make_unique(loc, declLoc, std::move(head->definee), head->nameLoc, head->name, std::move(args), + std::move(body)); } unique_ptr empty_else(const token *tok) { diff --git a/parser/tools/generate_ast.cc b/parser/tools/generate_ast.cc index 9497b7e0e0..f6328988f1 100644 --- a/parser/tools/generate_ast.cc +++ b/parser/tools/generate_ast.cc @@ -194,6 +194,7 @@ NodeDef nodes[] = { "DefMethod", "def", vector({{"declLoc", FieldType::Loc}, + {"nameLoc", FieldType::Loc}, {"name", FieldType::Name}, {"args", FieldType::Node}, {"body", FieldType::Node}}), @@ -205,13 +206,14 @@ NodeDef nodes[] = { vector({{"value", FieldType::Node}}), }, // def name, instance method def - {"DefnHead", "defnhead", vector({{"name", FieldType::Name}})}, + {"DefnHead", "defnhead", vector({{"nameLoc", FieldType::Loc}, {"name", FieldType::Name}})}, // def .name singleton-class method def { "DefS", "defs", vector({{"declLoc", FieldType::Loc}, {"singleton", FieldType::Node}, + {"nameLoc", FieldType::Loc}, {"name", FieldType::Name}, {"args", FieldType::Node}, {"body", FieldType::Node}}), @@ -222,6 +224,7 @@ NodeDef nodes[] = { "defshead", vector({ {"definee", FieldType::Node}, + {"nameLoc", FieldType::Loc}, {"name", FieldType::Name}, }), }, @@ -1040,10 +1043,12 @@ void emitNodeClassfile(ostream &out, NodeDef &node) { << maybeComma << "\\n\", " << arg.name << ");\n"; break; case FieldType::Loc: + out << "{\n"; out << " bool showFull = true;"; out << R"( fmt::format_to(std::back_inserter(buf), "\")" << arg.name << R"(\" : \"{}\")" << maybeComma << "\\n\", " << "core::Loc(file, " << arg.name << ").filePosToString(gs, showFull));\n"; + out << "}\n"; break; case FieldType::Bool: out << R"( fmt::format_to(std::back_inserter(buf), "\")" << arg.name << R"(\" : \"{}\")" diff --git a/resolver/resolver.cc b/resolver/resolver.cc index 921547c500..381edda7c7 100644 --- a/resolver/resolver.cc +++ b/resolver/resolver.cc @@ -880,7 +880,8 @@ class ResolveConstantsWalk { auto ancestorType = core::make_type(unresolvedPath->first, move(unresolvedPath->second)); - auto uaSym = ctx.state.enterMethodSymbol(core::Loc::none(), item.klass, core::Names::unresolvedAncestors()); + auto uaSym = ctx.state.enterMethodSymbol(core::Loc::none(), item.klass, core::Names::unresolvedAncestors(), + core::LocOffsets::none()); // Add a fake block argument so that this method symbol passes sanity checks auto &arg = ctx.state.enterMethodArgumentSymbol(core::Loc::none(), uaSym, core::Names::blkArg()); @@ -1073,7 +1074,7 @@ class ResolveConstantsWalk { // We never stored a mixin in this symbol // Create a the fake property that will hold the mixed in modules mixMethod = gs.enterMethodSymbol(core::Loc{todo.file, send->loc}, ownerKlass, - core::Names::mixedInClassMethods()); + core::Names::mixedInClassMethods(), core::LocOffsets::none()); mixMethod.data(gs)->resultType = core::make_type(vector{}); // Create a dummy block argument to satisfy sanitycheck during GlobalState::expandNames @@ -1873,6 +1874,7 @@ class ResolveTypeMembersAndFieldsWalk { core::ClassOrModuleRef owner; core::LocOffsets loc; core::LocOffsets toNameLoc; + // FIXME[alias-support]: Add a fromNameLoc field here core::NameRef toName; core::NameRef fromName; }; @@ -2438,7 +2440,8 @@ class ResolveTypeMembersAndFieldsWalk { return; } - auto alias = ctx.state.enterMethodSymbol(ctx.locAt(job.loc), job.owner, job.fromName); + // FIXME[alias-support]: Use job.fromNameLoc here for the last argument. + auto alias = ctx.state.enterMethodSymbol(ctx.locAt(job.loc), job.owner, job.fromName, job.loc); alias.data(ctx)->resultType = core::make_type(core::SymbolRef(toMethod)); // Add a fake keyword argument to remember the toName (for fast path hashing). diff --git a/rewriter/AttrReader.cc b/rewriter/AttrReader.cc index 4e783ef9ca..7cb08f6877 100644 --- a/rewriter/AttrReader.cc +++ b/rewriter/AttrReader.cc @@ -301,7 +301,7 @@ vector AttrReader::run(core::MutableContext ctx, ast::Send * if (sigIsUnchecked(ctx, sig)) { flags.isAttrReader = true; } - auto reader = ast::MK::SyntheticMethod0(loc, loc, name, ast::MK::Instance(argLoc, varName), flags); + auto reader = ast::MK::SyntheticMethod0(loc, loc, argLoc, name, ast::MK::Instance(argLoc, varName), flags); stats.emplace_back(std::move(reader)); } } @@ -337,7 +337,8 @@ vector AttrReader::run(core::MutableContext ctx, ast::Send * } else { body = ast::MK::Assign(loc, ast::MK::Instance(argLoc, varName), ast::MK::Local(loc, name)); } - stats.emplace_back(ast::MK::SyntheticMethod1(loc, loc, setName, ast::MK::Local(argLoc, name), move(body))); + stats.emplace_back( + ast::MK::SyntheticMethod1(loc, loc, argLoc, setName, ast::MK::Local(argLoc, name), move(body))); } } diff --git a/rewriter/Command.cc b/rewriter/Command.cc index 55e63c6012..05db336cc1 100644 --- a/rewriter/Command.cc +++ b/rewriter/Command.cc @@ -84,8 +84,8 @@ void Command::run(core::MutableContext ctx, ast::ClassDef *klass) { ast::MethodDef::Flags flags; flags.isSelfMethod = true; flags.discardDef = true; - auto selfCall = ast::MK::SyntheticMethod(call->loc, call->loc, call->name, std::move(newArgs), - ast::MK::UntypedNil(call->loc), flags); + auto selfCall = ast::MK::SyntheticMethod(call->loc, call->loc, core::LocOffsets::none(), call->name, + std::move(newArgs), ast::MK::UntypedNil(call->loc), flags); klass->rhs.insert(klass->rhs.begin() + i + 1, sig->deepCopy()); klass->rhs.insert(klass->rhs.begin() + i + 2, std::move(selfCall)); diff --git a/rewriter/DSLBuilder.cc b/rewriter/DSLBuilder.cc index f24fd2fa43..15203a5cec 100644 --- a/rewriter/DSLBuilder.cc +++ b/rewriter/DSLBuilder.cc @@ -93,7 +93,7 @@ vector DSLBuilder::run(core::MutableContext ctx, ast::Send * auto default_ = ast::MK::UntypedNil(loc); arg = ast::MK::OptionalArg(loc, move(arg), move(default_)); } - auto defSelfProp = ast::MK::SyntheticMethod1(loc, loc, name, move(arg), ast::MK::EmptyTree(), flags); + auto defSelfProp = ast::MK::SyntheticMethod1(loc, loc, nameLoc, name, move(arg), ast::MK::EmptyTree(), flags); ast::cast_tree(defSelfProp)->flags.isSelfMethod = true; stats.emplace_back(move(defSelfProp)); } @@ -106,13 +106,15 @@ vector DSLBuilder::run(core::MutableContext ctx, ast::Send * // def self.get_ core::NameRef getName = ctx.state.enterNameUTF8("get_" + name.show(ctx)); stats.emplace_back(ast::MK::Sig0(loc, ASTUtil::dupType(type))); - auto defSelfGetProp = ast::MK::SyntheticMethod(loc, loc, getName, {}, ast::MK::RaiseUnimplemented(loc), flags); + auto defSelfGetProp = + ast::MK::SyntheticMethod(loc, loc, nameLoc, getName, {}, ast::MK::RaiseUnimplemented(loc), flags); ast::cast_tree(defSelfGetProp)->flags.isSelfMethod = true; stats.emplace_back(move(defSelfGetProp)); // def () stats.emplace_back(ast::MK::Sig0(loc, ASTUtil::dupType(type))); - stats.emplace_back(ast::MK::SyntheticMethod(loc, loc, name, {}, ast::MK::RaiseUnimplemented(loc), flags)); + stats.emplace_back( + ast::MK::SyntheticMethod(loc, loc, nameLoc, name, {}, ast::MK::RaiseUnimplemented(loc), flags)); } return stats; diff --git a/rewriter/DefDelegator.cc b/rewriter/DefDelegator.cc index 2aebda0a3a..55e70bb274 100644 --- a/rewriter/DefDelegator.cc +++ b/rewriter/DefDelegator.cc @@ -9,7 +9,7 @@ using namespace std; namespace sorbet::rewriter { /// Generate method stub and sig for the delegator method -void generateStub(vector &methodStubs, const core::LocOffsets &loc, +void generateStub(vector &methodStubs, const core::LocOffsets &loc, core::LocOffsets nameLoc, const core::NameRef &methodName) { // sig {params(arg0: T.untyped, blk: Proc).returns(T.untyped)} auto sigArgs = ast::MK::SendArgs(ast::MK::Symbol(loc, core::Names::arg0()), ast::MK::Untyped(loc), @@ -24,7 +24,7 @@ void generateStub(vector &methodStubs, const core::LocOffset args.emplace_back(ast::make_expression(loc, ast::MK::Local(loc, core::Names::blkArg()))); methodStubs.push_back( - ast::MK::SyntheticMethod(loc, loc, methodName, std::move(args), ast::MK::RaiseUnimplemented(loc))); + ast::MK::SyntheticMethod(loc, loc, nameLoc, methodName, std::move(args), ast::MK::RaiseUnimplemented(loc))); } /// Handle #def_delegator for a single delegate method @@ -53,6 +53,7 @@ vector runDefDelegator(core::MutableContext ctx, const ast:: } core::NameRef methodName = method->asSymbol(); + auto nameLoc = method->loc; if (send->numPosArgs() == 3) { auto *alias = ast::cast_tree(send->getPosArg(2)); @@ -61,9 +62,10 @@ vector runDefDelegator(core::MutableContext ctx, const ast:: } methodName = alias->asSymbol(); + nameLoc = alias->loc; } - generateStub(methodStubs, loc, methodName); + generateStub(methodStubs, loc, nameLoc, methodName); // Include the original call to def_delegator so sorbet will still type-check it // and throw errors if the class (or its parent) didn't `extend Forwardable` @@ -100,7 +102,7 @@ vector runDefDelegators(core::MutableContext ctx, const ast: continue; } - generateStub(methodStubs, loc, method->asSymbol()); + generateStub(methodStubs, loc, method->loc, method->asSymbol()); } // Include the original call to def_delegators so sorbet will still type-check it diff --git a/rewriter/Delegate.cc b/rewriter/Delegate.cc index 602310e1ac..0b819d8754 100644 --- a/rewriter/Delegate.cc +++ b/rewriter/Delegate.cc @@ -95,6 +95,7 @@ vector Delegate::run(core::MutableContext ctx, const ast::Se return empty; } core::NameRef methodName; + core::LocOffsets nameLoc = lit->loc; if (prefixNode) { if (useToAsPrefix && (beforeUnderscore.empty() || beforeUnderscore[0] == '@')) { // Active Support raises at runtime for these cases @@ -117,7 +118,8 @@ vector Delegate::run(core::MutableContext ctx, const ast::Se args.emplace_back(ast::MK::RestArg(loc, ast::MK::Local(loc, core::Names::arg0()))); args.emplace_back(ast::make_expression(loc, ast::MK::Local(loc, core::Names::blkArg()))); - methodStubs.push_back(ast::MK::SyntheticMethod(loc, loc, methodName, std::move(args), ast::MK::EmptyTree())); + methodStubs.push_back( + ast::MK::SyntheticMethod(loc, loc, nameLoc, methodName, std::move(args), ast::MK::EmptyTree())); } return methodStubs; diff --git a/rewriter/Flatfiles.cc b/rewriter/Flatfiles.cc index 9d753d1ea0..be650273e9 100644 --- a/rewriter/Flatfiles.cc +++ b/rewriter/Flatfiles.cc @@ -10,16 +10,16 @@ using namespace std; namespace sorbet::rewriter { -optional getFieldName(core::MutableContext ctx, ast::Send &send) { +optional> getFieldName(core::MutableContext ctx, ast::Send &send) { if (auto propLit = ast::cast_tree(send.getPosArg(0))) { if (propLit->isSymbol()) { - return propLit->asSymbol(); + return make_pair(propLit->asSymbol(), propLit->loc); } } if (send.numPosArgs() >= 2) { if (auto propLit = ast::cast_tree(send.getPosArg(1))) { if (propLit->isSymbol()) { - return propLit->asSymbol(); + return make_pair(propLit->asSymbol(), propLit->loc); } } } @@ -42,19 +42,21 @@ void handleFieldDefinition(core::MutableContext ctx, ast::ExpressionPtr &stat, v !send->recv.isSelfReference() || send->numPosArgs() < 1) { return; } - auto name = getFieldName(ctx, *send); - if (!name) { + auto nameAndLoc = getFieldName(ctx, *send); + if (!nameAndLoc) { return; } + auto [name, nameLoc] = nameAndLoc.value(); methods.emplace_back(ast::MK::Sig0(send->loc, ast::MK::Untyped(send->loc))); - methods.emplace_back(ast::MK::SyntheticMethod0(send->loc, send->loc, *name, ast::MK::Nil(send->loc))); + + methods.emplace_back(ast::MK::SyntheticMethod0(send->loc, send->loc, nameLoc, name, ast::MK::Nil(send->loc))); auto var = ast::MK::Local(send->loc, core::Names::arg0()); - auto setName = name->addEq(ctx); + auto setName = name.addEq(ctx); methods.emplace_back(ast::MK::Sig1(send->loc, ast::MK::Symbol(send->loc, core::Names::arg0()), ast::MK::Untyped(send->loc), ast::MK::Untyped(send->loc))); methods.emplace_back( - ast::MK::SyntheticMethod1(send->loc, send->loc, setName, move(var), ast::MK::Nil(send->loc))); + ast::MK::SyntheticMethod1(send->loc, send->loc, nameLoc, setName, move(var), ast::MK::Nil(send->loc))); } } diff --git a/rewriter/Mattr.cc b/rewriter/Mattr.cc index 492cdfbd14..ea43f3f55e 100644 --- a/rewriter/Mattr.cc +++ b/rewriter/Mattr.cc @@ -95,7 +95,7 @@ vector Mattr::run(core::MutableContext ctx, const ast::Send auto loc = lit->loc; if (doReaders) { auto sig = ast::MK::Sig0(loc, ast::MK::Untyped(loc)); - auto def = ast::MK::SyntheticMethod0(loc, loc, lit->asSymbol(), ast::MK::EmptyTree()); + auto def = ast::MK::SyntheticMethod0(loc, loc, loc, lit->asSymbol(), ast::MK::EmptyTree()); ast::cast_tree_nonnull(def).flags.isSelfMethod = true; if (instanceReader) { addInstanceCounterPart(result, sig, def); @@ -106,7 +106,7 @@ vector Mattr::run(core::MutableContext ctx, const ast::Send if (doWriters) { auto sig = ast::MK::Sig1(loc, ast::MK::Symbol(loc, core::Names::arg0()), ast::MK::Untyped(loc), ast::MK::Untyped(loc)); - auto def = ast::MK::SyntheticMethod1(loc, loc, lit->asSymbol().addEq(ctx), + auto def = ast::MK::SyntheticMethod1(loc, loc, loc, lit->asSymbol().addEq(ctx), ast::MK::Local(loc, core::Names::arg0()), ast::MK::EmptyTree()); ast::cast_tree_nonnull(def).flags.isSelfMethod = true; if (instanceWriter) { @@ -120,7 +120,7 @@ vector Mattr::run(core::MutableContext ctx, const ast::Send // from being generated. auto sig = ast::MK::Sig0( loc, ast::MK::UnresolvedConstant(loc, ast::MK::T(loc), core::Names::Constants::Boolean())); - auto def = ast::MK::SyntheticMethod0(loc, loc, lit->asSymbol().addQuestion(ctx), ast::MK::False(loc)); + auto def = ast::MK::SyntheticMethod0(loc, loc, loc, lit->asSymbol().addQuestion(ctx), ast::MK::False(loc)); ast::cast_tree_nonnull(def).flags.isSelfMethod = true; if (instanceReader && instancePredicate) { addInstanceCounterPart(result, sig, def); diff --git a/rewriter/Minitest.cc b/rewriter/Minitest.cc index 4bdca06628..409df6f879 100644 --- a/rewriter/Minitest.cc +++ b/rewriter/Minitest.cc @@ -193,7 +193,8 @@ ast::ExpressionPtr runUnderEach(core::MutableContext ctx, core::NameRef eachName if (send->fun == core::Names::it() && send->numPosArgs() == 1 && send->hasBlock() && send->block()->args.size() == 0) { // we use this for the name of our test - auto argString = to_s(ctx, send->getPosArg(0)); + auto &arg0 = send->getPosArg(0); + auto argString = to_s(ctx, arg0); auto name = ctx.state.enterNameUTF8(""); // pull constants out of the block @@ -220,7 +221,8 @@ ast::ExpressionPtr runUnderEach(core::MutableContext ctx, core::NameRef eachName auto each = ast::MK::Send0Block(send->loc, iteratee.deepCopy(), core::Names::each(), send->loc.copyWithZeroLength(), move(blk)); // put that into a method def named the appropriate thing - auto method = addSigVoid(ast::MK::SyntheticMethod0(send->loc, send->loc, move(name), move(each))); + auto method = + addSigVoid(ast::MK::SyntheticMethod0(send->loc, send->loc, arg0.loc(), move(name), move(each))); // add back any moved constants return constantMover.addConstantsToExpression(send->loc, move(method)); } @@ -356,8 +358,8 @@ ast::ExpressionPtr runSingle(core::MutableContext ctx, bool isClass, ast::Send * auto name = send->fun == core::Names::after() ? core::Names::afterAngles() : core::Names::initialize(); ConstantMover constantMover; ast::TreeWalk::apply(ctx, constantMover, block->body); - auto method = addSigVoid( - ast::MK::SyntheticMethod0(send->loc, send->loc, name, prepareBody(ctx, isClass, std::move(block->body)))); + auto method = addSigVoid(ast::MK::SyntheticMethod0(send->loc, send->loc, send->funLoc, name, + prepareBody(ctx, isClass, std::move(block->body)))); return constantMover.addConstantsToExpression(send->loc, move(method)); } @@ -387,7 +389,7 @@ ast::ExpressionPtr runSingle(core::MutableContext ctx, bool isClass, ast::Send * ast::TreeWalk::apply(ctx, constantMover, block->body); auto name = ctx.state.enterNameUTF8(""); const bool bodyIsClass = false; - auto method = addSigVoid(ast::MK::SyntheticMethod0(send->loc, send->loc, std::move(name), + auto method = addSigVoid(ast::MK::SyntheticMethod0(send->loc, send->loc, arg.loc(), std::move(name), prepareBody(ctx, bodyIsClass, std::move(block->body)))); method = ast::MK::InsSeq1(send->loc, send->getPosArg(0).deepCopy(), move(method)); return constantMover.addConstantsToExpression(send->loc, move(method)); diff --git a/rewriter/MixinEncryptedProp.cc b/rewriter/MixinEncryptedProp.cc index 31b8ac9793..6d202f4d72 100644 --- a/rewriter/MixinEncryptedProp.cc +++ b/rewriter/MixinEncryptedProp.cc @@ -70,10 +70,10 @@ vector MixinEncryptedProp::run(core::MutableContext ctx, ast // Compute the getters stats.emplace_back(ast::MK::Sig(loc, {}, mkNilableString(loc))); - stats.emplace_back(ASTUtil::mkGet(ctx, loc, name, ast::MK::RaiseUnimplemented(loc))); + stats.emplace_back(ASTUtil::mkGet(ctx, loc, name, nameLoc, ast::MK::RaiseUnimplemented(loc))); stats.emplace_back(ast::MK::Sig(loc, {}, mkNilableEncryptedValue(ctx, loc))); - stats.emplace_back(ASTUtil::mkGet(ctx, loc, enc_name, ast::MK::RaiseUnimplemented(loc))); + stats.emplace_back(ASTUtil::mkGet(ctx, loc, enc_name, nameLoc, ast::MK::RaiseUnimplemented(loc))); core::NameRef setName = name.addEq(ctx); core::NameRef setEncName = enc_name.addEq(ctx); diff --git a/rewriter/ModuleFunction.cc b/rewriter/ModuleFunction.cc index d20e332008..196ee9955d 100644 --- a/rewriter/ModuleFunction.cc +++ b/rewriter/ModuleFunction.cc @@ -138,7 +138,8 @@ vector ModuleFunction::run(core::MutableContext ctx, ast::Se ast::MethodDef::ARGS_store args; args.emplace_back(ast::MK::RestArg(loc, ast::MK::Local(loc, core::Names::arg0()))); args.emplace_back(ast::make_expression(loc, ast::MK::Local(loc, core::Names::blkArg()))); - auto methodDef = ast::MK::SyntheticMethod(loc, loc, methodName, std::move(args), ast::MK::EmptyTree()); + auto methodDef = + ast::MK::SyntheticMethod(loc, loc, lit->loc, methodName, std::move(args), ast::MK::EmptyTree()); ast::cast_tree_nonnull(methodDef).flags.isSelfMethod = true; stats.emplace_back(std::move(methodDef)); } else { diff --git a/rewriter/Prop.cc b/rewriter/Prop.cc index 8f8d2970dc..cb4d5576c0 100644 --- a/rewriter/Prop.cc +++ b/rewriter/Prop.cc @@ -378,21 +378,22 @@ vector processProp(core::MutableContext ctx, PropInfo &ret, auto assertTypeMatches = ast::MK::AssertType(computedByMethodNameLoc, std::move(sendComputedMethod), ASTUtil::dupType(getType)); auto insSeq = ast::MK::InsSeq1(loc, std::move(assertTypeMatches), ast::MK::RaiseUnimplemented(loc)); - nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, std::move(insSeq))); + nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, nameLoc, std::move(insSeq))); } else if (propContext.needsRealPropBodies && propContext.classDefKind == ast::ClassDef::Kind::Module) { // Not all modules include Kernel, can't make an initialize, etc. so we're punting on props in modules rn. - nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, ast::MK::RaiseUnimplemented(loc))); + nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, nameLoc, ast::MK::RaiseUnimplemented(loc))); } else if (ret.ifunset == nullptr) { if (knownNonModel(propContext.syntacticSuperClass)) { ast::MethodDef::Flags flags; flags.isAttrReader = true; if (wantTypedInitialize(propContext.syntacticSuperClass)) { - nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, ast::MK::Instance(nameLoc, ivarName), flags)); + nodes.emplace_back( + ASTUtil::mkGet(ctx, loc, name, nameLoc, ast::MK::Instance(nameLoc, ivarName), flags)); } else { // Need to hide the instance variable access, because there wasn't a typed constructor to declare it auto ivarGet = ast::MK::Send1(loc, ast::MK::Self(loc), core::Names::instanceVariableGet(), locZero, ast::MK::Symbol(nameLoc, ivarName)); - nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, std::move(ivarGet), flags)); + nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, nameLoc, std::move(ivarGet), flags)); } } else if (propContext.needsRealPropBodies) { ast::MethodDef::Flags flags; @@ -414,12 +415,12 @@ vector processProp(core::MutableContext ctx, PropInfo &ret, ast::MK::Self(loc), ast::MK::Symbol(nameLoc, name), std::move(arg2)); auto insSeq = ast::MK::InsSeq1(loc, std::move(assign), std::move(propGetLogic)); - nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, std::move(insSeq), flags)); + nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, nameLoc, std::move(insSeq), flags)); } else { - nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, ast::MK::RaiseUnimplemented(loc))); + nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, nameLoc, ast::MK::RaiseUnimplemented(loc))); } } else { - nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, ast::MK::RaiseUnimplemented(loc))); + nodes.emplace_back(ASTUtil::mkGet(ctx, loc, name, nameLoc, ast::MK::RaiseUnimplemented(loc))); } core::NameRef setName = name.addEq(ctx); @@ -494,8 +495,8 @@ vector processProp(core::MutableContext ctx, PropInfo &ret, auto arg = ast::MK::KeywordArgWithDefault(nameLoc, core::Names::allowDirectMutation(), ast::MK::Nil(loc)); ast::MethodDef::Flags fkFlags; fkFlags.discardDef = true; - auto fkMethodDef = - ast::MK::SyntheticMethod1(loc, loc, fkMethod, std::move(arg), ast::MK::RaiseUnimplemented(loc), fkFlags); + auto fkMethodDef = ast::MK::SyntheticMethod1(loc, loc, nameLoc, fkMethod, std::move(arg), + ast::MK::RaiseUnimplemented(loc), fkFlags); nodes.emplace_back(std::move(fkMethodDef)); // sig {params(opts: T.untyped).returns($foreign)} @@ -510,7 +511,7 @@ vector processProp(core::MutableContext ctx, PropInfo &ret, auto arg2 = ast::MK::KeywordArgWithDefault(nameLoc, core::Names::allowDirectMutation(), ast::MK::Nil(loc)); ast::MethodDef::Flags fkBangFlags; fkBangFlags.discardDef = true; - auto fkMethodDefBang = ast::MK::SyntheticMethod1(loc, loc, fkMethodBang, std::move(arg2), + auto fkMethodDefBang = ast::MK::SyntheticMethod1(loc, loc, nameLoc, fkMethodBang, std::move(arg2), ast::MK::RaiseUnimplemented(loc), fkBangFlags); nodes.emplace_back(std::move(fkMethodDefBang)); } @@ -545,7 +546,8 @@ ast::ExpressionPtr ensureWithoutAccessors(const PropInfo &prop, const ast::Send } vector mkTypedInitialize(core::MutableContext ctx, core::LocOffsets klassLoc, - core::LocOffsets klassDeclLoc, const vector &props) { + core::LocOffsets klassDeclLoc, core::LocOffsets klassNameLoc, + const vector &props) { ast::MethodDef::ARGS_store args; ast::Send::ARGS_store sigArgs; args.reserve(props.size()); @@ -596,8 +598,8 @@ vector mkTypedInitialize(core::MutableContext ctx, core::Loc vector result; result.emplace_back(ast::MK::SigVoid(klassDeclLoc, std::move(sigArgs))); - result.emplace_back( - ast::MK::SyntheticMethod(klassLoc, klassDeclLoc, core::Names::initialize(), std::move(args), std::move(body))); + result.emplace_back(ast::MK::SyntheticMethod(klassLoc, klassDeclLoc, klassNameLoc, core::Names::initialize(), + std::move(args), std::move(body))); return result; } @@ -661,7 +663,7 @@ void Prop::run(core::MutableContext ctx, ast::ClassDef *klass) { // we define our synthesized initialize first so that if the user wrote one themselves, it overrides ours. if (wantTypedInitialize(syntacticSuperClass)) { // For direct T::Struct subclasses, we know that seeing no props means the constructor should be zero-arity. - for (auto &stat : mkTypedInitialize(ctx, klass->loc, klass->declLoc, props)) { + for (auto &stat : mkTypedInitialize(ctx, klass->loc, klass->declLoc, klass->name.loc(), props)) { klass->rhs.emplace_back(std::move(stat)); } } diff --git a/rewriter/Singleton.cc b/rewriter/Singleton.cc index 65b46a8817..c3a526e6fa 100644 --- a/rewriter/Singleton.cc +++ b/rewriter/Singleton.cc @@ -84,7 +84,8 @@ void Singleton::run(core::MutableContext ctx, ast::ClassDef *cdef) { } { - auto method = ast::MK::SyntheticMethod0(loc, loc, core::Names::instance(), ast::MK::RaiseUnimplemented(loc)); + auto method = + ast::MK::SyntheticMethod0(loc, loc, loc, core::Names::instance(), ast::MK::RaiseUnimplemented(loc)); ast::cast_tree_nonnull(method).flags.isSelfMethod = true; newRHS.emplace_back(std::move(method)); } diff --git a/rewriter/Struct.cc b/rewriter/Struct.cc index c731e5a3cd..988e9cd620 100644 --- a/rewriter/Struct.cc +++ b/rewriter/Struct.cc @@ -138,10 +138,9 @@ vector Struct::run(core::MutableContext ctx, ast::Assign *as argName = ast::make_expression(symLoc, move(argName)); } newArgs.emplace_back(ast::MK::OptionalArg(symLoc, move(argName), ast::MK::Nil(symLoc))); - - body.emplace_back(ast::MK::SyntheticMethod0(symLoc, symLoc, name, ast::MK::RaiseUnimplemented(loc))); - body.emplace_back(ast::MK::SyntheticMethod1(symLoc, symLoc, name.addEq(ctx), ast::MK::Local(symLoc, name), - ast::MK::RaiseUnimplemented(loc))); + body.emplace_back(ast::MK::SyntheticMethod0(symLoc, symLoc, symLoc, name, ast::MK::RaiseUnimplemented(loc))); + body.emplace_back(ast::MK::SyntheticMethod1(symLoc, symLoc, symLoc, name.addEq(ctx), + ast::MK::Local(symLoc, name), ast::MK::RaiseUnimplemented(loc))); } // Elem = type_member {{fixed: T.untyped}} @@ -157,7 +156,7 @@ vector Struct::run(core::MutableContext ctx, ast::Assign *as if (isMissingInitialize(ctx, send)) { body.emplace_back(ast::MK::SigVoid(loc, std::move(sigArgs))); - body.emplace_back(ast::MK::SyntheticMethod(loc, loc, core::Names::initialize(), std::move(newArgs), + body.emplace_back(ast::MK::SyntheticMethod(loc, loc, loc, core::Names::initialize(), std::move(newArgs), ast::MK::RaiseUnimplemented(loc))); } diff --git a/rewriter/TestCase.cc b/rewriter/TestCase.cc index 5c8a17819c..9fec885ced 100644 --- a/rewriter/TestCase.cc +++ b/rewriter/TestCase.cc @@ -40,7 +40,7 @@ void TestCase::run(core::MutableContext ctx, ast::ClassDef *klass) { auto snake_case_name = absl::StrReplaceAll(arg0->asString().toString(ctx), {{" ", "_"}}); auto name = ctx.state.enterNameUTF8("test_" + snake_case_name); - auto method = ast::MK::SyntheticMethod0(loc, loc, name, std::move(block->body)); + auto method = ast::MK::SyntheticMethod0(loc, loc, arg0->loc, name, std::move(block->body)); auto method_with_sig = ast::MK::InsSeq1(method.loc(), ast::MK::SigVoid(method.loc(), {}), std::move(method)); stats.emplace_back(std::move(method_with_sig)); @@ -55,7 +55,7 @@ void TestCase::run(core::MutableContext ctx, ast::ClassDef *klass) { auto block = send->block(); auto method_name = send->fun == core::Names::setup() ? core::Names::initialize() : core::Names::teardown(); - auto method = ast::MK::SyntheticMethod0(loc, loc, method_name, std::move(block->body)); + auto method = ast::MK::SyntheticMethod0(loc, loc, send->funLoc, method_name, std::move(block->body)); auto method_with_sig = ast::MK::InsSeq1(method.loc(), ast::MK::SigVoid(method.loc(), {}), std::move(method)); diff --git a/rewriter/Util.cc b/rewriter/Util.cc index ea0590a710..d191358bf0 100644 --- a/rewriter/Util.cc +++ b/rewriter/Util.cc @@ -249,15 +249,16 @@ ast::ExpressionPtr ASTUtil::mkKwArgsHash(const ast::Send *send) { } } -ast::ExpressionPtr ASTUtil::mkGet(core::Context ctx, core::LocOffsets loc, core::NameRef name, ast::ExpressionPtr rhs, - ast::MethodDef::Flags flags) { - auto ret = ast::MK::SyntheticMethod0(loc, loc, name, move(rhs), flags); +ast::ExpressionPtr ASTUtil::mkGet(core::Context ctx, core::LocOffsets loc, core::NameRef name, core::LocOffsets nameLoc, + ast::ExpressionPtr rhs, ast::MethodDef::Flags flags) { + auto ret = ast::MK::SyntheticMethod0(loc, loc, nameLoc, name, move(rhs), flags); return ret; } -ast::ExpressionPtr ASTUtil::mkSet(core::Context ctx, core::LocOffsets loc, core::NameRef name, core::LocOffsets argLoc, +ast::ExpressionPtr ASTUtil::mkSet(core::Context ctx, core::LocOffsets loc, core::NameRef name, core::LocOffsets nameLoc, ast::ExpressionPtr rhs, ast::MethodDef::Flags flags) { - return ast::MK::SyntheticMethod1(loc, loc, name, ast::MK::Local(argLoc, core::Names::arg0()), move(rhs), flags); + return ast::MK::SyntheticMethod1(loc, loc, nameLoc, name, ast::MK::Local(nameLoc, core::Names::arg0()), move(rhs), + flags); } ast::ExpressionPtr ASTUtil::mkNilable(core::LocOffsets loc, ast::ExpressionPtr type) { diff --git a/rewriter/Util.h b/rewriter/Util.h index b985d3b7cd..45b3df7769 100644 --- a/rewriter/Util.h +++ b/rewriter/Util.h @@ -21,11 +21,12 @@ class ASTUtil { static ast::ExpressionPtr mkKwArgsHash(const ast::Send *send); - static ast::ExpressionPtr mkGet(core::Context ctx, core::LocOffsets loc, core::NameRef name, ast::ExpressionPtr rhs, + static ast::ExpressionPtr mkGet(core::Context ctx, core::LocOffsets loc, core::NameRef name, + core::LocOffsets nameLoc, ast::ExpressionPtr rhs, ast::MethodDef::Flags flags = ast::MethodDef::Flags()); static ast::ExpressionPtr mkSet(core::Context ctx, core::LocOffsets loc, core::NameRef name, - core::LocOffsets argLoc, ast::ExpressionPtr rhs, + core::LocOffsets nameLoc, ast::ExpressionPtr rhs, ast::MethodDef::Flags flags = ast::MethodDef::Flags()); static ast::ExpressionPtr mkNilable(core::LocOffsets loc, ast::ExpressionPtr type); diff --git a/scip_indexer/SCIPIndexer.cc b/scip_indexer/SCIPIndexer.cc index 1f5250cf9c..04ebce038b 100644 --- a/scip_indexer/SCIPIndexer.cc +++ b/scip_indexer/SCIPIndexer.cc @@ -158,6 +158,26 @@ class GemMetadata final { } }; +bool isSorbetInternal(const core::GlobalState &gs, core::SymbolRef sym) { + UnorderedSet visited; + auto classT = core::Symbols::T().data(gs)->lookupSingletonClass(gs); + while (sym.exists() && !visited.contains(sym)) { + if (sym.isClassOrModule()) { + auto klass = sym.asClassOrModuleRef(); + if (klass == core::Symbols::Sorbet_Private() || klass == core::Symbols::T() || klass == classT) { + return true; + } + auto name = klass.data(gs)->name; + if (name == core::Names::Constants::Opus()) { + return true; + } + } + visited.insert(sym); + sym = sym.owner(gs); + } + return false; +} + // A wrapper type to handle both top-level symbols (like classes) as well as // "inner symbols" like fields (@x). In a statically typed language, field // symbols are like any other symbols, but in Ruby, they aren't declared @@ -215,6 +235,11 @@ class NamedSymbolRef final { return lhs.selfOrOwner == rhs.selfOrOwner && lhs.name == rhs.name; } + friend bool operator<(const NamedSymbolRef &lhs, const NamedSymbolRef &rhs) { + return lhs.selfOrOwner.rawId() < rhs.selfOrOwner.rawId() || + (lhs.selfOrOwner == rhs.selfOrOwner && lhs.name.rawId() < rhs.name.rawId()); + } + template friend H AbslHashValue(H h, const NamedSymbolRef &c) { return H::combine(std::move(h), c.selfOrOwner, c.name); } @@ -268,6 +293,18 @@ class NamedSymbolRef final { return this->selfOrOwner; } + bool isSorbetInternalClassOrMethod(const core::GlobalState &gs) const { + switch (this->kind()) { + case Kind::UndeclaredField: + case Kind::DeclaredField: + return false; + case Kind::ClassOrModule: + case Kind::Method: + return isSorbetInternal(gs, this->asSymbolRef()); + } + ENFORCE(false, "impossible"); + } + vector docStrings(const core::GlobalState &gs, core::TypePtr fieldType, core::Loc loc) { #define CHECK_TYPE(type, name) \ ENFORCE(type, "missing type for {} in file {}\n{}\n", name, loc.file().data(gs).path(), loc.toString(gs)) @@ -392,10 +429,22 @@ class NamedSymbolRef final { return absl::OkStatus(); } - core::Loc symbolLoc(const core::GlobalState &gs) const { - // FIXME(varun): For methods, this returns the full line! - ENFORCE(this->name == core::NameRef::noName()); - return this->selfOrOwner.loc(gs); + core::Loc symbolLoc(const core::GlobalState &gs, core::FileRef file) const { + switch (this->kind()) { + case Kind::Method: { + auto method = this->selfOrOwner.asMethodRef().data(gs); + auto offset = method->nameLoc; + if (!offset.exists() || offset.empty()) { + return method->loc(); + } + return core::Loc(file, offset); + } + case Kind::ClassOrModule: + case Kind::DeclaredField: + return this->selfOrOwner.loc(gs); + case Kind::UndeclaredField: + ENFORCE(false, "case UndeclaredField should not be triggered here"); + } } }; @@ -455,6 +504,8 @@ class SCIPState { // map in debug, so keeping it a map. UnorderedMap, uint32_t> localOccurrenceCache; + UnorderedSet> symbolOccurrenceCache; + GemMetadata gemMetadata; public: @@ -606,6 +657,17 @@ class SCIPState { return true; } + bool cacheOccurrence(const core::GlobalState &gs, core::Loc loc, NamedSymbolRef sym, int32_t symbolRoles) { + // Optimization: + // Avoid emitting duplicate def/refs for symbols. + // This can happen with constructs like: + // prop :foo, String + // Without this optimization, there are 4 occurrences for String + // emitted for the same source range. + auto [_, inserted] = this->symbolOccurrenceCache.insert({sym, loc, symbolRoles}); + return !inserted; + } + public: absl::Status saveDefinition(const core::GlobalState &gs, core::FileRef file, OwnedLocal occ, core::TypePtr type) { if (this->cacheOccurrence(gs, file, occ, scip::SymbolRole::Definition)) { @@ -626,9 +688,10 @@ class SCIPState { // TODO(varun): Should we always pass in the location instead of sometimes only? absl::Status saveDefinition(const core::GlobalState &gs, core::FileRef file, NamedSymbolRef symRef, std::optional loc = std::nullopt) { - // TODO:(varun) Should we cache here too to avoid emitting duplicate definitions? + // In practice, there doesn't seem to be any situation which triggers + // a duplicate definition being emitted, so skip calling cacheOccurrence here. scip::Symbol symbol; - auto occLoc = loc.has_value() ? core::Loc(file, loc.value()) : symRef.symbolLoc(gs); + auto occLoc = loc.has_value() ? core::Loc(file, loc.value()) : symRef.symbolLoc(gs, file); auto status = symRef.symbolForExpr(gs, this->gemMetadata, symbol, occLoc); if (!status.ok()) { return status; @@ -660,8 +723,20 @@ class SCIPState { return absl::OkStatus(); } - absl::Status saveReference(const core::GlobalState &gs, core::FileRef file, NamedSymbolRef symRef, - optional overrideType, core::LocOffsets occLoc, int32_t symbol_roles) { + absl::Status saveReference(const core::Context &ctx, NamedSymbolRef symRef, optional overrideType, + core::LocOffsets occLoc, int32_t symbol_roles) { + // HACK: Reduce noise due to in snapshots. + if (ctx.owner.name(ctx) == core::Names::staticInit()) { + if (symRef.isSorbetInternalClassOrMethod(ctx)) { + return absl::OkStatus(); + } + } + auto loc = core::Loc(ctx.file, occLoc); + if (this->cacheOccurrence(ctx, loc, symRef, symbol_roles)) { + return absl::OkStatus(); + } + auto &gs = ctx.state; + auto file = ctx.file; // TODO:(varun) Should we cache here to to avoid emitting duplicate references? absl::StatusOr valueOrStatus(this->saveSymbolString(gs, symRef, nullptr)); if (!valueOrStatus.ok()) { @@ -678,7 +753,7 @@ class SCIPState { case Kind::UndeclaredField: case Kind::DeclaredField: if (overrideType.has_value()) { - overrideDocs = symRef.docStrings(gs, overrideType.value(), core::Loc(file, occLoc)); + overrideDocs = symRef.docStrings(gs, overrideType.value(), loc); } } this->saveReferenceImpl(gs, file, symbolString, overrideDocs, occLoc, symbol_roles); @@ -960,7 +1035,7 @@ class CFGTraversal final { status = this->scipState.saveDefinition(gs, file, namedSym, loc); } else { auto overrideType = computeOverrideType(namedSym.definitionType, type); - status = this->scipState.saveReference(gs, file, namedSym, overrideType, loc, referenceRole); + status = this->scipState.saveReference(ctx, namedSym, overrideType, loc, referenceRole); } } else { uint32_t localId = this->functionLocals[localRef]; @@ -1033,7 +1108,7 @@ class CFGTraversal final { status = this->scipState.saveDefinition(gs, file, namedSym, arg.loc); kind = "definition"; } else { - status = this->scipState.saveReference(gs, file, namedSym, nullopt, arg.loc, 0); + status = this->scipState.saveReference(ctx, namedSym, nullopt, arg.loc, 0); kind = "reference"; } ENFORCE(status.ok(), "failed to save {} for {}\ncontext:\ninstruction: {}\nlocation: {}\n", kind, @@ -1102,11 +1177,11 @@ class CFGTraversal final { if (recv.exists()) { auto funSym = gs.lookupMethodSymbol(recv, send->fun); if (funSym.exists()) { - // TODO:(varun) For arrays, hashes etc., try to identify if the function - // matches a known operator (e.g. []=), and emit an appropriate 'WriteAccess' - // symbol role for it. - auto status = this->scipState.saveReference( - gs, file, NamedSymbolRef::method(funSym), nullopt, send->funLoc, 0); + // TODO(varun): For arrays, hashes etc., try to identify if the function + // matches a known operator (e.g. []=), and emit an appropriate + // 'WriteAccess' symbol role for it. + auto status = this->scipState.saveReference(ctx, NamedSymbolRef::method(funSym), + nullopt, send->funLoc, 0); ENFORCE(status.ok()); } } @@ -1187,14 +1262,18 @@ class CFGTraversal final { // Sort for determinism fast_sort(todo, [&](const SymbolWithLoc &p1, const SymbolWithLoc &p2) -> bool { if (p1.second.beginPos() == p2.second.beginPos()) { - // TODO: This code path is hit when there is a module_function on top of a sig. - // In that case, the 'T' and 'X' in 'T::X' in a sig end up with two occurrences each. - // We should check if this is a Sorbet bug or deliberate. - ENFORCE(p1.first == p2.first, - "found different symbols at same location in {}, source:\n{}\nsym1 = {}\nsym2 = {}\n", - file.data(gs).path(), core::Loc(file, p1.second).toString(gs), p1.first.showRaw(gs), - p2.first.showRaw(gs)); - foundDupes = true; + if (p1.first == p2.first) { + foundDupes = true; + return false; + } else { + // This code path is hit when trying to use encrypted_prop -- that creates two + // classes ::Opus and ::Opus::DB::Model with the same source locations as the declaration. + // + // It is also hit when a module_function is on top of sig, in which case, + // the 'T' and the 'X' in 'T::X' end up with two occurrences each. This latter + // example seems like a bug though. + return p1.first < p2.first; + } } return p1.second.beginPos() < p2.second.beginPos(); }); @@ -1213,7 +1292,7 @@ class CFGTraversal final { // Specifically, Go to Definition for modules seems to go to 'module M' even // when other forms like 'class M::C' are present. for (auto &[namedSym, loc] : todo) { - auto status = this->scipState.saveReference(gs, file, namedSym, nullopt, loc, 0); + auto status = this->scipState.saveReference(ctx, namedSym, nullopt, loc, 0); ENFORCE(status.ok(), "status: {}\n", status.message()); } } diff --git a/test/hello-test.cc b/test/hello-test.cc index 08828ff897..cd8966c6df 100644 --- a/test/hello-test.cc +++ b/test/hello-test.cc @@ -123,7 +123,7 @@ TEST_CASE("CountTrees") { // see if it crashes via failed ENFORCE cb.enterTypeMember(loc, classSym, cb.enterNameConstant(name), sorbet::core::Variance::CoVariant); - auto methodSym = cb.enterMethodSymbol(loc, classSym, name); + auto methodSym = cb.enterMethodSymbol(loc, classSym, name, core::LocOffsets::none()); // see if it crashes via failed ENFORCE cb.enterTypeArgument(loc, methodSym, cb.enterNameConstant(name), sorbet::core::Variance::CoVariant); diff --git a/test/scip/testdata/alias.rb b/test/scip/testdata/alias.rb new file mode 100644 index 0000000000..c8cec4665e --- /dev/null +++ b/test/scip/testdata/alias.rb @@ -0,0 +1,14 @@ +# typed: true + +class X + alias_method :am_aaa, :aaa + alias :a_aaa :aaa + + def aaa + puts "AAA" + end + + def check_alias + return [am_aaa, a_aaa] + end +end diff --git a/test/scip/testdata/alias.snapshot.rb b/test/scip/testdata/alias.snapshot.rb new file mode 100644 index 0000000000..b68c3fbbc1 --- /dev/null +++ b/test/scip/testdata/alias.snapshot.rb @@ -0,0 +1,19 @@ + # typed: true + + class X +# ^ definition [..] X# + alias_method :am_aaa, :aaa + alias :a_aaa :aaa + + def aaa +# ^^^ definition [..] X#aaa(). + puts "AAA" + end + + def check_alias +# ^^^^^^^^^^^ definition [..] X#check_alias(). + return [am_aaa, a_aaa] +# ^^^^^^ reference [..] X#am_aaa(). +# ^^^^^ reference [..] X#a_aaa(). + end + end diff --git a/test/scip/testdata/args.snapshot.rb b/test/scip/testdata/args.snapshot.rb index 5a33b7c570..bc7cc48ed6 100644 --- a/test/scip/testdata/args.snapshot.rb +++ b/test/scip/testdata/args.snapshot.rb @@ -1,7 +1,7 @@ # typed: true def args(x, y) -#^^^^^^^^^^^^^^ definition [..] Object#args(). +# ^^^^ definition [..] Object#args(). # ^ definition local 1~#2634721084 # ^ definition local 2~#2634721084 z = x + y @@ -25,7 +25,7 @@ def args(x, y) end def keyword_args(w:, x: 3, y: [], **kwargs) -#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] Object#keyword_args(). +# ^^^^^^^^^^^^ definition [..] Object#keyword_args(). # ^^ definition local 1~#3526982640 # ^^ definition local 2~#3526982640 # ^^ definition local 3~#3526982640 @@ -39,7 +39,7 @@ def keyword_args(w:, x: 3, y: [], **kwargs) end def use_kwargs -#^^^^^^^^^^^^^^ definition [..] Object#use_kwargs(). +# ^^^^^^^^^^ definition [..] Object#use_kwargs(). h = { a: 3 } # ^ definition local 1~#571973038 keyword_args(w: 0, **h) diff --git a/test/scip/testdata/arrays.snapshot.rb b/test/scip/testdata/arrays.snapshot.rb index 96ab5c7c43..3cb6463323 100644 --- a/test/scip/testdata/arrays.snapshot.rb +++ b/test/scip/testdata/arrays.snapshot.rb @@ -1,7 +1,7 @@ # typed: true def arrays(a, i) -#^^^^^^^^^^^^^^^^ definition [..] Object#arrays(). +# ^^^^^^ definition [..] Object#arrays(). # ^ definition local 1~#513334479 # ^ definition local 2~#513334479 a[0] = 0 diff --git a/test/scip/testdata/cattr.rb b/test/scip/testdata/cattr.rb new file mode 100644 index 0000000000..72d40a1192 --- /dev/null +++ b/test/scip/testdata/cattr.rb @@ -0,0 +1,61 @@ +# typed: strict + +class CR + extend T::Sig + cattr_reader :both, :foo + cattr_reader :no_instance, instance_accessor: false + cattr_reader :bar, :no_reader, instance_reader: false + + sig {void} + def usages + both + end + + both + no_instance + no_reader +end + +class CW + extend T::Sig + cattr_writer :both, :foo + cattr_writer :no_instance, instance_accessor: false + cattr_writer :bar, :no_instance_writer, instance_writer: false + + sig {void} + def usages + self.both = 1 + end + + self.both = 1 + self.no_instance = 1 + self.no_instance_writer = 1 +end + +class CA + extend T::Sig + cattr_accessor :both, :foo + cattr_accessor :no_instance, instance_accessor: false + cattr_accessor :no_instance_reader, instance_reader: false + cattr_accessor :bar, :no_instance_writer, instance_writer: false + + sig {void} + def usages + both + self.both = 1 + self.no_instance_reader= 1 + no_instance_writer + end + + both + self.both = 1 + + no_instance + self.no_instance = 1 + + no_instance_reader + self.no_instance_reader = 1 + + no_instance_writer + self.no_instance_writer = 1 +end diff --git a/test/scip/testdata/cattr.snapshot.rb b/test/scip/testdata/cattr.snapshot.rb new file mode 100644 index 0000000000..af63aaf7fe --- /dev/null +++ b/test/scip/testdata/cattr.snapshot.rb @@ -0,0 +1,120 @@ + # typed: strict + + class CR +# ^^ definition [..] CR# + extend T::Sig + cattr_reader :both, :foo +# ^^^^^ definition [..] CR#both(). +# ^^^^^ definition [..] ``#both(). +# ^^^^ definition [..] CR#foo(). +# ^^^^ definition [..] ``#foo(). + cattr_reader :no_instance, instance_accessor: false +# ^^^^^^^^^^^^ definition [..] ``#no_instance(). + cattr_reader :bar, :no_reader, instance_reader: false +# ^^^^ definition [..] ``#bar(). +# ^^^^^^^^^^ definition [..] ``#no_reader(). + + sig {void} + def usages +# ^^^^^^ definition [..] CR#usages(). + both +# ^^^^ reference [..] CR#both(). + end + + both +# ^^^^ reference [..] ``#both(). + no_instance +# ^^^^^^^^^^^ reference [..] ``#no_instance(). + no_reader +# ^^^^^^^^^ reference [..] ``#no_reader(). + end + + class CW +# ^^ definition [..] CW# + extend T::Sig + cattr_writer :both, :foo +# ^^^^^ definition [..] CW#`both=`(). +# ^^^^^ definition [..] ``#`both=`(). +# ^^^^ definition [..] CW#`foo=`(). +# ^^^^ definition [..] ``#`foo=`(). + cattr_writer :no_instance, instance_accessor: false +# ^^^^^^^^^^^^ definition [..] ``#`no_instance=`(). + cattr_writer :bar, :no_instance_writer, instance_writer: false +# ^^^^ definition [..] ``#`bar=`(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#`no_instance_writer=`(). + + sig {void} + def usages +# ^^^^^^ definition [..] CW#usages(). + self.both = 1 +# ^^^^^^ reference [..] CW#`both=`(). + end + + self.both = 1 +# ^^^^^^ reference [..] ``#`both=`(). + self.no_instance = 1 +# ^^^^^^^^^^^^^ reference [..] ``#`no_instance=`(). + self.no_instance_writer = 1 +# ^^^^^^^^^^^^^^^^^^^^ reference [..] ``#`no_instance_writer=`(). + end + + class CA +# ^^ definition [..] CA# + extend T::Sig + cattr_accessor :both, :foo +# ^^^^^ definition [..] CA#`both=`(). +# ^^^^^ definition [..] ``#both(). +# ^^^^^ definition [..] CA#both(). +# ^^^^^ definition [..] ``#`both=`(). +# ^^^^ definition [..] CA#foo(). +# ^^^^ definition [..] ``#foo(). +# ^^^^ definition [..] CA#`foo=`(). +# ^^^^ definition [..] ``#`foo=`(). + cattr_accessor :no_instance, instance_accessor: false +# ^^^^^^^^^^^^ definition [..] ``#no_instance(). +# ^^^^^^^^^^^^ definition [..] ``#`no_instance=`(). + cattr_accessor :no_instance_reader, instance_reader: false +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#no_instance_reader(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] CA#`no_instance_reader=`(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#`no_instance_reader=`(). + cattr_accessor :bar, :no_instance_writer, instance_writer: false +# ^^^^ definition [..] CA#bar(). +# ^^^^ definition [..] ``#bar(). +# ^^^^ definition [..] ``#`bar=`(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] CA#no_instance_writer(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#no_instance_writer(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#`no_instance_writer=`(). + + sig {void} + def usages +# ^^^^^^ definition [..] CA#usages(). + both +# ^^^^ reference [..] CA#both(). + self.both = 1 +# ^^^^^^ reference [..] CA#`both=`(). + self.no_instance_reader= 1 +# ^^^^^^^^^^^^^^^^^^^ reference [..] CA#`no_instance_reader=`(). + no_instance_writer +# ^^^^^^^^^^^^^^^^^^ reference [..] CA#no_instance_writer(). + end + + both +# ^^^^ reference [..] ``#both(). + self.both = 1 +# ^^^^^^ reference [..] ``#`both=`(). + + no_instance +# ^^^^^^^^^^^ reference [..] ``#no_instance(). + self.no_instance = 1 +# ^^^^^^^^^^^^^ reference [..] ``#`no_instance=`(). + + no_instance_reader +# ^^^^^^^^^^^^^^^^^^ reference [..] ``#no_instance_reader(). + self.no_instance_reader = 1 +# ^^^^^^^^^^^^^^^^^^^^ reference [..] ``#`no_instance_reader=`(). + + no_instance_writer +# ^^^^^^^^^^^^^^^^^^ reference [..] ``#no_instance_writer(). + self.no_instance_writer = 1 +# ^^^^^^^^^^^^^^^^^^^^ reference [..] ``#`no_instance_writer=`(). + end diff --git a/test/scip/testdata/classes.snapshot.rb b/test/scip/testdata/classes.snapshot.rb index b55719d22b..f8deee50ba 100644 --- a/test/scip/testdata/classes.snapshot.rb +++ b/test/scip/testdata/classes.snapshot.rb @@ -6,7 +6,7 @@ class C1 # ^^ definition [..] C1# def f() -# ^^^^^^^ definition [..] C1#f(). +# ^ definition [..] C1#f(). _a = C1.new # ^^ definition local 1~#3809224601 # ^^ reference [..] C1# @@ -31,14 +31,14 @@ class M3::C3 end def local_class() -#^^^^^^^^^^^^^^^^^ definition [..] Object#local_class(). +# ^^^^^^^^^^^ definition [..] Object#local_class(). localClass = Class.new # ^^^^^^^^^^ definition local 1~#552113551 # ^^^^^ reference [..] Class# # Technically, this is not supported by Sorbet (https://srb.help/3001), # but make sure we don't crash or do something weird. def localClass.myMethod() -# ^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] Object#myMethod(). +# ^^^^^^^^ definition [..] Object#myMethod(). ":)" end _c = localClass.new @@ -60,7 +60,7 @@ module M4 end def module_access() -#^^^^^^^^^^^^^^^^^^^ definition [..] Object#module_access(). +# ^^^^^^^^^^^^^ definition [..] Object#module_access(). _ = M4::K # ^ definition local 1~#3353511840 # ^^ reference [..] M4# @@ -73,12 +73,12 @@ module M5 module M6 # ^^ definition [..] M5#M6# def self.g() -# ^^^^^^^^^^^^ definition [..] M5#``#g(). +# ^ definition [..] M5#``#g(). end end def self.h() -# ^^^^^^^^^^^^ definition [..] ``#h(). +# ^ definition [..] ``#h(). M6.g() # ^^ reference [..] M5#M6# # ^ reference [..] M5#``#g(). @@ -91,12 +91,12 @@ class C7 module M8 # ^^ definition [..] C7#M8# def self.i() -# ^^^^^^^^^^^^ definition [..] C7#``#i(). +# ^ definition [..] C7#``#i(). end end def j() -# ^^^^^^^ definition [..] C7#j(). +# ^ definition [..] C7#j(). M8.i() # ^^ reference [..] C7#M8# # ^ reference [..] C7#``#i(). diff --git a/test/scip/testdata/def_delegator.snapshot.rb b/test/scip/testdata/def_delegator.snapshot.rb index 7ee110293c..54f82e9f7e 100644 --- a/test/scip/testdata/def_delegator.snapshot.rb +++ b/test/scip/testdata/def_delegator.snapshot.rb @@ -5,137 +5,53 @@ class MyArray1 # ^^^^^^^^ definition [..] MyArray1# attr_accessor :inner_array -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray1#inner_array(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray1#`inner_array=`(). +# ^^^^^^^^^^^ definition [..] MyArray1#inner_array(). +# ^^^^^^^^^^^ definition [..] MyArray1#`inner_array=`(). extend Forwardable # ^^^^^^^^^^^ reference [..] Forwardable# def_delegator :@inner_array, :[], :get_at_index -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray1#get_at_index(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Proc# +# ^^^^^^^^^^^^^ definition [..] MyArray1#get_at_index(). end class MyArray2 # ^^^^^^^^ definition [..] MyArray2# extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# attr_accessor :inner_array -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray2#inner_array(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray2#`inner_array=`(). +# ^^^^^^^^^^^ definition [..] MyArray2#inner_array(). +# ^^^^^^^^^^^ definition [..] MyArray2#`inner_array=`(). extend Forwardable # ^^^^^^^^^^^ reference [..] Forwardable# def_delegator :@inner_array, :[], :get_at_index -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray2#get_at_index(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Proc# +# ^^^^^^^^^^^^^ definition [..] MyArray2#get_at_index(). end class MyArray3 # ^^^^^^^^ definition [..] MyArray3# attr_accessor :inner_array -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray3#inner_array(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray3#`inner_array=`(). +# ^^^^^^^^^^^ definition [..] MyArray3#inner_array(). +# ^^^^^^^^^^^ definition [..] MyArray3#`inner_array=`(). extend Forwardable # ^^^^^^^^^^^ reference [..] Forwardable# def_delegators :@inner_array, :size, :<<, :map -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Proc# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray3#map(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray3#`<<`(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray3#size(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). +# ^^^^^ definition [..] MyArray3#size(). +# ^^^ definition [..] MyArray3#`<<`(). +# ^^^^ definition [..] MyArray3#map(). end class MyArray4 # ^^^^^^^^ definition [..] MyArray4# extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# attr_accessor :inner_array -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray4#`inner_array=`(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray4#inner_array(). +# ^^^^^^^^^^^ definition [..] MyArray4#inner_array(). +# ^^^^^^^^^^^ definition [..] MyArray4#`inner_array=`(). extend Forwardable # ^^^^^^^^^^^ reference [..] Forwardable# def_delegators :@inner_array, :size, :<<, :map -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray4#size(). # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Proc# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#nilable(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#untyped(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray4#map(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyArray4#`<<`(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#``#sig(). +# ^^^^^ definition [..] MyArray4#size(). +# ^^^ definition [..] MyArray4#`<<`(). +# ^^^^ definition [..] MyArray4#map(). end diff --git a/test/scip/testdata/delegate.rb b/test/scip/testdata/delegate.rb new file mode 100644 index 0000000000..b4f8fa9ca8 --- /dev/null +++ b/test/scip/testdata/delegate.rb @@ -0,0 +1,17 @@ +# typed: true + +class MethodNameManipulation + extend T::Sig + delegate :ball, to: :thing, private: true, allow_nil: true + delegate :foo, :bar, prefix: 'string', to: :thing + delegate :foo, :bar, prefix: :symbol, to: :thing + + sig {void} + def usages + ball(thing: 0) {} + string_foo + string_bar + symbol_foo {} + symbol_bar(1, 2) {} + end +end diff --git a/test/scip/testdata/delegate.snapshot.rb b/test/scip/testdata/delegate.snapshot.rb new file mode 100644 index 0000000000..d177aa4421 --- /dev/null +++ b/test/scip/testdata/delegate.snapshot.rb @@ -0,0 +1,32 @@ + # typed: true + + class MethodNameManipulation +# ^^^^^^^^^^^^^^^^^^^^^^ definition [..] MethodNameManipulation# + extend T::Sig + delegate :ball, to: :thing, private: true, allow_nil: true +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Proc# +# ^^^^^ definition [..] MethodNameManipulation#ball(). + delegate :foo, :bar, prefix: 'string', to: :thing +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Proc# +# ^^^^ definition [..] MethodNameManipulation#string_foo(). +# ^^^^ definition [..] MethodNameManipulation#string_bar(). + delegate :foo, :bar, prefix: :symbol, to: :thing +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Proc# +# ^^^^ definition [..] MethodNameManipulation#symbol_foo(). +# ^^^^ definition [..] MethodNameManipulation#symbol_bar(). + + sig {void} + def usages +# ^^^^^^ definition [..] MethodNameManipulation#usages(). + ball(thing: 0) {} +# ^^^^ reference [..] MethodNameManipulation#ball(). + string_foo +# ^^^^^^^^^^ reference [..] MethodNameManipulation#string_foo(). + string_bar +# ^^^^^^^^^^ reference [..] MethodNameManipulation#string_bar(). + symbol_foo {} +# ^^^^^^^^^^ reference [..] MethodNameManipulation#symbol_foo(). + symbol_bar(1, 2) {} +# ^^^^^^^^^^ reference [..] MethodNameManipulation#symbol_bar(). + end + end diff --git a/test/scip/testdata/encrypted_prop.rb b/test/scip/testdata/encrypted_prop.rb new file mode 100644 index 0000000000..b1e1c7dcd8 --- /dev/null +++ b/test/scip/testdata/encrypted_prop.rb @@ -0,0 +1,21 @@ +# typed: true + +# Minimal stub of Chalk implementation to support encrypted_prop +class Chalk::ODM::Document +end +class Opus::DB::Model::Mixins::Encryptable::EncryptedValue < Chalk::ODM::Document +end + +class EncryptedProp + include T::Props + def self.encrypted_prop(opts={}); end + encrypted_prop :foo + encrypted_prop :bar, migrating: true, immutable: true +end + + +def f + EncryptedProp.new.foo = "hello" + EncryptedProp.new.foo = nil + return EncryptedProp.new.encrypted_foo +end diff --git a/test/scip/testdata/encrypted_prop.snapshot.rb b/test/scip/testdata/encrypted_prop.snapshot.rb new file mode 100644 index 0000000000..143bfa17bb --- /dev/null +++ b/test/scip/testdata/encrypted_prop.snapshot.rb @@ -0,0 +1,50 @@ + # typed: true + + # Minimal stub of Chalk implementation to support encrypted_prop + class Chalk::ODM::Document +# ^^^^^ reference [..] Chalk# +# ^^^ reference [..] Chalk#ODM# +# ^^^^^^^^ definition [..] Chalk#ODM#Document# + end + class Opus::DB::Model::Mixins::Encryptable::EncryptedValue < Chalk::ODM::Document +# ^^^^ reference [..] Opus# +# ^^ reference [..] Opus#DB# +# ^^^^^ reference [..] Opus#DB#Model# +# ^^^^^^ reference [..] Opus#DB#Model#Mixins# +# ^^^^^^^^^^^ reference [..] Opus#DB#Model#Mixins#Encryptable# +# ^^^^^^^^^^^^^^ definition [..] Opus#DB#Model#Mixins#Encryptable#EncryptedValue# +# ^^^^^ reference [..] Chalk# +# ^^^ reference [..] Chalk#ODM# +# ^^^^^^^^ definition [..] Chalk#ODM#Document# + end + + class EncryptedProp +# ^^^^^^^^^^^^^ definition [..] EncryptedProp# + include T::Props + def self.encrypted_prop(opts={}); end +# ^^^^^^^^^^^^^^ definition [..] ``#encrypted_prop(). + encrypted_prop :foo +# ^^^^^^^^^^^^^^^^^^^ reference [..] String# +# ^^^ definition [..] EncryptedProp#`encrypted_foo=`(). +# ^^^ definition [..] EncryptedProp#`foo=`(). +# ^^^ definition [..] EncryptedProp#encrypted_foo(). +# ^^^ definition [..] EncryptedProp#foo(). + encrypted_prop :bar, migrating: true, immutable: true +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] String# +# ^^^ definition [..] EncryptedProp#bar(). +# ^^^ definition [..] EncryptedProp#encrypted_bar(). + end + + + def f +# ^ definition [..] Object#f(). + EncryptedProp.new.foo = "hello" +# ^^^^^^^^^^^^^ reference [..] EncryptedProp# +# ^^^^^ reference [..] EncryptedProp#`foo=`(). + EncryptedProp.new.foo = nil +# ^^^^^^^^^^^^^ reference [..] EncryptedProp# +# ^^^^^ reference [..] EncryptedProp#`foo=`(). + return EncryptedProp.new.encrypted_foo +# ^^^^^^^^^^^^^ reference [..] EncryptedProp# +# ^^^^^^^^^^^^^ reference [..] EncryptedProp#encrypted_foo(). + end diff --git a/test/scip/testdata/fields_and_attrs.snapshot.rb b/test/scip/testdata/fields_and_attrs.snapshot.rb index 188cdec2f2..863851472a 100644 --- a/test/scip/testdata/fields_and_attrs.snapshot.rb +++ b/test/scip/testdata/fields_and_attrs.snapshot.rb @@ -6,7 +6,7 @@ class K # ^ definition [..] K# def m1 -# ^^^^^^ definition [..] K#m1(). +# ^^ definition [..] K#m1(). @f = 0 # ^^ definition [..] K#`@f`. @g = @f @@ -15,7 +15,7 @@ def m1 return end def m2 -# ^^^^^^ definition [..] K#m2(). +# ^^ definition [..] K#m2(). @f = @g # ^^ definition [..] K#`@f`. # ^^ reference [..] K#`@g`. @@ -27,7 +27,7 @@ def m2 class K # ^ definition [..] K# def m3 -# ^^^^^^ definition [..] K#m3(). +# ^^ definition [..] K#m3(). @g = @f # ^^ definition [..] K#`@g`. # ^^ reference [..] K#`@f`. @@ -43,7 +43,7 @@ class L @y = 9 # ^^ definition [..] ``#`@y`. def self.m1 -# ^^^^^^^^^^^ definition [..] ``#m1(). +# ^^ definition [..] ``#m1(). @y = @x # ^^ definition [..] ``#`@y`. # ^^ reference [..] ``#`@x`. @@ -51,7 +51,7 @@ def self.m1 end def m2 -# ^^^^^^ definition [..] L#m2(). +# ^^ definition [..] L#m2(). # FIXME: Missing references self.class.y = self.class.x return @@ -66,7 +66,7 @@ class N @@b = 1 # ^^^ definition [..] ``#`@@b`. def self.m1 -# ^^^^^^^^^^^ definition [..] ``#m1(). +# ^^ definition [..] ``#m1(). @@b = @@a # ^^^ definition [..] ``#`@@b`. # ^^^ reference [..] ``#`@@a`. @@ -74,7 +74,7 @@ def self.m1 end def m2 -# ^^^^^^ definition [..] N#m2(). +# ^^ definition [..] N#m2(). @@b = @@a # ^^^ definition [..] N#`@@b`. # ^^^ reference [..] N#`@@a`. @@ -82,7 +82,7 @@ def m2 end def m3 -# ^^^^^^ definition [..] N#m3(). +# ^^ definition [..] N#m3(). # FIXME: Missing references self.class.b = self.class.a end @@ -92,15 +92,15 @@ def m3 class P # ^ definition [..] P# attr_accessor :a -# ^^^^^^^^^^^^^^^^ definition [..] P#`a=`(). -# ^^^^^^^^^^^^^^^^ definition [..] P#a(). +# ^ definition [..] P#`a=`(). +# ^ definition [..] P#a(). attr_reader :r -# ^^^^^^^^^^^^^^ definition [..] P#r(). +# ^ definition [..] P#r(). attr_writer :w -# ^^^^^^^^^^^^^^ definition [..] P#`w=`(). +# ^ definition [..] P#`w=`(). def init -# ^^^^^^^^ definition [..] P#init(). +# ^^^^ definition [..] P#init(). self.a = self.r # ^^^ reference [..] P#`a=`(). # ^ reference [..] P#r(). @@ -110,7 +110,7 @@ def init end def wrong_init -# ^^^^^^^^^^^^^^ definition [..] P#wrong_init(). +# ^^^^^^^^^^ definition [..] P#wrong_init(). # Check that 'r' is a method access but 'a' and 'w' are locals a = r # ^ definition local 1~#1021288725 @@ -123,7 +123,7 @@ def wrong_init end def useP -#^^^^^^^^ definition [..] Object#useP(). +# ^^^^ definition [..] Object#useP(). p = P.new # ^ definition local 1~#2121829932 # ^ reference [..] P# diff --git a/test/scip/testdata/flatfile_dsl.rb b/test/scip/testdata/flatfile_dsl.rb new file mode 100644 index 0000000000..a6a1691b4e --- /dev/null +++ b/test/scip/testdata/flatfile_dsl.rb @@ -0,0 +1,21 @@ +# typed: true + +class Record + def self.flatfile; end + def self.from(*_); end + def self.pattern(*_); end + def self.field(*_); end +end + +class Flatfile < Record + flatfile do + from 1..2, :foo + pattern(/A-Za-z/, :bar) + field :baz + end +end + +t = Flatfile.new +t.foo = t.foo + 1 +t.bar = t.bar + 1 +t.baz = t.baz + 1 diff --git a/test/scip/testdata/flatfile_dsl.snapshot.rb b/test/scip/testdata/flatfile_dsl.snapshot.rb new file mode 100644 index 0000000000..048b2d10f6 --- /dev/null +++ b/test/scip/testdata/flatfile_dsl.snapshot.rb @@ -0,0 +1,49 @@ + # typed: true + + class Record +# ^^^^^^ definition [..] Record# + def self.flatfile; end +# ^^^^^^^^ definition [..] ``#flatfile(). + def self.from(*_); end +# ^^^^ definition [..] ``#from(). + def self.pattern(*_); end +# ^^^^^^^ definition [..] ``#pattern(). + def self.field(*_); end +# ^^^^^ definition [..] ``#field(). + end + + class Flatfile < Record +# ^^^^^^^^ definition [..] Flatfile# +# ^^^^^^ definition [..] Record# + flatfile do + from 1..2, :foo +# ^^^^ definition [..] Flatfile#`foo=`(). +# ^^^^ definition [..] Flatfile#foo(). + pattern(/A-Za-z/, :bar) +# ^^^^^^^^ reference [..] Regexp# +# ^^^^ definition [..] Flatfile#bar(). +# ^^^^ definition [..] Flatfile#`bar=`(). + field :baz +# ^^^^ definition [..] Flatfile#baz(). +# ^^^^ definition [..] Flatfile#`baz=`(). + end + end + + t = Flatfile.new +#^ definition local 1~#119448696 +# ^^^^^^^^ reference [..] Flatfile# + t.foo = t.foo + 1 +#^ reference local 1~#119448696 +# ^^^^^ reference [..] Flatfile#`foo=`(). +# ^ reference local 1~#119448696 +# ^^^ reference [..] Flatfile#foo(). + t.bar = t.bar + 1 +#^ reference local 1~#119448696 +# ^^^^^ reference [..] Flatfile#`bar=`(). +# ^ reference local 1~#119448696 +# ^^^ reference [..] Flatfile#bar(). + t.baz = t.baz + 1 +#^ reference local 1~#119448696 +# ^^^^^ reference [..] Flatfile#`baz=`(). +# ^ reference local 1~#119448696 +# ^^^ reference [..] Flatfile#baz(). diff --git a/test/scip/testdata/for.snapshot.rb b/test/scip/testdata/for.snapshot.rb index 3b275cbffd..77446a45f4 100644 --- a/test/scip/testdata/for.snapshot.rb +++ b/test/scip/testdata/for.snapshot.rb @@ -1,7 +1,7 @@ # typed: true def for_loop() -#^^^^^^^^^^^^^^ definition [..] Object#for_loop(). +# ^^^^^^^^ definition [..] Object#for_loop(). y = 0 # ^ definition local 1~#1120785331 for x in [1, 2, 3] diff --git a/test/scip/testdata/functions.snapshot.rb b/test/scip/testdata/functions.snapshot.rb index f20793284e..76ee7d2714 100644 --- a/test/scip/testdata/functions.snapshot.rb +++ b/test/scip/testdata/functions.snapshot.rb @@ -1,7 +1,7 @@ # typed: true def globalFn1() -#^^^^^^^^^^^^^^^ definition [..] Object#globalFn1(). +# ^^^^^^^^^ definition [..] Object#globalFn1(). x = 10 # ^ definition local 1~#3846536873 x @@ -9,7 +9,7 @@ def globalFn1() end def globalFn2() -#^^^^^^^^^^^^^^^ definition [..] Object#globalFn2(). +# ^^^^^^^^^ definition [..] Object#globalFn2(). x = globalFn1() # ^ definition local 1~#3796204016 # ^^^^^^^^^^^^^^^ reference local 1~#3796204016 diff --git a/test/scip/testdata/gem_metadata.snapshot.rb b/test/scip/testdata/gem_metadata.snapshot.rb index e7d229190a..8c6e505bca 100644 --- a/test/scip/testdata/gem_metadata.snapshot.rb +++ b/test/scip/testdata/gem_metadata.snapshot.rb @@ -4,12 +4,12 @@ class C # ^ definition leet 1.3.3.7 C# def m -# ^^^^^ definition leet 1.3.3.7 C#m(). +# ^ definition leet 1.3.3.7 C#m(). n # ^ reference leet 1.3.3.7 C#n(). end def n -# ^^^^^ definition leet 1.3.3.7 C#n(). +# ^ definition leet 1.3.3.7 C#n(). m # ^ reference leet 1.3.3.7 C#m(). end diff --git a/test/scip/testdata/hashes.snapshot.rb b/test/scip/testdata/hashes.snapshot.rb index 8a3cb2b5db..376f343470 100644 --- a/test/scip/testdata/hashes.snapshot.rb +++ b/test/scip/testdata/hashes.snapshot.rb @@ -1,7 +1,7 @@ # typed: true def hashes(h, k) -#^^^^^^^^^^^^^^^^ definition [..] Object#hashes(). +# ^^^^^^ definition [..] Object#hashes(). # ^ definition local 1~#1685166589 # ^ definition local 2~#1685166589 h["hello"] = "world" diff --git a/test/scip/testdata/hoverdocs.snapshot.rb b/test/scip/testdata/hoverdocs.snapshot.rb index 06517de908..3f37950e45 100644 --- a/test/scip/testdata/hoverdocs.snapshot.rb +++ b/test/scip/testdata/hoverdocs.snapshot.rb @@ -11,51 +11,39 @@ class C1 # documentation # | Class doc comment extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# def m1 -# ^^^^^^ definition [..] C1#m1(). -# documentation -# | ```ruby -# | sig {returns(T.untyped)} -# | def m1 -# | ``` +# ^^ definition [..] C1#m1(). +# documentation +# | ```ruby +# | sig {returns(T.untyped)} +# | def m1 +# | ``` end sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def m2 -# ^^^^^^ definition [..] C1#m2(). -# documentation -# | ```ruby -# | sig {returns(T::Boolean)} -# | def m2 -# | ``` +# ^^ definition [..] C1#m2(). +# documentation +# | ```ruby +# | sig {returns(T::Boolean)} +# | def m2 +# | ``` true end sig { params(C, T::Boolean).returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). # ^ reference [..] `T.untyped`# -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def m3(c, b) -# ^^^^^^^^^^^^ definition [..] C1#m3(). -# documentation -# | ```ruby -# | sig {params(c: T.untyped, b: T.untyped).returns(T::Boolean)} -# | def m3(c, b) -# | ``` +# ^^ definition [..] C1#m3(). +# documentation +# | ```ruby +# | sig {params(c: T.untyped, b: T.untyped).returns(T::Boolean)} +# | def m3(c, b) +# | ``` # ^ definition local 1~#2519626513 # documentation # | ```ruby @@ -74,15 +62,15 @@ def m3(c, b) # _This_ is a # **doc comment.** def m4(xs) -# ^^^^^^^^^^ definition [..] C1#m4(). -# documentation -# | ```ruby -# | sig {params(xs: T.untyped).returns(T.untyped)} -# | def m4(xs) -# | ``` -# documentation -# | _This_ is a -# | **doc comment.** +# ^^ definition [..] C1#m4(). +# documentation +# | ```ruby +# | sig {params(xs: T.untyped).returns(T.untyped)} +# | def m4(xs) +# | ``` +# documentation +# | _This_ is a +# | **doc comment.** # ^^ definition local 1~#2536404132 # documentation # | ```ruby @@ -95,46 +83,36 @@ def m4(xs) # Yet another.. # ...doc comment sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def m5 -# ^^^^^^ definition [..] C1#m5(). -# documentation -# | ```ruby -# | sig {returns(T::Boolean)} -# | def m5 -# | ``` -# documentation -# | Yet another.. -# | ...doc comment +# ^^ definition [..] C1#m5(). +# documentation +# | ```ruby +# | sig {returns(T::Boolean)} +# | def m5 +# | ``` +# documentation +# | Yet another.. +# | ...doc comment true end # And... # ...one more doc comment sig { params(C, T::Boolean).returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). # ^ reference [..] `T.untyped`# -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def m6(c, b) -# ^^^^^^^^^^^^ definition [..] C1#m6(). -# documentation -# | ```ruby -# | sig {params(c: T.untyped, b: T.untyped).returns(T::Boolean)} -# | def m6(c, b) -# | ``` -# documentation -# | And... -# | ...one more doc comment +# ^^ definition [..] C1#m6(). +# documentation +# | ```ruby +# | sig {params(c: T.untyped, b: T.untyped).returns(T::Boolean)} +# | def m6(c, b) +# | ``` +# documentation +# | And... +# | ...one more doc comment # ^ definition local 1~#2569959370 # documentation # | ```ruby @@ -193,52 +171,46 @@ module M2 # documentation # | This module is nested inside M1 extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# # This method is inside M1::M2 sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def n1 -# ^^^^^^ definition [..] M1#M2#n1(). -# documentation -# | ```ruby -# | sig {returns(T::Boolean)} -# | def n1 -# | ``` -# documentation -# | This method is inside M1::M2 +# ^^ definition [..] M1#M2#n1(). +# documentation +# | ```ruby +# | sig {returns(T::Boolean)} +# | def n1 +# | ``` +# documentation +# | This method is inside M1::M2 true end # This method is also inside M1::M2 def n2 -# ^^^^^^ definition [..] M1#M2#n2(). -# documentation -# | ```ruby -# | sig {returns(T.untyped)} -# | def n2 -# | ``` -# documentation -# | This method is also inside M1::M2 +# ^^ definition [..] M1#M2#n2(). +# documentation +# | ```ruby +# | sig {returns(T.untyped)} +# | def n2 +# | ``` +# documentation +# | This method is also inside M1::M2 end end end # This is a global function def f1 -#^^^^^^ definition [..] Object#f1(). -#documentation -#| ```ruby -#| sig {returns(T.untyped)} -#| def f1 -#| ``` -#documentation -#| This is a global function +# ^^ definition [..] Object#f1(). +# documentation +# | ```ruby +# | sig {returns(T.untyped)} +# | def f1 +# | ``` +# documentation +# | This is a global function M1::M2::m6 # ^^ reference [..] M1# # ^^ reference [..] M1#M2# @@ -255,24 +227,24 @@ def f1 # ^^^^^^^ reference [..] `T.untyped`# # ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def f2 -#^^^^^^ definition [..] Object#f2(). -#documentation -#| ```ruby -#| sig {returns(T::Integer (unresolved))} -#| def f2 -#| ``` -#documentation -#| Yet another global function +# ^^ definition [..] Object#f2(). +# documentation +# | ```ruby +# | sig {returns(T::Integer (unresolved))} +# | def f2 +# | ``` +# documentation +# | Yet another global function return 10 end def f3 # undocumented global function -#^^^^^^ definition [..] Object#f3(). -#documentation -#| ```ruby -#| sig {returns(T.untyped)} -#| def f3 -#| ``` +# ^^ definition [..] Object#f3(). +# documentation +# | ```ruby +# | sig {returns(T.untyped)} +# | def f3 +# | ``` end extend T::Sig @@ -286,12 +258,12 @@ def f3 # undocumented global function # ^^^^^^^ reference [..] `T.untyped`# # ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def f4 # another undocumented global function -#^^^^^^ definition [..] Object#f4(). -#documentation -#| ```ruby -#| sig {returns(T::Integer (unresolved))} -#| def f4 -#| ``` +# ^^ definition [..] Object#f4(). +# documentation +# | ```ruby +# | sig {returns(T::Integer (unresolved))} +# | def f4 +# | ``` return 10 end @@ -306,14 +278,14 @@ class K1 # | Parent class # sets @x and @@y def p1 -# ^^^^^^ definition [..] K1#p1(). -# documentation -# | ```ruby -# | sig {returns(T.untyped)} -# | def p1 -# | ``` -# documentation -# | sets @x and @@y +# ^^ definition [..] K1#p1(). +# documentation +# | ```ruby +# | sig {returns(T.untyped)} +# | def p1 +# | ``` +# documentation +# | sets @x and @@y @x = 10 # ^^ definition [..] K1#`@x`. # documentation @@ -335,14 +307,14 @@ def p1 # lorem ipsum, you get it def self.p2 -# ^^^^^^^^^^^ definition [..] ``#p2(). -# documentation -# | ```ruby -# | sig {returns(T.untyped)} -# | def self.p2 -# | ``` -# documentation -# | lorem ipsum, you get it +# ^^ definition [..] ``#p2(). +# documentation +# | ```ruby +# | sig {returns(T.untyped)} +# | def self.p2 +# | ``` +# documentation +# | lorem ipsum, you get it @z = 10 # ^^ definition [..] ``#`@z`. # documentation @@ -385,14 +357,14 @@ class K2 < K1 # overrides K1's p1 def p1 -# ^^^^^^ definition [..] K2#p1(). -# documentation -# | ```ruby -# | sig {returns(T.untyped)} -# | def p1 -# | ``` -# documentation -# | overrides K1's p1 +# ^^ definition [..] K2#p1(). +# documentation +# | ```ruby +# | sig {returns(T.untyped)} +# | def p1 +# | ``` +# documentation +# | overrides K1's p1 @x = 20 # ^^ definition [..] K2#`@x`. # documentation diff --git a/test/scip/testdata/implicit_super_arg.snapshot.rb b/test/scip/testdata/implicit_super_arg.snapshot.rb index 352c88b9da..003672d3b8 100644 --- a/test/scip/testdata/implicit_super_arg.snapshot.rb +++ b/test/scip/testdata/implicit_super_arg.snapshot.rb @@ -21,7 +21,7 @@ class C # ^ definition [..] C# def f(a, b) -# ^^^^^^^^^^^ definition [..] C#f(). +# ^ definition [..] C#f(). # ^ definition local 1~#3809224601 # ^ definition local 2~#3809224601 super diff --git a/test/scip/testdata/inheritance.snapshot.rb b/test/scip/testdata/inheritance.snapshot.rb index 9bbdc70d8b..8556c248a1 100644 --- a/test/scip/testdata/inheritance.snapshot.rb +++ b/test/scip/testdata/inheritance.snapshot.rb @@ -3,18 +3,11 @@ class Z1 # ^^ definition [..] Z1# extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# sig { params(a: T::Boolean).void } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^ reference [..] T#Private#Methods#DeclBuilder#void(). def write_f(a) -# ^^^^^^^^^^^^^^ definition [..] Z1#write_f(). +# ^^^^^^^ definition [..] Z1#write_f(). # ^ definition local 1~#1000661517 @f = a # ^^ definition [..] Z1#`@f`. @@ -23,13 +16,9 @@ def write_f(a) end sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def read_f? -# ^^^^^^^^^^^ definition [..] Z1#`read_f?`(). +# ^^^^^^^ definition [..] Z1#`read_f?`(). @f # ^^ reference [..] Z1#`@f`. end @@ -38,30 +27,19 @@ def read_f? class Z2 # ^^ definition [..] Z2# extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def read_f? -# ^^^^^^^^^^^ definition [..] Z2#`read_f?`(). +# ^^^^^^^ definition [..] Z2#`read_f?`(). @f # ^^ reference [..] Z2#`@f`. end sig { params(a: T::Boolean).void } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^ reference [..] T#Private#Methods#DeclBuilder#void(). def write_f(a) -# ^^^^^^^^^^^^^^ definition [..] Z2#write_f(). +# ^^^^^^^ definition [..] Z2#write_f(). # ^ definition local 1~#1000661517 @f = a # ^^ definition [..] Z2#`@f`. @@ -74,17 +52,11 @@ class Z3 < Z1 # ^^ definition [..] Z3# # ^^ definition [..] Z1# extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def read_f_plus_1? -# ^^^^^^^^^^^^^^^^^^ definition [..] Z3#`read_f_plus_1?`(). +# ^^^^^^^^^^^^^^ definition [..] Z3#`read_f_plus_1?`(). @f + 1 # ^^ reference [..] Z3#`@f`. end @@ -94,18 +66,11 @@ class Z4 < Z3 # ^^ definition [..] Z4# # ^^ definition [..] Z3# extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# sig { params(a: T::Boolean).void } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^ reference [..] T#Private#Methods#DeclBuilder#params(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^ reference [..] T#Private#Methods#DeclBuilder#void(). def write_f_plus_1(a) -# ^^^^^^^^^^^^^^^^^^^^^ definition [..] Z4#write_f_plus_1(). +# ^^^^^^^^^^^^^^ definition [..] Z4#write_f_plus_1(). # ^ definition local 1~#3337417690 write_f(a) # ^ reference local 1~#3337417690 diff --git a/test/scip/testdata/loops_and_conditionals.snapshot.rb b/test/scip/testdata/loops_and_conditionals.snapshot.rb index 24cc13e110..4a872437c8 100644 --- a/test/scip/testdata/loops_and_conditionals.snapshot.rb +++ b/test/scip/testdata/loops_and_conditionals.snapshot.rb @@ -1,7 +1,7 @@ # typed: true def if_elsif_else() -#^^^^^^^^^^^^^^^^^^^ definition [..] Object#if_elsif_else(). +# ^^^^^^^^^^^^^ definition [..] Object#if_elsif_else(). x = 0 # ^ definition local 1~#2393773952 y = 0 @@ -44,7 +44,7 @@ def if_elsif_else() end def unless() -#^^^^^^^^^^^^ definition [..] Object#unless(). +# ^^^^^^ definition [..] Object#unless(). z = 0 # ^ definition local 1~#2827997891 x = 1 @@ -67,7 +67,7 @@ def unless() end def case(x, y) -#^^^^^^^^^^^^^^ definition [..] Object#case(). +# ^^^^ definition [..] Object#case(). # ^ definition local 1~#2602907825 # ^ definition local 2~#2602907825 case x @@ -92,7 +92,7 @@ def case(x, y) end def for(xs) -#^^^^^^^^^^^ definition [..] Object#for(). +# ^^^ definition [..] Object#for(). # ^^ definition local 1~#2901640080 for e in xs # ^ definition local 2~#2901640080 @@ -125,7 +125,7 @@ def for(xs) end def while(xs) -#^^^^^^^^^^^^^ definition [..] Object#while(). +# ^^^^^ definition [..] Object#while(). # ^^ definition local 1~#231090382 i = 0 # ^ definition local 2~#231090382 @@ -162,7 +162,7 @@ def while(xs) end def until(xs) -#^^^^^^^^^^^^^ definition [..] Object#until(). +# ^^^^^ definition [..] Object#until(). # ^^ definition local 1~#3132432719 i = 0 # ^ definition local 2~#3132432719 @@ -199,7 +199,7 @@ def until(xs) end def flip_flop(xs) -#^^^^^^^^^^^^^^^^^ definition [..] Object#flip_flop(). +# ^^^^^^^^^ definition [..] Object#flip_flop(). # ^^ definition local 1~#2191960030 # NOTE: flip-flops are unsupported (https://srb.help/3003) # Unlike redo, which somehow works, we fail to emit references diff --git a/test/scip/testdata/mattr.rb b/test/scip/testdata/mattr.rb new file mode 100644 index 0000000000..c6e4001a09 --- /dev/null +++ b/test/scip/testdata/mattr.rb @@ -0,0 +1,63 @@ +# typed: strict + +class MR + extend T::Sig + mattr_reader :both, :foo + mattr_reader :no_instance, instance_accessor: false + mattr_reader :bar, :no_instance_reader, instance_reader: false + + sig {void} + def usages + both + end + + both + no_instance + no_instance_reader +end + +class MW + extend T::Sig + mattr_writer :both, :foo + mattr_writer :no_instance, instance_accessor: false + mattr_writer :bar, :no_instance_writer, instance_writer: false + + sig {void} + def usages + self.both = 1 + end + + self.both = 1 + self.no_instance = 1 + self.no_instance_writer = 1 +end + +class MA + extend T::Sig + mattr_accessor :both, :foo + mattr_accessor :no_instance, instance_accessor: false + mattr_accessor :no_instance_reader, instance_reader: false + mattr_accessor :bar, :no_instance_writer, instance_writer: false + + sig {void} + def usages + both + self.both = 1 + + self.no_instance_reader= 1 + + no_instance_writer + end + + both + self.both = 1 + + no_instance + self.no_instance = 1 + + no_instance_reader + self.no_instance_reader = 1 + + no_instance_writer + self.no_instance_writer = 1 +end diff --git a/test/scip/testdata/mattr.snapshot.rb b/test/scip/testdata/mattr.snapshot.rb new file mode 100644 index 0000000000..abbc161f71 --- /dev/null +++ b/test/scip/testdata/mattr.snapshot.rb @@ -0,0 +1,122 @@ + # typed: strict + + class MR +# ^^ definition [..] MR# + extend T::Sig + mattr_reader :both, :foo +# ^^^^^ definition [..] MR#both(). +# ^^^^^ definition [..] ``#both(). +# ^^^^ definition [..] MR#foo(). +# ^^^^ definition [..] ``#foo(). + mattr_reader :no_instance, instance_accessor: false +# ^^^^^^^^^^^^ definition [..] ``#no_instance(). + mattr_reader :bar, :no_instance_reader, instance_reader: false +# ^^^^ definition [..] ``#bar(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#no_instance_reader(). + + sig {void} + def usages +# ^^^^^^ definition [..] MR#usages(). + both +# ^^^^ reference [..] MR#both(). + end + + both +# ^^^^ reference [..] ``#both(). + no_instance +# ^^^^^^^^^^^ reference [..] ``#no_instance(). + no_instance_reader +# ^^^^^^^^^^^^^^^^^^ reference [..] ``#no_instance_reader(). + end + + class MW +# ^^ definition [..] MW# + extend T::Sig + mattr_writer :both, :foo +# ^^^^^ definition [..] MW#`both=`(). +# ^^^^^ definition [..] ``#`both=`(). +# ^^^^ definition [..] MW#`foo=`(). +# ^^^^ definition [..] ``#`foo=`(). + mattr_writer :no_instance, instance_accessor: false +# ^^^^^^^^^^^^ definition [..] ``#`no_instance=`(). + mattr_writer :bar, :no_instance_writer, instance_writer: false +# ^^^^ definition [..] ``#`bar=`(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#`no_instance_writer=`(). + + sig {void} + def usages +# ^^^^^^ definition [..] MW#usages(). + self.both = 1 +# ^^^^^^ reference [..] MW#`both=`(). + end + + self.both = 1 +# ^^^^^^ reference [..] ``#`both=`(). + self.no_instance = 1 +# ^^^^^^^^^^^^^ reference [..] ``#`no_instance=`(). + self.no_instance_writer = 1 +# ^^^^^^^^^^^^^^^^^^^^ reference [..] ``#`no_instance_writer=`(). + end + + class MA +# ^^ definition [..] MA# + extend T::Sig + mattr_accessor :both, :foo +# ^^^^^ definition [..] MA#`both=`(). +# ^^^^^ definition [..] ``#both(). +# ^^^^^ definition [..] MA#both(). +# ^^^^^ definition [..] ``#`both=`(). +# ^^^^ definition [..] MA#foo(). +# ^^^^ definition [..] ``#foo(). +# ^^^^ definition [..] MA#`foo=`(). +# ^^^^ definition [..] ``#`foo=`(). + mattr_accessor :no_instance, instance_accessor: false +# ^^^^^^^^^^^^ definition [..] ``#no_instance(). +# ^^^^^^^^^^^^ definition [..] ``#`no_instance=`(). + mattr_accessor :no_instance_reader, instance_reader: false +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#no_instance_reader(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] MA#`no_instance_reader=`(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#`no_instance_reader=`(). + mattr_accessor :bar, :no_instance_writer, instance_writer: false +# ^^^^ definition [..] MA#bar(). +# ^^^^ definition [..] ``#bar(). +# ^^^^ definition [..] ``#`bar=`(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] MA#no_instance_writer(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#no_instance_writer(). +# ^^^^^^^^^^^^^^^^^^^ definition [..] ``#`no_instance_writer=`(). + + sig {void} + def usages +# ^^^^^^ definition [..] MA#usages(). + both +# ^^^^ reference [..] MA#both(). + self.both = 1 +# ^^^^^^ reference [..] MA#`both=`(). + + self.no_instance_reader= 1 +# ^^^^^^^^^^^^^^^^^^^ reference [..] MA#`no_instance_reader=`(). + + no_instance_writer +# ^^^^^^^^^^^^^^^^^^ reference [..] MA#no_instance_writer(). + end + + both +# ^^^^ reference [..] ``#both(). + self.both = 1 +# ^^^^^^ reference [..] ``#`both=`(). + + no_instance +# ^^^^^^^^^^^ reference [..] ``#no_instance(). + self.no_instance = 1 +# ^^^^^^^^^^^^^ reference [..] ``#`no_instance=`(). + + no_instance_reader +# ^^^^^^^^^^^^^^^^^^ reference [..] ``#no_instance_reader(). + self.no_instance_reader = 1 +# ^^^^^^^^^^^^^^^^^^^^ reference [..] ``#`no_instance_reader=`(). + + no_instance_writer +# ^^^^^^^^^^^^^^^^^^ reference [..] ``#no_instance_writer(). + self.no_instance_writer = 1 +# ^^^^^^^^^^^^^^^^^^^^ reference [..] ``#`no_instance_writer=`(). + end diff --git a/test/scip/testdata/minitest.rb b/test/scip/testdata/minitest.rb new file mode 100644 index 0000000000..4ec4734d44 --- /dev/null +++ b/test/scip/testdata/minitest.rb @@ -0,0 +1,78 @@ +# typed: true +class MyTest + def outside_method + end + + it "works outside" do + outside_method + end + + it "allows constants inside of IT" do + CONST = 10 + end + + it "allows let-ed constants inside of IT" do + C2 = T.let(10, Integer) + end + + it "allows path constants inside of IT" do + C3 = Mod::C + C3.new + end + + describe "some inner tests" do + def inside_method + end + + it "works inside" do + outside_method + inside_method + end + end + + def instance_helper; end + + before do + @foo = T.let(3, Integer) + instance_helper + end + + it 'can read foo' do + T.assert_type!(@foo, Integer) + instance_helper + end + + def self.random_method + end + + describe Object do + it Object do + end + it Object do + end + end + + def self.it(*args) + end + it "ignores methods without a block" + + junk.it "ignores non-self calls" do + junk + end + + describe "a non-ideal situation" do + it "contains nested describes" do + describe "nobody should write this but we should still parse it" do + end + end + end +end + +def junk +end + + +module Mod + class C + end +end diff --git a/test/scip/testdata/minitest.snapshot.rb b/test/scip/testdata/minitest.snapshot.rb new file mode 100644 index 0000000000..eaaf6cc6c7 --- /dev/null +++ b/test/scip/testdata/minitest.snapshot.rb @@ -0,0 +1,112 @@ + # typed: true + class MyTest +# ^^^^^^ definition [..] MyTest# + def outside_method +# ^^^^^^^^^^^^^^ definition [..] MyTest#outside_method(). + end + + it "works outside" do +# ^^^^^^^^^^^^^^^ definition [..] MyTest#``(). + outside_method + end + + it "allows constants inside of IT" do +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#``(). + CONST = 10 +# ^^^^^ definition [..] MyTest#CONST. +# ^^^^^^^^^^ reference [..] Kernel# + end + + it "allows let-ed constants inside of IT" do +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#``(). + C2 = T.let(10, Integer) +# ^^ definition [..] MyTest#C2. +# ^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Kernel# +# ^^^^^^^ reference [..] Integer# + end + + it "allows path constants inside of IT" do +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#``(). + C3 = Mod::C +# ^^ definition [..] MyTest#C3. +# ^^^ reference [..] Mod# +# ^ reference [..] Mod#C# + C3.new + end + + describe "some inner tests" do +# ^^^^^^^^^^^^^^^^^^ definition [..] MyTest#``# + def inside_method +# ^^^^^^^^^^^^^ definition [..] MyTest#``#inside_method(). + end + + it "works inside" do +# ^^^^^^^^^^^^^^ definition [..] MyTest#``#``(). + outside_method + inside_method + end + end + + def instance_helper; end +# ^^^^^^^^^^^^^^^ definition [..] MyTest#instance_helper(). + + before do +# ^^^^^^ definition [..] MyTest#initialize(). + @foo = T.let(3, Integer) + instance_helper + end + + it 'can read foo' do +# ^^^^^^^^^^^^^^ definition [..] MyTest#``(). + T.assert_type!(@foo, Integer) + instance_helper + end + + def self.random_method +# ^^^^^^^^^^^^^ definition [..] ``#random_method(). + end + + describe Object do +# ^^^^^^ definition [..] MyTest#``# + it Object do +# ^^^^^^ definition [..] MyTest#``#``(). +# ^^^^^^ definition [..] MyTest#``#``(). +# ^^^^^^ reference [..] Object# + end + it Object do +# ^^^^^^ reference [..] Object# + end + end + + def self.it(*args) +# ^^ definition [..] ``#it(). + end + it "ignores methods without a block" +# ^^ reference [..] ``#it(). + + junk.it "ignores non-self calls" do + junk + end + + describe "a non-ideal situation" do +# ^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#``# + it "contains nested describes" do +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#``#``(). + describe "nobody should write this but we should still parse it" do +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#``#``# + end + end + end + end + + def junk +# ^^^^ definition [..] Object#junk(). + end + + + module Mod +# ^^^ definition [..] Mod# + class C +# ^ definition [..] Mod#C# + end + end diff --git a/test/scip/testdata/types.rb b/test/scip/testdata/module_function.rb similarity index 59% rename from test/scip/testdata/types.rb rename to test/scip/testdata/module_function.rb index f7dd8cc5c4..8da0c6e48d 100644 --- a/test/scip/testdata/types.rb +++ b/test/scip/testdata/module_function.rb @@ -1,13 +1,10 @@ # typed: true -def f() - T.let(true, T::Boolean) -end - module M - module_function sig { returns(T::Boolean) } def b true end + + module_function :b end diff --git a/test/scip/testdata/module_function.snapshot.rb b/test/scip/testdata/module_function.snapshot.rb new file mode 100644 index 0000000000..2379b31e56 --- /dev/null +++ b/test/scip/testdata/module_function.snapshot.rb @@ -0,0 +1,14 @@ + # typed: true + + module M +# ^ definition [..] M# + sig { returns(T::Boolean) } +# ^^^^^^^ reference [..] T#Boolean. + def b +# ^ definition [..] M#b(). + true + end + + module_function :b +# ^^ definition [..] ``#b(). + end diff --git a/test/scip/testdata/multifile/basic/def_class1.snapshot.rb b/test/scip/testdata/multifile/basic/def_class1.snapshot.rb index 84e94e3170..3435f1bcf9 100644 --- a/test/scip/testdata/multifile/basic/def_class1.snapshot.rb +++ b/test/scip/testdata/multifile/basic/def_class1.snapshot.rb @@ -3,17 +3,11 @@ class C1 # ^^ definition [..] C1# extend T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^ reference [..] T#Private#Methods#DeclBuilder#returns(). -# ^ reference [..] T# # ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# def m1 -# ^^^^^^ definition [..] C1#m1(). +# ^^ definition [..] C1#m1(). true end end diff --git a/test/scip/testdata/prop.rb b/test/scip/testdata/prop.rb new file mode 100644 index 0000000000..1fc5baed62 --- /dev/null +++ b/test/scip/testdata/prop.rb @@ -0,0 +1,105 @@ +# typed: true + +class SomeODM + extend T::Sig + include T::Props + + prop :foo, String + + sig {returns(T.nilable(String))} + def foo2; T.cast(T.unsafe(nil), T.nilable(String)); end + sig {params(arg0: String).returns(String)} + def foo2=(arg0); T.cast(nil, String); end +end + +class ForeignClass +end + +class AdvancedODM + include T::Props + prop :default, String, default: "" + prop :t_nilable, T.nilable(String) + + prop :array, Array + prop :t_array, T::Array[String] + prop :hash_of, T::Hash[Symbol, String] + + prop :const_explicit, String, immutable: true + const :const, String + + prop :enum_prop, String, enum: ["hello", "goodbye"] + + prop :foreign_lazy, String, foreign: -> {ForeignClass} + prop :foreign_proc, String, foreign: proc {ForeignClass} + prop :foreign_invalid, String, foreign: proc { :not_a_type } + + prop :ifunset, String, ifunset: '' + prop :ifunset_nilable, T.nilable(String), ifunset: '' + + prop :empty_hash_rules, String, {} + prop :hash_rules, String, { enum: ["hello", "goodbye" ] } +end + +class PropHelpers + include T::Props + def self.token_prop(opts={}); end + def self.created_prop(opts={}); end + token_prop + created_prop +end + +class PropHelpers2 + include T::Props + def self.timestamped_token_prop(opts={}); end + def self.created_prop(opts={}); end + timestamped_token_prop + created_prop(immutable: true) +end + +def main + SomeODM.new.foo + SomeODM.new.foo = 'b' + SomeODM.new.foo2 + SomeODM.new.foo2 = 'b' + + AdvancedODM.new.default + AdvancedODM.new.t_nilable + + AdvancedODM.new.t_array + AdvancedODM.new.hash_of + + AdvancedODM.new.const_explicit + AdvancedODM.new.const_explicit = 'b' + AdvancedODM.new.const + AdvancedODM.new.const = 'b' + + AdvancedODM.new.enum_prop + AdvancedODM.new.enum_prop = "hello" + + AdvancedODM.new.foreign_ + AdvancedODM.new.foreign_ + AdvancedODM.new.foreign_lazy_ + + # Check that the method still exists even if we can't parse the type + AdvancedODM.new.foreign_invalid_ + + PropHelpers.new.token + PropHelpers.new.token = "tok_token" + PropHelpers.new.token = nil + + PropHelpers.new.created + PropHelpers.new.created = 0.0 + PropHelpers.new.created = nil + + PropHelpers2.new.token + PropHelpers2.new.token = "tok_token" + PropHelpers2.new.token = nil + + PropHelpers2.new.created + PropHelpers2.new.created = 0.0 + + AdvancedODM.new.ifunset + AdvancedODM.new.ifunset_nilable + AdvancedODM.new.ifunset = nil + AdvancedODM.new.ifunset_nilable = nil +end diff --git a/test/scip/testdata/prop.snapshot.rb b/test/scip/testdata/prop.snapshot.rb new file mode 100644 index 0000000000..b915d90fbf --- /dev/null +++ b/test/scip/testdata/prop.snapshot.rb @@ -0,0 +1,261 @@ + # typed: true + + class SomeODM +# ^^^^^^^ definition [..] SomeODM# + extend T::Sig + include T::Props + + prop :foo, String +# ^^^ definition [..] SomeODM#foo(). +# ^^^ definition [..] SomeODM#`foo=`(). +# ^^^^^^ reference [..] String# + + sig {returns(T.nilable(String))} +# ^^^^^^ reference [..] String# + def foo2; T.cast(T.unsafe(nil), T.nilable(String)); end +# ^^^^ definition [..] SomeODM#foo2(). +# ^ reference [..] T# +# ^^^^^^ reference [..] ``#unsafe(). +# ^ reference [..] T# +# ^^^^^^^ reference [..] ``#nilable(). +# ^^^^^^ reference [..] String# + sig {params(arg0: String).returns(String)} +# ^^^^^^ reference [..] String# +# ^^^^^^ reference [..] String# + def foo2=(arg0); T.cast(nil, String); end +# ^^^^^ definition [..] SomeODM#`foo2=`(). +# ^^^^^^ reference [..] String# + end + + class ForeignClass +# ^^^^^^^^^^^^ definition [..] ForeignClass# + end + + class AdvancedODM +# ^^^^^^^^^^^ definition [..] AdvancedODM# + include T::Props + prop :default, String, default: "" +# ^^^^^^^ definition [..] AdvancedODM#default(). +# ^^^^^^^ definition [..] AdvancedODM#`default=`(). +# ^^^^^^ reference [..] String# + prop :t_nilable, T.nilable(String) +# ^^^^^^^^^ definition [..] AdvancedODM#t_nilable(). +# ^^^^^^^^^ definition [..] AdvancedODM#`t_nilable=`(). +# ^^^^^^ reference [..] String# + + prop :array, Array +# ^^^^^ definition [..] AdvancedODM#`array=`(). +# ^^^^^ definition [..] AdvancedODM#array(). +# ^^^^^ reference [..] Array# + prop :t_array, T::Array[String] +# ^^^^^^^ definition [..] AdvancedODM#t_array(). +# ^^^^^^^ definition [..] AdvancedODM#`t_array=`(). +# ^^^^^^ reference [..] String# + prop :hash_of, T::Hash[Symbol, String] +# ^^^^^^^ definition [..] AdvancedODM#hash_of(). +# ^^^^^^^ definition [..] AdvancedODM#`hash_of=`(). +# ^^^^^^ reference [..] Symbol# +# ^^^^^^ reference [..] String# + + prop :const_explicit, String, immutable: true +# ^^^^^^^^^^^^^^ definition [..] AdvancedODM#const_explicit(). +# ^^^^^^ reference [..] String# + const :const, String +# ^^^^^ definition [..] AdvancedODM#const(). +# ^^^^^^ reference [..] String# + + prop :enum_prop, String, enum: ["hello", "goodbye"] +# ^^^^^^^^^ definition [..] AdvancedODM#`enum_prop=`(). +# ^^^^^^^^^ definition [..] AdvancedODM#enum_prop(). +# ^^^^^^ reference [..] String# + + prop :foreign_lazy, String, foreign: -> {ForeignClass} +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Boolean. +# ^^^^^^^^^^^^ definition [..] AdvancedODM#`foreign_lazy_!`(). +# ^^^^^^^^^^^^ definition [..] AdvancedODM#foreign_lazy_(). +# ^^^^^^^^^^^^ definition [..] AdvancedODM#`foreign_lazy=`(). +# ^^^^^^^^^^^^ definition [..] AdvancedODM#foreign_lazy(). +# ^^^^^^ reference [..] String# +# ^^ reference [..] Kernel# +# ^^^^^^^^^^^^ reference [..] ForeignClass# + prop :foreign_proc, String, foreign: proc {ForeignClass} +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Boolean. +# ^^^^^^^^^^^^ definition [..] AdvancedODM#`foreign_proc_!`(). +# ^^^^^^^^^^^^ definition [..] AdvancedODM#foreign_proc_(). +# ^^^^^^^^^^^^ definition [..] AdvancedODM#`foreign_proc=`(). +# ^^^^^^^^^^^^ definition [..] AdvancedODM#foreign_proc(). +# ^^^^^^ reference [..] String# +# ^^^^^^^^^^^^ reference [..] ForeignClass# + prop :foreign_invalid, String, foreign: proc { :not_a_type } +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] T#Boolean. +# ^^^^^^^^^^^^^^^ definition [..] AdvancedODM#`foreign_invalid_!`(). +# ^^^^^^^^^^^^^^^ definition [..] AdvancedODM#foreign_invalid_(). +# ^^^^^^^^^^^^^^^ definition [..] AdvancedODM#`foreign_invalid=`(). +# ^^^^^^^^^^^^^^^ definition [..] AdvancedODM#foreign_invalid(). +# ^^^^^^ reference [..] String# + + prop :ifunset, String, ifunset: '' +# ^^^^^^^ definition [..] AdvancedODM#ifunset(). +# ^^^^^^^ definition [..] AdvancedODM#`ifunset=`(). +# ^^^^^^ reference [..] String# + prop :ifunset_nilable, T.nilable(String), ifunset: '' +# ^^^^^^^^^^^^^^^ definition [..] AdvancedODM#ifunset_nilable(). +# ^^^^^^^^^^^^^^^ definition [..] AdvancedODM#`ifunset_nilable=`(). +# ^^^^^^ reference [..] String# + + prop :empty_hash_rules, String, {} +# ^^^^^^^^^^^^^^^^ definition [..] AdvancedODM#empty_hash_rules(). +# ^^^^^^^^^^^^^^^^ definition [..] AdvancedODM#`empty_hash_rules=`(). +# ^^^^^^ reference [..] String# + prop :hash_rules, String, { enum: ["hello", "goodbye" ] } +# ^^^^^^^^^^ definition [..] AdvancedODM#`hash_rules=`(). +# ^^^^^^^^^^ definition [..] AdvancedODM#hash_rules(). +# ^^^^^^ reference [..] String# + end + + class PropHelpers +# ^^^^^^^^^^^ definition [..] PropHelpers# + include T::Props + def self.token_prop(opts={}); end +# ^^^^^^^^^^ definition [..] ``#token_prop(). + def self.created_prop(opts={}); end +# ^^^^^^^^^^^^ definition [..] ``#created_prop(). + token_prop +# ^^^^^ definition [..] PropHelpers#`token=`(). +# ^^^^^ definition [..] PropHelpers#token(). +# ^^^^^^^^^^ reference [..] ``#token_prop(). +# ^^^^^^^^^^ reference [..] String# + created_prop +# ^^^^^^^ definition [..] PropHelpers#`created=`(). +# ^^^^^^^ definition [..] PropHelpers#created(). +# ^^^^^^^^^^^^ reference [..] ``#created_prop(). +# ^^^^^^^^^^^^ reference [..] Float# + end + + class PropHelpers2 +# ^^^^^^^^^^^^ definition [..] PropHelpers2# + include T::Props + def self.timestamped_token_prop(opts={}); end +# ^^^^^^^^^^^^^^^^^^^^^^ definition [..] ``#timestamped_token_prop(). + def self.created_prop(opts={}); end +# ^^^^^^^^^^^^ definition [..] ``#created_prop(). + timestamped_token_prop +# ^^^^^^^^^^^^^^^^^^^^^^ reference [..] String# +# ^^^^^^^^^^^^^^^^^^^^^^ reference [..] ``#timestamped_token_prop(). +# ^^^^^ definition [..] PropHelpers2#token(). +# ^^^^^ definition [..] PropHelpers2#`token=`(). + created_prop(immutable: true) +# ^^^^^^^^^^^^ reference [..] ``#created_prop(). +# ^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] PropHelpers2#created(). +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Float# + end + + def main +# ^^^^ definition [..] Object#main(). + SomeODM.new.foo +# ^^^^^^^ reference [..] SomeODM# +# ^^^ reference [..] SomeODM#foo(). + SomeODM.new.foo = 'b' +# ^^^^^^^ reference [..] SomeODM# +# ^^^^^ reference [..] SomeODM#`foo=`(). + SomeODM.new.foo2 +# ^^^^^^^ reference [..] SomeODM# +# ^^^^ reference [..] SomeODM#foo2(). + SomeODM.new.foo2 = 'b' +# ^^^^^^^ reference [..] SomeODM# +# ^^^^^^ reference [..] SomeODM#`foo2=`(). + + AdvancedODM.new.default +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^ reference [..] AdvancedODM#default(). + AdvancedODM.new.t_nilable +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^ reference [..] AdvancedODM#t_nilable(). + + AdvancedODM.new.t_array +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^ reference [..] AdvancedODM#t_array(). + AdvancedODM.new.hash_of +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^ reference [..] AdvancedODM#hash_of(). + + AdvancedODM.new.const_explicit +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^^^^^^ reference [..] AdvancedODM#const_explicit(). + AdvancedODM.new.const_explicit = 'b' +# ^^^^^^^^^^^ reference [..] AdvancedODM# + AdvancedODM.new.const +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^ reference [..] AdvancedODM#const(). + AdvancedODM.new.const = 'b' +# ^^^^^^^^^^^ reference [..] AdvancedODM# + + AdvancedODM.new.enum_prop +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^ reference [..] AdvancedODM#enum_prop(). + AdvancedODM.new.enum_prop = "hello" +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^^^ reference [..] AdvancedODM#`enum_prop=`(). + + AdvancedODM.new.foreign_ +# ^^^^^^^^^^^ reference [..] AdvancedODM# + AdvancedODM.new.foreign_ +# ^^^^^^^^^^^ reference [..] AdvancedODM# + AdvancedODM.new.foreign_lazy_ +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^^^^^ reference [..] AdvancedODM#foreign_lazy_(). + + # Check that the method still exists even if we can't parse the type + AdvancedODM.new.foreign_invalid_ +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^^^^^^^^ reference [..] AdvancedODM#foreign_invalid_(). + + PropHelpers.new.token +# ^^^^^^^^^^^ reference [..] PropHelpers# +# ^^^^^ reference [..] PropHelpers#token(). + PropHelpers.new.token = "tok_token" +# ^^^^^^^^^^^ reference [..] PropHelpers# +# ^^^^^^^ reference [..] PropHelpers#`token=`(). + PropHelpers.new.token = nil +# ^^^^^^^^^^^ reference [..] PropHelpers# +# ^^^^^^^ reference [..] PropHelpers#`token=`(). + + PropHelpers.new.created +# ^^^^^^^^^^^ reference [..] PropHelpers# +# ^^^^^^^ reference [..] PropHelpers#created(). + PropHelpers.new.created = 0.0 +# ^^^^^^^^^^^ reference [..] PropHelpers# +# ^^^^^^^^^ reference [..] PropHelpers#`created=`(). + PropHelpers.new.created = nil +# ^^^^^^^^^^^ reference [..] PropHelpers# +# ^^^^^^^^^ reference [..] PropHelpers#`created=`(). + + PropHelpers2.new.token +# ^^^^^^^^^^^^ reference [..] PropHelpers2# +# ^^^^^ reference [..] PropHelpers2#token(). + PropHelpers2.new.token = "tok_token" +# ^^^^^^^^^^^^ reference [..] PropHelpers2# +# ^^^^^^^ reference [..] PropHelpers2#`token=`(). + PropHelpers2.new.token = nil +# ^^^^^^^^^^^^ reference [..] PropHelpers2# +# ^^^^^^^ reference [..] PropHelpers2#`token=`(). + + PropHelpers2.new.created +# ^^^^^^^^^^^^ reference [..] PropHelpers2# +# ^^^^^^^ reference [..] PropHelpers2#created(). + PropHelpers2.new.created = 0.0 +# ^^^^^^^^^^^^ reference [..] PropHelpers2# + + AdvancedODM.new.ifunset +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^ reference [..] AdvancedODM#ifunset(). + AdvancedODM.new.ifunset_nilable +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^^^^^^^ reference [..] AdvancedODM#ifunset_nilable(). + AdvancedODM.new.ifunset = nil +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^ reference [..] AdvancedODM#`ifunset=`(). + AdvancedODM.new.ifunset_nilable = nil +# ^^^^^^^^^^^ reference [..] AdvancedODM# +# ^^^^^^^^^^^^^^^^^ reference [..] AdvancedODM#`ifunset_nilable=`(). + end diff --git a/test/scip/testdata/rescue.snapshot.rb b/test/scip/testdata/rescue.snapshot.rb index 7e7a7cba52..c2102e69fb 100644 --- a/test/scip/testdata/rescue.snapshot.rb +++ b/test/scip/testdata/rescue.snapshot.rb @@ -6,14 +6,14 @@ class MyError < StandardError end def handle(e) -#^^^^^^^^^^^^^ definition [..] Object#handle(). +# ^^^^^^ definition [..] Object#handle(). # ^ definition local 1~#780127187 puts e.inspect.to_s # ^ reference local 1~#780127187 end def f -#^^^^^ definition [..] Object#f(). +# ^ definition [..] Object#f(). begin raise 'This exception will be rescued!' rescue MyError => e1 diff --git a/test/scip/testdata/singleton.rb b/test/scip/testdata/singleton.rb new file mode 100644 index 0000000000..46c01b5c24 --- /dev/null +++ b/test/scip/testdata/singleton.rb @@ -0,0 +1,18 @@ +# typed: true + +class A + include Singleton +end + +# Singleton supports inheritance, turning the sub-class into a singleton as well. +class B < A; end + +class C + include Singleton + extend T::Helpers + final! +end + +def f + return [A.instance, B.instance, C.instance] +end diff --git a/test/scip/testdata/singleton.snapshot.rb b/test/scip/testdata/singleton.snapshot.rb new file mode 100644 index 0000000000..82901b445e --- /dev/null +++ b/test/scip/testdata/singleton.snapshot.rb @@ -0,0 +1,32 @@ + # typed: true + + class A +# ^ definition [..] A# + include Singleton +# ^^^^^^^^^^^^^^^^^ definition [..] ``#instance(). +# ^^^^^^^^^ reference [..] Singleton# + end + + # Singleton supports inheritance, turning the sub-class into a singleton as well. + class B < A; end +# ^ definition [..] B# +# ^ definition [..] A# + + class C +# ^ definition [..] C# + include Singleton +# ^^^^^^^^^^^^^^^^^ definition [..] ``#instance(). +# ^^^^^^^^^ reference [..] Singleton# + extend T::Helpers + final! + end + + def f +# ^ definition [..] Object#f(). + return [A.instance, B.instance, C.instance] +# ^ reference [..] A# +# ^^^^^^^^ reference [..] ``#instance(). +# ^ reference [..] B# +# ^ reference [..] C# +# ^^^^^^^^ reference [..] ``#instance(). + end diff --git a/test/scip/testdata/struct.rb b/test/scip/testdata/struct.rb new file mode 100644 index 0000000000..492ea1facf --- /dev/null +++ b/test/scip/testdata/struct.rb @@ -0,0 +1,28 @@ +# typed: true + +# From Sorbet docs https://sorbet.org/docs/tstruct +class S < T::Struct + prop :prop_i, Integer + const :const_s, T.nilable(String) + const :const_f, Float, default: 0.5 +end + +def f + s = S.new(prop_i: 3) + _ = s.prop_i.to_s + s.const_s + s.const_f.to_s + s.serialize.to_s + s.prop_i = 4 + return +end + +POINT = Struct.new(:x, :y) do + def array + [x, y] + end +end + +def g + p = POINT.new(0, 1) + a = p.array + px = p.x + return +end diff --git a/test/scip/testdata/struct.snapshot.rb b/test/scip/testdata/struct.snapshot.rb new file mode 100644 index 0000000000..5628793687 --- /dev/null +++ b/test/scip/testdata/struct.snapshot.rb @@ -0,0 +1,79 @@ + # typed: true + + # From Sorbet docs https://sorbet.org/docs/tstruct + class S < T::Struct +# ^ definition [..] S#initialize(). +# ^ definition [..] S# +# ^ reference [..] T# +# ^^^^^^ definition [..] T#Struct# + prop :prop_i, Integer +# ^^^^^^ definition [..] S#prop_i(). +# ^^^^^^ definition [..] S#`prop_i=`(). +# ^^^^^^^ reference [..] Integer# + const :const_s, T.nilable(String) +# ^^^^^^^ definition [..] S#const_s(). +# ^^^^^^ reference [..] String# + const :const_f, Float, default: 0.5 +# ^^^^^^^ definition [..] S#const_f(). +# ^^^^^ reference [..] Float# + end + + def f +# ^ definition [..] Object#f(). + s = S.new(prop_i: 3) +# ^ definition local 1~#3809224601 +# ^ reference [..] S# + _ = s.prop_i.to_s + s.const_s + s.const_f.to_s + s.serialize.to_s +# ^ definition local 3~#3809224601 +# ^ reference local 1~#3809224601 +# ^^^^^^ reference [..] S#prop_i(). +# ^^^^ reference [..] Integer#to_s(). +# ^ reference [..] String#+(). +# ^ reference local 1~#3809224601 +# ^^^^^^^ reference [..] S#const_s(). +# ^ reference [..] String#+(). +# ^ reference local 1~#3809224601 +# ^^^^^^^ reference [..] S#const_f(). +# ^^^^ reference [..] Float#to_s(). +# ^ reference [..] String#+(). +# ^ reference local 1~#3809224601 + s.prop_i = 4 +# ^ reference local 1~#3809224601 +# ^^^^^^^^ reference [..] S#`prop_i=`(). + return + end + + POINT = Struct.new(:x, :y) do +#^^^^^ definition [..] POINT# +#^^^^^^^^^^^^^^^^^^^^ definition local 5~#119448696 +#^^^^^^^^^^^^^^^^^^^^ definition [..] Struct# +#^^^^^^^^^^^^^^^^^^^^ definition [..] POINT#initialize(). +# ^ definition [..] POINT#x(). +# ^ definition [..] POINT#`x=`(). +# ^ reference [..] BasicObject# +# ^ definition [..] POINT#y(). +# ^ definition [..] POINT#`y=`(). +# ^ reference [..] BasicObject# + def array +# ^^^^^ definition [..] POINT#array(). + [x, y] +# ^ reference [..] POINT#x(). +# ^ reference [..] POINT#y(). + end + end + + def g +# ^ definition [..] Object#g(). + p = POINT.new(0, 1) +# ^ definition local 1~#3792446982 +# ^^^^^ reference [..] POINT# + a = p.array +# ^ definition local 3~#3792446982 +# ^ reference local 1~#3792446982 +# ^^^^^ reference [..] POINT#array(). + px = p.x +# ^^ definition local 4~#3792446982 +# ^ reference local 1~#3792446982 +# ^ reference [..] POINT#x(). + return + end diff --git a/test/scip/testdata/test_case.rb b/test/scip/testdata/test_case.rb new file mode 100644 index 0000000000..c2e961ee23 --- /dev/null +++ b/test/scip/testdata/test_case.rb @@ -0,0 +1,64 @@ +# typed: strict + +class ActiveSupport::TestCase +end + +class MyTest < ActiveSupport::TestCase + extend T::Sig + # Helper instance method + sig { params(test: T.untyped).returns(T::Boolean) } + def assert(test) + test ? true : false + end + + # Helper method to direct calls to `test` instead of Kernel#test + sig { params(args: T.untyped, block: T.nilable(T.proc.void)).void } + def self.test(*args, &block) + end + + setup do + @a = T.let(1, Integer) + end + + test "valid method call" do + end + + test "block is evaluated in the context of an instance" do + assert true + end +end + +class NoMatchTest < ActiveSupport::TestCase + extend T::Sig + + sig { params(block: T.proc.void).void } + def self.setup(&block); end + + sig { params(block: T.proc.void).void } + def self.teardown(&block); end +end + +class NoParentClass + extend T::Sig + + sig { params(block: T.proc.void).void } + def self.setup(&block); end + + sig { params(block: T.proc.void).void } + def self.teardown(&block); end + + sig { params(a: T.untyped, b: T.untyped).void } + def assert_equal(a, b); end + + setup do + @a = T.let(1, Integer) + end + + test "it works" do + assert_equal 1, @a + end + + teardown do + @a = 5 + end +end diff --git a/test/scip/testdata/test_case.snapshot.rb b/test/scip/testdata/test_case.snapshot.rb new file mode 100644 index 0000000000..59d5ad9e60 --- /dev/null +++ b/test/scip/testdata/test_case.snapshot.rb @@ -0,0 +1,93 @@ + # typed: strict + + class ActiveSupport::TestCase +# ^^^^^^^^^^^^^ reference [..] ActiveSupport# +# ^^^^^^^^ definition [..] ActiveSupport#TestCase# + end + + class MyTest < ActiveSupport::TestCase +# ^^^^^^ definition [..] MyTest# +# ^^^^^^^^^^^^^ reference [..] ActiveSupport# +# ^^^^^^^^ definition [..] ActiveSupport#TestCase# + extend T::Sig + # Helper instance method + sig { params(test: T.untyped).returns(T::Boolean) } +# ^^^^^^^ reference [..] T#Boolean. + def assert(test) +# ^^^^^^ definition [..] MyTest#assert(). +# ^^^^ definition local 1~#2774883451 + test ? true : false + end + + # Helper method to direct calls to `test` instead of Kernel#test + sig { params(args: T.untyped, block: T.nilable(T.proc.void)).void } +# ^^^^ reference [..] `>`#void(). + def self.test(*args, &block) +# ^^^^ definition [..] ``#test(). + end + + setup do +# ^^^^^ definition [..] MyTest#initialize(). + @a = T.let(1, Integer) + end + + test "valid method call" do +# ^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#test_valid_method_call(). + end + + test "block is evaluated in the context of an instance" do +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] MyTest#test_block_is_evaluated_in_the_context_of_an_instance(). + assert true + end + end + + class NoMatchTest < ActiveSupport::TestCase +# ^^^^^^^^^^^ definition [..] NoMatchTest# +# ^^^^^^^^^^^^^ reference [..] ActiveSupport# +# ^^^^^^^^ definition [..] ActiveSupport#TestCase# + extend T::Sig + + sig { params(block: T.proc.void).void } +# ^^^^ reference [..] `>`#void(). + def self.setup(&block); end +# ^^^^^ definition [..] ``#setup(). + + sig { params(block: T.proc.void).void } +# ^^^^ reference [..] `>`#void(). + def self.teardown(&block); end +# ^^^^^^^^ definition [..] ``#teardown(). + end + + class NoParentClass +# ^^^^^^^^^^^^^ definition [..] NoParentClass# + extend T::Sig + + sig { params(block: T.proc.void).void } +# ^^^^ reference [..] `>`#void(). + def self.setup(&block); end +# ^^^^^ definition [..] ``#setup(). + + sig { params(block: T.proc.void).void } +# ^^^^ reference [..] `>`#void(). + def self.teardown(&block); end +# ^^^^^^^^ definition [..] ``#teardown(). + + sig { params(a: T.untyped, b: T.untyped).void } + def assert_equal(a, b); end +# ^^^^^^^^^^^^ definition [..] NoParentClass#assert_equal(). + + setup do +# ^^^^^ definition [..] NoParentClass#initialize(). + @a = T.let(1, Integer) + end + + test "it works" do +# ^^^^^^^^^^ definition [..] NoParentClass#test_it_works(). + assert_equal 1, @a + end + + teardown do +# ^^^^^^^^ definition [..] NoParentClass#teardown(). + @a = 5 + end + end diff --git a/test/scip/testdata/type_change.snapshot.rb b/test/scip/testdata/type_change.snapshot.rb index b446852ed2..490bf10cfc 100644 --- a/test/scip/testdata/type_change.snapshot.rb +++ b/test/scip/testdata/type_change.snapshot.rb @@ -2,12 +2,12 @@ # options: showDocs def assign_different_branches(b) -#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] Object#assign_different_branches(). -#documentation -#| ```ruby -#| sig {params(b: T.untyped).returns(T.untyped)} -#| def assign_different_branches(b) -#| ``` +# ^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] Object#assign_different_branches(). +# documentation +# | ```ruby +# | sig {params(b: T.untyped).returns(T.untyped)} +# | def assign_different_branches(b) +# | ``` # ^ definition local 1~#3317016627 # documentation # | ```ruby @@ -32,12 +32,12 @@ def assign_different_branches(b) end def change_different_branches(b) -#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] Object#change_different_branches(). -#documentation -#| ```ruby -#| sig {params(b: T.untyped).returns(T.untyped)} -#| def change_different_branches(b) -#| ``` +# ^^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] Object#change_different_branches(). +# documentation +# | ```ruby +# | sig {params(b: T.untyped).returns(T.untyped)} +# | def change_different_branches(b) +# | ``` # ^ definition local 1~#2122680152 # documentation # | ```ruby @@ -68,12 +68,12 @@ def change_different_branches(b) end def loop_type_change(bs) -#^^^^^^^^^^^^^^^^^^^^^^^^ definition [..] Object#loop_type_change(). -#documentation -#| ```ruby -#| sig {params(bs: T.untyped).returns(T.untyped)} -#| def loop_type_change(bs) -#| ``` +# ^^^^^^^^^^^^^^^^ definition [..] Object#loop_type_change(). +# documentation +# | ```ruby +# | sig {params(bs: T.untyped).returns(T.untyped)} +# | def loop_type_change(bs) +# | ``` # ^^ definition local 1~#4057334513 # documentation # | ```ruby @@ -137,12 +137,12 @@ class C # | ``` def change_type(b) -# ^^^^^^^^^^^^^^^^^^ definition [..] C#change_type(). -# documentation -# | ```ruby -# | sig {params(b: T.untyped).returns(T.untyped)} -# | def change_type(b) -# | ``` +# ^^^^^^^^^^^ definition [..] C#change_type(). +# documentation +# | ```ruby +# | sig {params(b: T.untyped).returns(T.untyped)} +# | def change_type(b) +# | ``` # ^ definition local 1~#2066187318 # documentation # | ```ruby @@ -230,12 +230,12 @@ class D < C # | class C # | ``` def change_type(b) -# ^^^^^^^^^^^^^^^^^^ definition [..] D#change_type(). -# documentation -# | ```ruby -# | sig {params(b: T.untyped).returns(T.untyped)} -# | def change_type(b) -# | ``` +# ^^^^^^^^^^^ definition [..] D#change_type(). +# documentation +# | ```ruby +# | sig {params(b: T.untyped).returns(T.untyped)} +# | def change_type(b) +# | ``` # ^ definition local 1~#2066187318 # documentation # | ```ruby diff --git a/test/scip/testdata/type_docs.snapshot.rb b/test/scip/testdata/type_docs.snapshot.rb index 0062e2e8bf..3d88235724 100644 --- a/test/scip/testdata/type_docs.snapshot.rb +++ b/test/scip/testdata/type_docs.snapshot.rb @@ -8,22 +8,18 @@ module M # | module M # | ``` extent T::Sig -# ^ reference [..] T# -# ^^^ reference [..] T#Sig# sig { params(x: Integer, y: String).returns(String) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reference [..] Sorbet#Private#Static# # ^^^^^^^ reference [..] Integer# # ^^^^^^ reference [..] String# # ^^^^^^ reference [..] String# def js_add(x, y) -# ^^^^^^^^^^^^^^^^ definition [..] M#js_add(). -# documentation -# | ```ruby -# | sig {params(x: Integer, y: String).returns(String)} -# | def js_add(x, y) -# | ``` +# ^^^^^^ definition [..] M#js_add(). +# documentation +# | ```ruby +# | sig {params(x: Integer, y: String).returns(String)} +# | def js_add(x, y) +# | ``` # ^ definition local 1~#1239553962 # documentation # | ```ruby diff --git a/test/scip/testdata/types.snapshot.rb b/test/scip/testdata/types.snapshot.rb deleted file mode 100644 index ce065a8358..0000000000 --- a/test/scip/testdata/types.snapshot.rb +++ /dev/null @@ -1,26 +0,0 @@ - # typed: true - - def f() -#^^^^^^^ definition [..] Object#f(). - T.let(true, T::Boolean) -# ^ reference [..] T# -# ^^^^^^^ reference [..] T#Boolean. - end - - module M -# ^ definition [..] M# - module_function - sig { returns(T::Boolean) } -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^^^ reference [..] Sorbet#Private#``#sig(). -# ^ reference [..] T# -# ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^ reference [..] T#Boolean. -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# -# ^^^^^^^^^^ reference [..] Sorbet#Private#Static# - def b -# ^^^^^ definition [..] M#b(). -# ^^^^^ definition [..] ``#b(). - true - end - end