Skip to content

Commit e9b7024

Browse files
committed
Reject p(p a, &block => value) and similar
They were being parsed as `p((p a, &block) => value)`. When we get to this point, we must not just have parsed a command call, always consuming the `=>` is not correct. Closes [Bug #21622]
1 parent a156df0 commit e9b7024

File tree

4 files changed

+300
-40
lines changed

4 files changed

+300
-40
lines changed

snapshots/command_method_call.txt

Lines changed: 233 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
@ ProgramNode (location: (1,0)-(41,10))
1+
@ ProgramNode (location: (1,0)-(47,27))
22
├── flags: ∅
33
├── locals: [:foo, :bar]
44
└── statements:
5-
@ StatementsNode (location: (1,0)-(41,10))
5+
@ StatementsNode (location: (1,0)-(47,27))
66
├── flags: ∅
7-
└── body: (length: 21)
7+
└── body: (length: 24)
88
├── @ CallNode (location: (1,0)-(1,5))
99
│ ├── flags: newline, ignore_visibility
1010
│ ├── receiver: ∅
@@ -779,42 +779,236 @@
779779
│ │ ├── equal_loc: ∅
780780
│ │ └── block: ∅
781781
│ └── operator_loc: (39,7)-(39,9) = "or"
782-
└── @ CallNode (location: (41,0)-(41,10))
783-
├── flags: newline
784-
├── receiver:
785-
│ @ CallNode (location: (41,4)-(41,10))
786-
│ ├── flags: ∅
787-
│ ├── receiver:
788-
│ │ @ CallNode (location: (41,5)-(41,10))
789-
│ │ ├── flags: ignore_visibility
790-
│ │ ├── receiver: ∅
791-
│ │ ├── call_operator_loc: ∅
792-
│ │ ├── name: :foo
793-
│ │ ├── message_loc: (41,5)-(41,8) = "foo"
794-
│ │ ├── opening_loc: ∅
795-
│ │ ├── arguments:
796-
│ │ │ @ ArgumentsNode (location: (41,9)-(41,10))
797-
│ │ │ ├── flags: ∅
798-
│ │ │ └── arguments: (length: 1)
799-
│ │ │ └── @ IntegerNode (location: (41,9)-(41,10))
800-
│ │ │ ├── flags: static_literal, decimal
801-
│ │ │ └── value: 1
802-
│ │ ├── closing_loc: ∅
803-
│ │ ├── equal_loc: ∅
804-
│ │ └── block: ∅
805-
│ ├── call_operator_loc: ∅
806-
│ ├── name: :!
807-
│ ├── message_loc: (41,4)-(41,5) = "!"
808-
│ ├── opening_loc: ∅
809-
│ ├── arguments: ∅
810-
│ ├── closing_loc: ∅
811-
│ ├── equal_loc: ∅
812-
│ └── block: ∅
782+
├── @ CallNode (location: (41,0)-(41,10))
783+
│ ├── flags: newline
784+
│ ├── receiver:
785+
│ │ @ CallNode (location: (41,4)-(41,10))
786+
│ │ ├── flags: ∅
787+
│ │ ├── receiver:
788+
│ │ │ @ CallNode (location: (41,5)-(41,10))
789+
│ │ │ ├── flags: ignore_visibility
790+
│ │ │ ├── receiver: ∅
791+
│ │ │ ├── call_operator_loc: ∅
792+
│ │ │ ├── name: :foo
793+
│ │ │ ├── message_loc: (41,5)-(41,8) = "foo"
794+
│ │ │ ├── opening_loc: ∅
795+
│ │ │ ├── arguments:
796+
│ │ │ │ @ ArgumentsNode (location: (41,9)-(41,10))
797+
│ │ │ │ ├── flags: ∅
798+
│ │ │ │ └── arguments: (length: 1)
799+
│ │ │ │ └── @ IntegerNode (location: (41,9)-(41,10))
800+
│ │ │ │ ├── flags: static_literal, decimal
801+
│ │ │ │ └── value: 1
802+
│ │ │ ├── closing_loc: ∅
803+
│ │ │ ├── equal_loc: ∅
804+
│ │ │ └── block: ∅
805+
│ │ ├── call_operator_loc: ∅
806+
│ │ ├── name: :!
807+
│ │ ├── message_loc: (41,4)-(41,5) = "!"
808+
│ │ ├── opening_loc: ∅
809+
│ │ ├── arguments: ∅
810+
│ │ ├── closing_loc: ∅
811+
│ │ ├── equal_loc: ∅
812+
│ │ └── block: ∅
813+
│ ├── call_operator_loc: ∅
814+
│ ├── name: :!
815+
│ ├── message_loc: (41,0)-(41,3) = "not"
816+
│ ├── opening_loc: ∅
817+
│ ├── arguments: ∅
818+
│ ├── closing_loc: ∅
819+
│ ├── equal_loc: ∅
820+
│ └── block: ∅
821+
├── @ CallNode (location: (43,0)-(43,26))
822+
│ ├── flags: newline, ignore_visibility
823+
│ ├── receiver: ∅
824+
│ ├── call_operator_loc: ∅
825+
│ ├── name: :foo
826+
│ ├── message_loc: (43,0)-(43,3) = "foo"
827+
│ ├── opening_loc: (43,3)-(43,4) = "("
828+
│ ├── arguments:
829+
│ │ @ ArgumentsNode (location: (43,4)-(43,25))
830+
│ │ ├── flags: ∅
831+
│ │ └── arguments: (length: 1)
832+
│ │ └── @ CallNode (location: (43,4)-(43,25))
833+
│ │ ├── flags: ignore_visibility
834+
│ │ ├── receiver: ∅
835+
│ │ ├── call_operator_loc: ∅
836+
│ │ ├── name: :bar
837+
│ │ ├── message_loc: (43,4)-(43,7) = "bar"
838+
│ │ ├── opening_loc: ∅
839+
│ │ ├── arguments:
840+
│ │ │ @ ArgumentsNode (location: (43,8)-(43,25))
841+
│ │ │ ├── flags: contains_keywords
842+
│ │ │ └── arguments: (length: 2)
843+
│ │ │ ├── @ CallNode (location: (43,8)-(43,11))
844+
│ │ │ │ ├── flags: variable_call, ignore_visibility
845+
│ │ │ │ ├── receiver: ∅
846+
│ │ │ │ ├── call_operator_loc: ∅
847+
│ │ │ │ ├── name: :baz
848+
│ │ │ │ ├── message_loc: (43,8)-(43,11) = "baz"
849+
│ │ │ │ ├── opening_loc: ∅
850+
│ │ │ │ ├── arguments: ∅
851+
│ │ │ │ ├── closing_loc: ∅
852+
│ │ │ │ ├── equal_loc: ∅
853+
│ │ │ │ └── block: ∅
854+
│ │ │ └── @ KeywordHashNode (location: (43,13)-(43,25))
855+
│ │ │ ├── flags: ∅
856+
│ │ │ └── elements: (length: 1)
857+
│ │ │ └── @ AssocNode (location: (43,13)-(43,25))
858+
│ │ │ ├── flags: ∅
859+
│ │ │ ├── key:
860+
│ │ │ │ @ CallNode (location: (43,13)-(43,16))
861+
│ │ │ │ ├── flags: variable_call, ignore_visibility
862+
│ │ │ │ ├── receiver: ∅
863+
│ │ │ │ ├── call_operator_loc: ∅
864+
│ │ │ │ ├── name: :key
865+
│ │ │ │ ├── message_loc: (43,13)-(43,16) = "key"
866+
│ │ │ │ ├── opening_loc: ∅
867+
│ │ │ │ ├── arguments: ∅
868+
│ │ │ │ ├── closing_loc: ∅
869+
│ │ │ │ ├── equal_loc: ∅
870+
│ │ │ │ └── block: ∅
871+
│ │ │ ├── value:
872+
│ │ │ │ @ CallNode (location: (43,20)-(43,25))
873+
│ │ │ │ ├── flags: variable_call, ignore_visibility
874+
│ │ │ │ ├── receiver: ∅
875+
│ │ │ │ ├── call_operator_loc: ∅
876+
│ │ │ │ ├── name: :value
877+
│ │ │ │ ├── message_loc: (43,20)-(43,25) = "value"
878+
│ │ │ │ ├── opening_loc: ∅
879+
│ │ │ │ ├── arguments: ∅
880+
│ │ │ │ ├── closing_loc: ∅
881+
│ │ │ │ ├── equal_loc: ∅
882+
│ │ │ │ └── block: ∅
883+
│ │ │ └── operator_loc: (43,17)-(43,19) = "=>"
884+
│ │ ├── closing_loc: ∅
885+
│ │ ├── equal_loc: ∅
886+
│ │ └── block: ∅
887+
│ ├── closing_loc: (43,25)-(43,26) = ")"
888+
│ ├── equal_loc: ∅
889+
│ └── block: ∅
890+
├── @ CallNode (location: (45,0)-(45,26))
891+
│ ├── flags: newline, ignore_visibility
892+
│ ├── receiver: ∅
893+
│ ├── call_operator_loc: ∅
894+
│ ├── name: :foo
895+
│ ├── message_loc: (45,0)-(45,3) = "foo"
896+
│ ├── opening_loc: (45,3)-(45,4) = "("
897+
│ ├── arguments:
898+
│ │ @ ArgumentsNode (location: (45,4)-(45,25))
899+
│ │ ├── flags: ∅
900+
│ │ └── arguments: (length: 1)
901+
│ │ └── @ CallNode (location: (45,4)-(45,25))
902+
│ │ ├── flags: ignore_visibility
903+
│ │ ├── receiver: ∅
904+
│ │ ├── call_operator_loc: ∅
905+
│ │ ├── name: :bar
906+
│ │ ├── message_loc: (45,4)-(45,7) = "bar"
907+
│ │ ├── opening_loc: ∅
908+
│ │ ├── arguments:
909+
│ │ │ @ ArgumentsNode (location: (45,8)-(45,25))
910+
│ │ │ ├── flags: contains_keywords
911+
│ │ │ └── arguments: (length: 2)
912+
│ │ │ ├── @ CallNode (location: (45,8)-(45,11))
913+
│ │ │ │ ├── flags: variable_call, ignore_visibility
914+
│ │ │ │ ├── receiver: ∅
915+
│ │ │ │ ├── call_operator_loc: ∅
916+
│ │ │ │ ├── name: :baz
917+
│ │ │ │ ├── message_loc: (45,8)-(45,11) = "baz"
918+
│ │ │ │ ├── opening_loc: ∅
919+
│ │ │ │ ├── arguments: ∅
920+
│ │ │ │ ├── closing_loc: ∅
921+
│ │ │ │ ├── equal_loc: ∅
922+
│ │ │ │ └── block: ∅
923+
│ │ │ └── @ KeywordHashNode (location: (45,13)-(45,25))
924+
│ │ │ ├── flags: ∅
925+
│ │ │ └── elements: (length: 1)
926+
│ │ │ └── @ AssocNode (location: (45,13)-(45,25))
927+
│ │ │ ├── flags: ∅
928+
│ │ │ ├── key:
929+
│ │ │ │ @ ConstantReadNode (location: (45,13)-(45,16))
930+
│ │ │ │ ├── flags: ∅
931+
│ │ │ │ └── name: :KEY
932+
│ │ │ ├── value:
933+
│ │ │ │ @ CallNode (location: (45,20)-(45,25))
934+
│ │ │ │ ├── flags: variable_call, ignore_visibility
935+
│ │ │ │ ├── receiver: ∅
936+
│ │ │ │ ├── call_operator_loc: ∅
937+
│ │ │ │ ├── name: :value
938+
│ │ │ │ ├── message_loc: (45,20)-(45,25) = "value"
939+
│ │ │ │ ├── opening_loc: ∅
940+
│ │ │ │ ├── arguments: ∅
941+
│ │ │ │ ├── closing_loc: ∅
942+
│ │ │ │ ├── equal_loc: ∅
943+
│ │ │ │ └── block: ∅
944+
│ │ │ └── operator_loc: (45,17)-(45,19) = "=>"
945+
│ │ ├── closing_loc: ∅
946+
│ │ ├── equal_loc: ∅
947+
│ │ └── block: ∅
948+
│ ├── closing_loc: (45,25)-(45,26) = ")"
949+
│ ├── equal_loc: ∅
950+
│ └── block: ∅
951+
└── @ CallNode (location: (47,0)-(47,27))
952+
├── flags: newline, ignore_visibility
953+
├── receiver: ∅
813954
├── call_operator_loc: ∅
814-
├── name: :!
815-
├── message_loc: (41,0)-(41,3) = "not"
816-
├── opening_loc: ∅
817-
├── arguments: ∅
818-
├── closing_loc: ∅
955+
├── name: :foo
956+
├── message_loc: (47,0)-(47,3) = "foo"
957+
├── opening_loc: (47,3)-(47,4) = "("
958+
├── arguments:
959+
│ @ ArgumentsNode (location: (47,4)-(47,26))
960+
│ ├── flags: ∅
961+
│ └── arguments: (length: 1)
962+
│ └── @ CallNode (location: (47,4)-(47,26))
963+
│ ├── flags: ignore_visibility
964+
│ ├── receiver: ∅
965+
│ ├── call_operator_loc: ∅
966+
│ ├── name: :bar
967+
│ ├── message_loc: (47,4)-(47,7) = "bar"
968+
│ ├── opening_loc: ∅
969+
│ ├── arguments:
970+
│ │ @ ArgumentsNode (location: (47,8)-(47,26))
971+
│ │ ├── flags: contains_keywords
972+
│ │ └── arguments: (length: 2)
973+
│ │ ├── @ CallNode (location: (47,8)-(47,11))
974+
│ │ │ ├── flags: variable_call, ignore_visibility
975+
│ │ │ ├── receiver: ∅
976+
│ │ │ ├── call_operator_loc: ∅
977+
│ │ │ ├── name: :baz
978+
│ │ │ ├── message_loc: (47,8)-(47,11) = "baz"
979+
│ │ │ ├── opening_loc: ∅
980+
│ │ │ ├── arguments: ∅
981+
│ │ │ ├── closing_loc: ∅
982+
│ │ │ ├── equal_loc: ∅
983+
│ │ │ └── block: ∅
984+
│ │ └── @ KeywordHashNode (location: (47,13)-(47,26))
985+
│ │ ├── flags: symbol_keys
986+
│ │ └── elements: (length: 1)
987+
│ │ └── @ AssocNode (location: (47,13)-(47,26))
988+
│ │ ├── flags: ∅
989+
│ │ ├── key:
990+
│ │ │ @ SymbolNode (location: (47,13)-(47,17))
991+
│ │ │ ├── flags: static_literal, forced_us_ascii_encoding
992+
│ │ │ ├── opening_loc: (47,13)-(47,14) = ":"
993+
│ │ │ ├── value_loc: (47,14)-(47,17) = "key"
994+
│ │ │ ├── closing_loc: ∅
995+
│ │ │ └── unescaped: "key"
996+
│ │ ├── value:
997+
│ │ │ @ CallNode (location: (47,21)-(47,26))
998+
│ │ │ ├── flags: variable_call, ignore_visibility
999+
│ │ │ ├── receiver: ∅
1000+
│ │ │ ├── call_operator_loc: ∅
1001+
│ │ │ ├── name: :value
1002+
│ │ │ ├── message_loc: (47,21)-(47,26) = "value"
1003+
│ │ │ ├── opening_loc: ∅
1004+
│ │ │ ├── arguments: ∅
1005+
│ │ │ ├── closing_loc: ∅
1006+
│ │ │ ├── equal_loc: ∅
1007+
│ │ │ └── block: ∅
1008+
│ │ └── operator_loc: (47,18)-(47,20) = "=>"
1009+
│ ├── closing_loc: ∅
1010+
│ ├── equal_loc: ∅
1011+
│ └── block: ∅
1012+
├── closing_loc: (47,26)-(47,27) = ")"
8191013
├── equal_loc: ∅
8201014
└── block: ∅

src/prism.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14230,6 +14230,25 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
1423014230
return contains_keyword_splat;
1423114231
}
1423214232

14233+
static inline bool
14234+
argument_allowed_for_bare_hash(pm_parser_t *parser, pm_node_t *argument) {
14235+
if (pm_symbol_node_label_p(argument)) {
14236+
return true;
14237+
}
14238+
14239+
switch (PM_NODE_TYPE(argument)) {
14240+
case PM_CALL_NODE: {
14241+
pm_call_node_t *cast = (pm_call_node_t *) argument;
14242+
if (cast->opening_loc.start == NULL && cast->arguments != NULL) {
14243+
return false;
14244+
}
14245+
break;
14246+
}
14247+
default: break;
14248+
}
14249+
return accept1(parser, PM_TOKEN_EQUAL_GREATER);
14250+
}
14251+
1423314252
/**
1423414253
* Append an argument to a list of arguments.
1423514254
*/
@@ -14387,7 +14406,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
1438714406
bool contains_keywords = false;
1438814407
bool contains_keyword_splat = false;
1438914408

14390-
if (pm_symbol_node_label_p(argument) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) {
14409+
if (argument_allowed_for_bare_hash(parser, argument)){
1439114410
if (parsed_bare_hash) {
1439214411
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_BARE_HASH);
1439314412
}

0 commit comments

Comments
 (0)