forked from sorbet/sorbet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDefDelegator.cc
72 lines (54 loc) · 2.42 KB
/
DefDelegator.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "rewriter/DefDelegator.h"
#include "ast/Helpers.h"
#include "core/GlobalState.h"
#include "rewriter/Util.h"
#include <optional>
using namespace std;
namespace sorbet::rewriter {
vector<ast::ExpressionPtr> DefDelegator::run(core::MutableContext ctx, const ast::Send *send) {
vector<ast::ExpressionPtr> methodStubs;
auto loc = send->loc;
if (send->fun != core::Names::defDelegator()) {
return methodStubs;
}
// This method takes 2..3 positional arguments and no keyword args:
// `def_delegator(accessor, method, ali = method)`
if (!(send->numPosArgs == 2 || send->numPosArgs == 3)) {
return methodStubs;
}
if (send->hasKwArgs()) {
return methodStubs;
}
auto *accessor = ast::cast_tree<ast::Literal>(send->args[0]);
if (!accessor || !(accessor->isSymbol(ctx) || accessor->isString(ctx))) {
return methodStubs;
}
auto *method = ast::cast_tree<ast::Literal>(send->args[1]);
if (!method || !method->isSymbol(ctx)) {
return methodStubs;
}
core::NameRef methodName = method->asSymbol(ctx);
if (send->numPosArgs == 3) {
auto *alias = ast::cast_tree<ast::Literal>(send->args[2]);
if (!alias || !alias->isSymbol(ctx)) {
return methodStubs;
}
methodName = alias->asSymbol(ctx);
}
// 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),
ast::MK::Symbol(loc, core::Names::blkArg()),
ast::MK::Nilable(loc, ast::MK::Constant(loc, core::Symbols::Proc())));
methodStubs.push_back(ast::MK::Sig(loc, std::move(sigArgs), ast::MK::Untyped(loc)));
// def $methodName(*arg0, &blk); end
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<ast::BlockArg>(loc, ast::MK::Local(loc, core::Names::blkArg())));
methodStubs.push_back(
ast::MK::SyntheticMethod(loc, loc, methodName, std::move(args), ast::MK::RaiseUnimplemented(loc)));
// 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`
methodStubs.push_back(send->deepCopy());
return methodStubs;
}
} // namespace sorbet::rewriter