Handles any construct following a "." or ".." operator. @param pn the left-hand side (target) of the operator. Never null. @param isOptionalChain whether we are inside an optional chain, i.e. whether a preceding property access was done via the ?. operator @return a PropertyGet, XmlMemb
(int tt, AstNode pn, boolean isOptionalChain)
| 3262 | * @return a PropertyGet, XmlMemberGet, or ErrorNode |
| 3263 | */ |
| 3264 | private AstNode propertyAccess(int tt, AstNode pn, boolean isOptionalChain) throws IOException { |
| 3265 | if (pn == null) codeBug(); |
| 3266 | if (pn.getType() == Token.SUPER && isOptionalChain) { |
| 3267 | reportError("msg.optional.super"); |
| 3268 | return makeErrorNode(); |
| 3269 | } |
| 3270 | |
| 3271 | int memberTypeFlags = 0, |
| 3272 | lineno = lineNumber(), |
| 3273 | dotPos = ts.tokenBeg, |
| 3274 | column = columnNumber(); |
| 3275 | consumeToken(); |
| 3276 | |
| 3277 | if (tt == Token.DOTDOT) { |
| 3278 | mustHaveXML(); |
| 3279 | memberTypeFlags = Node.DESCENDANTS_FLAG; |
| 3280 | } |
| 3281 | |
| 3282 | AstNode ref = null; // right side of . or .. operator |
| 3283 | int token = nextToken(); |
| 3284 | switch (token) { |
| 3285 | case Token.THROW: |
| 3286 | // needed for generator.throw(); |
| 3287 | saveNameTokenData(ts.tokenBeg, "throw", lineNumber(), columnNumber()); |
| 3288 | ref = propertyName(-1, memberTypeFlags); |
| 3289 | break; |
| 3290 | |
| 3291 | case Token.NAME: |
| 3292 | // handles: name, ns::name, ns::*, ns::[expr] |
| 3293 | ref = propertyName(-1, memberTypeFlags); |
| 3294 | break; |
| 3295 | |
| 3296 | case Token.MUL: |
| 3297 | if (compilerEnv.isXmlAvailable()) { |
| 3298 | // handles: *, *::name, *::*, *::[expr] |
| 3299 | saveNameTokenData(ts.tokenBeg, "*", lineNumber(), columnNumber()); |
| 3300 | ref = propertyName(-1, memberTypeFlags); |
| 3301 | break; |
| 3302 | } else { |
| 3303 | reportError("msg.no.name.after.dot"); |
| 3304 | return makeErrorNode(); |
| 3305 | } |
| 3306 | |
| 3307 | case Token.XMLATTR: |
| 3308 | if (compilerEnv.isXmlAvailable()) { |
| 3309 | // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*', |
| 3310 | // '@::attr', '@::*', '@*', '@*::attr', '@*::*' |
| 3311 | ref = attributeAccess(); |
| 3312 | break; |
| 3313 | } else { |
| 3314 | reportError("msg.no.name.after.dot"); |
| 3315 | return makeErrorNode(); |
| 3316 | } |
| 3317 | |
| 3318 | case Token.RESERVED: |
| 3319 | { |
| 3320 | String name = ts.getString(); |
| 3321 | saveNameTokenData(ts.tokenBeg, name, lineNumber(), columnNumber()); |
no test coverage detected