| 1092 | } |
| 1093 | |
| 1094 | func TestParse_optional_chaining(t *testing.T) { |
| 1095 | parseTests := []struct { |
| 1096 | input string |
| 1097 | expected Node |
| 1098 | }{ |
| 1099 | { |
| 1100 | "foo?.bar.baz", |
| 1101 | &ChainNode{ |
| 1102 | Node: &MemberNode{ |
| 1103 | Node: &MemberNode{ |
| 1104 | Node: &IdentifierNode{Value: "foo"}, |
| 1105 | Property: &StringNode{Value: "bar"}, |
| 1106 | Optional: true, |
| 1107 | }, |
| 1108 | Property: &StringNode{Value: "baz"}, |
| 1109 | }, |
| 1110 | }, |
| 1111 | }, |
| 1112 | { |
| 1113 | "foo.bar?.baz", |
| 1114 | &ChainNode{ |
| 1115 | Node: &MemberNode{ |
| 1116 | Node: &MemberNode{ |
| 1117 | Node: &IdentifierNode{Value: "foo"}, |
| 1118 | Property: &StringNode{Value: "bar"}, |
| 1119 | }, |
| 1120 | Property: &StringNode{Value: "baz"}, |
| 1121 | Optional: true, |
| 1122 | }, |
| 1123 | }, |
| 1124 | }, |
| 1125 | { |
| 1126 | "foo?.bar?.baz", |
| 1127 | &ChainNode{ |
| 1128 | Node: &MemberNode{ |
| 1129 | Node: &MemberNode{ |
| 1130 | Node: &IdentifierNode{Value: "foo"}, |
| 1131 | Property: &StringNode{Value: "bar"}, |
| 1132 | Optional: true, |
| 1133 | }, |
| 1134 | Property: &StringNode{Value: "baz"}, |
| 1135 | Optional: true, |
| 1136 | }, |
| 1137 | }, |
| 1138 | }, |
| 1139 | { |
| 1140 | "!foo?.bar.baz", |
| 1141 | &UnaryNode{ |
| 1142 | Operator: "!", |
| 1143 | Node: &ChainNode{ |
| 1144 | Node: &MemberNode{ |
| 1145 | Node: &MemberNode{ |
| 1146 | Node: &IdentifierNode{Value: "foo"}, |
| 1147 | Property: &StringNode{Value: "bar"}, |
| 1148 | Optional: true, |
| 1149 | }, |
| 1150 | Property: &StringNode{Value: "baz"}, |
| 1151 | }, |