Lines 1459-1466
Link Here
|
1459 |
boolean isEmptyNameCompletion = false; |
1459 |
boolean isEmptyNameCompletion = false; |
1460 |
boolean isEmptyAssistIdentifier = false; |
1460 |
boolean isEmptyAssistIdentifier = false; |
1461 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR_QUALIFIER |
1461 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR_QUALIFIER |
1462 |
&& ((isEmptyNameCompletion = topExpression == this.assistNode && isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]" |
1462 |
&& ((isEmptyNameCompletion = topExpression == this.assistNode && isEmptyNameCompletion()) // e.g. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]" |
1463 |
|| (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]" |
1463 |
|| (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // e.g. it is something like "this.fred(1 [cursor]" |
1464 |
|
1464 |
|
1465 |
// pop empty name completion |
1465 |
// pop empty name completion |
1466 |
if (isEmptyNameCompletion) { |
1466 |
if (isEmptyNameCompletion) { |
Lines 1654-1660
Link Here
|
1654 |
/* |
1654 |
/* |
1655 |
We didn't find any other completion, but the completion identifier is on the identifier stack, |
1655 |
We didn't find any other completion, but the completion identifier is on the identifier stack, |
1656 |
so it can only be a completion on name. |
1656 |
so it can only be a completion on name. |
1657 |
Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would |
1657 |
Note that we allow the completion on a name even if nothing is expected (e.g. foo() b[cursor] would |
1658 |
be a completion on 'b'). This policy gives more to the user than he/she would expect, but this |
1658 |
be a completion on 'b'). This policy gives more to the user than he/she would expect, but this |
1659 |
simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity |
1659 |
simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity |
1660 |
instead of at the 'expression' granularity as it does right now. |
1660 |
instead of at the 'expression' granularity as it does right now. |
Lines 1977-1983
Link Here
|
1977 |
if (checkClassLiteralAccess()) return; |
1977 |
if (checkClassLiteralAccess()) return; |
1978 |
if (checkInstanceofKeyword()) return; |
1978 |
if (checkInstanceofKeyword()) return; |
1979 |
|
1979 |
|
1980 |
// if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor]) |
1980 |
// if the completion was not on an empty name, it can still be inside an invocation (e.g. this.fred("abc"[cursor]) |
1981 |
// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack) |
1981 |
// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack) |
1982 |
if (checkInvocation()) return; |
1982 |
if (checkInvocation()) return; |
1983 |
|
1983 |
|
Lines 3262-3276
Link Here
|
3262 |
switch (token) { |
3262 |
switch (token) { |
3263 |
case TokenNameDOT: |
3263 |
case TokenNameDOT: |
3264 |
switch (previous) { |
3264 |
switch (previous) { |
3265 |
case TokenNamethis: // eg. this[.]fred() |
3265 |
case TokenNamethis: // e.g. this[.]fred() |
3266 |
this.invocationType = EXPLICIT_RECEIVER; |
3266 |
this.invocationType = EXPLICIT_RECEIVER; |
3267 |
break; |
3267 |
break; |
3268 |
case TokenNamesuper: // eg. super[.]fred() |
3268 |
case TokenNamesuper: // e.g. super[.]fred() |
3269 |
this.invocationType = SUPER_RECEIVER; |
3269 |
this.invocationType = SUPER_RECEIVER; |
3270 |
break; |
3270 |
break; |
3271 |
case TokenNameIdentifier: // eg. bar[.]fred() |
3271 |
case TokenNameIdentifier: // e.g. bar[.]fred() |
3272 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_BETWEEN_NEW_AND_LEFT_BRACKET) { |
3272 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_BETWEEN_NEW_AND_LEFT_BRACKET) { |
3273 |
if (this.identifierPtr != prevIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred() |
3273 |
if (this.identifierPtr != prevIdentifierPtr) { // if identifier has been consumed, e.g. this.x[.]fred() |
3274 |
this.invocationType = EXPLICIT_RECEIVER; |
3274 |
this.invocationType = EXPLICIT_RECEIVER; |
3275 |
} else { |
3275 |
} else { |
3276 |
this.invocationType = NAME_RECEIVER; |
3276 |
this.invocationType = NAME_RECEIVER; |
Lines 3280-3300
Link Here
|
3280 |
} |
3280 |
} |
3281 |
break; |
3281 |
break; |
3282 |
case TokenNameIdentifier: |
3282 |
case TokenNameIdentifier: |
3283 |
if (previous == TokenNameDOT) { // eg. foo().[fred]() |
3283 |
if (previous == TokenNameDOT) { // e.g. foo().[fred]() |
3284 |
if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]() |
3284 |
if (this.invocationType != SUPER_RECEIVER // e.g. not super.[fred]() |
3285 |
&& this.invocationType != NAME_RECEIVER // eg. not bar.[fred]() |
3285 |
&& this.invocationType != NAME_RECEIVER // e.g. not bar.[fred]() |
3286 |
&& this.invocationType != ALLOCATION // eg. not new foo.[Bar]() |
3286 |
&& this.invocationType != ALLOCATION // e.g. not new foo.[Bar]() |
3287 |
&& this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]() |
3287 |
&& this.invocationType != QUALIFIED_ALLOCATION) { // e.g. not fred().new foo.[Bar]() |
3288 |
|
3288 |
|
3289 |
this.invocationType = EXPLICIT_RECEIVER; |
3289 |
this.invocationType = EXPLICIT_RECEIVER; |
3290 |
this.qualifier = this.expressionPtr; |
3290 |
this.qualifier = this.expressionPtr; |
3291 |
} |
3291 |
} |
3292 |
} |
3292 |
} |
3293 |
if (previous == TokenNameGREATER) { // eg. foo().<X>[fred]() |
3293 |
if (previous == TokenNameGREATER) { // e.g. foo().<X>[fred]() |
3294 |
if (this.invocationType != SUPER_RECEIVER // eg. not super.<X>[fred]() |
3294 |
if (this.invocationType != SUPER_RECEIVER // e.g. not super.<X>[fred]() |
3295 |
&& this.invocationType != NAME_RECEIVER // eg. not bar.<X>[fred]() |
3295 |
&& this.invocationType != NAME_RECEIVER // e.g. not bar.<X>[fred]() |
3296 |
&& this.invocationType != ALLOCATION // eg. not new foo.<X>[Bar]() |
3296 |
&& this.invocationType != ALLOCATION // e.g. not new foo.<X>[Bar]() |
3297 |
&& this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.<X>[Bar]() |
3297 |
&& this.invocationType != QUALIFIED_ALLOCATION) { // e.g. not fred().new foo.<X>[Bar]() |
3298 |
|
3298 |
|
3299 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_METHOD_INVOCATION) { |
3299 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_METHOD_INVOCATION) { |
3300 |
this.invocationType = EXPLICIT_RECEIVER; |
3300 |
this.invocationType = EXPLICIT_RECEIVER; |
Lines 3306-3325
Link Here
|
3306 |
case TokenNamenew: |
3306 |
case TokenNamenew: |
3307 |
pushOnElementStack(K_BETWEEN_NEW_AND_LEFT_BRACKET); |
3307 |
pushOnElementStack(K_BETWEEN_NEW_AND_LEFT_BRACKET); |
3308 |
this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed |
3308 |
this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed |
3309 |
if (previous == TokenNameDOT) { // eg. fred().[new] X() |
3309 |
if (previous == TokenNameDOT) { // e.g. fred().[new] X() |
3310 |
this.invocationType = QUALIFIED_ALLOCATION; |
3310 |
this.invocationType = QUALIFIED_ALLOCATION; |
3311 |
} else { // eg. [new] X() |
3311 |
} else { // e.g. [new] X() |
3312 |
this.invocationType = ALLOCATION; |
3312 |
this.invocationType = ALLOCATION; |
3313 |
} |
3313 |
} |
3314 |
break; |
3314 |
break; |
3315 |
case TokenNamethis: |
3315 |
case TokenNamethis: |
3316 |
if (previous == TokenNameDOT) { // eg. fred().[this]() |
3316 |
if (previous == TokenNameDOT) { // e.g. fred().[this]() |
3317 |
this.invocationType = QUALIFIED_ALLOCATION; |
3317 |
this.invocationType = QUALIFIED_ALLOCATION; |
3318 |
this.qualifier = this.expressionPtr; |
3318 |
this.qualifier = this.expressionPtr; |
3319 |
} |
3319 |
} |
3320 |
break; |
3320 |
break; |
3321 |
case TokenNamesuper: |
3321 |
case TokenNamesuper: |
3322 |
if (previous == TokenNameDOT) { // eg. fred().[super]() |
3322 |
if (previous == TokenNameDOT) { // e.g. fred().[super]() |
3323 |
this.invocationType = QUALIFIED_ALLOCATION; |
3323 |
this.invocationType = QUALIFIED_ALLOCATION; |
3324 |
this.qualifier = this.expressionPtr; |
3324 |
this.qualifier = this.expressionPtr; |
3325 |
} |
3325 |
} |
Lines 3332-3338
Link Here
|
3332 |
this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed |
3332 |
this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed |
3333 |
} |
3333 |
} |
3334 |
switch (previous) { |
3334 |
switch (previous) { |
3335 |
case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(]) |
3335 |
case TokenNameIdentifier: // e.g. fred[(]) or foo.fred[(]) |
3336 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
3336 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
3337 |
int info = 0; |
3337 |
int info = 0; |
3338 |
if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER,1) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN && |
3338 |
if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER,1) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN && |
Lines 3352-3358
Link Here
|
3352 |
this.qualifier = -1; |
3352 |
this.qualifier = -1; |
3353 |
this.invocationType = NO_RECEIVER; |
3353 |
this.invocationType = NO_RECEIVER; |
3354 |
break; |
3354 |
break; |
3355 |
case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2) |
3355 |
case TokenNamethis: // explicit constructor invocation, e.g. this[(]1, 2) |
3356 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
3356 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
3357 |
this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION); |
3357 |
this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION); |
3358 |
this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier); |
3358 |
this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier); |
Lines 3360-3366
Link Here
|
3360 |
this.qualifier = -1; |
3360 |
this.qualifier = -1; |
3361 |
this.invocationType = NO_RECEIVER; |
3361 |
this.invocationType = NO_RECEIVER; |
3362 |
break; |
3362 |
break; |
3363 |
case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2) |
3363 |
case TokenNamesuper: // explicit constructor invocation, e.g. super[(]1, 2) |
3364 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
3364 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
3365 |
this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION); |
3365 |
this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION); |
3366 |
this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier); |
3366 |
this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier); |
Lines 3368-3374
Link Here
|
3368 |
this.qualifier = -1; |
3368 |
this.qualifier = -1; |
3369 |
this.invocationType = NO_RECEIVER; |
3369 |
this.invocationType = NO_RECEIVER; |
3370 |
break; |
3370 |
break; |
3371 |
case TokenNameGREATER: // explicit constructor invocation, eg. Fred<X>[(]1, 2) |
3371 |
case TokenNameGREATER: // explicit constructor invocation, e.g. Fred<X>[(]1, 2) |
3372 |
case TokenNameRIGHT_SHIFT: // or fred<X<X>>[(]1, 2) |
3372 |
case TokenNameRIGHT_SHIFT: // or fred<X<X>>[(]1, 2) |
3373 |
case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred<X<X<X>>>[(]1, 2) |
3373 |
case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred<X<X<X>>>[(]1, 2) |
3374 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
3374 |
if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) { |
Lines 4359-4365
Link Here
|
4359 |
} |
4359 |
} |
4360 |
/** |
4360 |
/** |
4361 |
* Returns whether the completion is just after an array type |
4361 |
* Returns whether the completion is just after an array type |
4362 |
* eg. String[].[cursor] |
4362 |
* e.g. String[].[cursor] |
4363 |
*/ |
4363 |
*/ |
4364 |
private boolean isAfterArrayType() { |
4364 |
private boolean isAfterArrayType() { |
4365 |
// TBD: The following relies on the fact that array dimensions are small: it says that if the |
4365 |
// TBD: The following relies on the fact that array dimensions are small: it says that if the |