@@ -52,8 +52,6 @@ class RenameRangeDetailCollector {
52
52
llvm::Optional<unsigned > FirstTrailingLabel,
53
53
LabelRangeType RangeType, bool isCallSite);
54
54
55
- bool isOperator () const { return Lexer::isOperator (Old.base ()); }
56
-
57
55
private:
58
56
// / Returns the range of the (possibly escaped) identifier at the start of
59
57
// / \p Range and updates \p IsEscaped to indicate whether it's escaped or not.
@@ -151,7 +149,7 @@ void RenameRangeDetailCollector::splitAndRenameLabel(CharSourceRange Range,
151
149
case LabelRangeType::NoncollapsibleParam:
152
150
return splitAndRenameParamLabel (Range, NameIndex,
153
151
/* IsCollapsible=*/ false );
154
- case LabelRangeType::Selector :
152
+ case LabelRangeType::CompoundName :
155
153
return addRenameRange (Range, RefactoringRangeKind::SelectorArgumentLabel,
156
154
NameIndex);
157
155
case LabelRangeType::None:
@@ -250,7 +248,7 @@ bool RenameRangeDetailCollector::labelRangeMatches(CharSourceRange Range,
250
248
LLVM_FALLTHROUGH;
251
249
case LabelRangeType::CallArg:
252
250
case LabelRangeType::Param:
253
- case LabelRangeType::Selector :
251
+ case LabelRangeType::CompoundName :
254
252
return ExistingLabel == (Expected.empty () ? " _" : Expected);
255
253
case LabelRangeType::None:
256
254
llvm_unreachable (" Unhandled label range type" );
@@ -277,12 +275,12 @@ bool RenameRangeDetailCollector::renameLabelsLenient(
277
275
if (OldNames.empty ())
278
276
return true ;
279
277
280
- while (!labelRangeMatches (Label, LabelRangeType::Selector ,
278
+ while (!labelRangeMatches (Label, LabelRangeType::CompoundName ,
281
279
OldNames.back ())) {
282
280
if ((OldNames = OldNames.drop_back ()).empty ())
283
281
return true ;
284
282
}
285
- splitAndRenameLabel (Label, LabelRangeType::Selector ,
283
+ splitAndRenameLabel (Label, LabelRangeType::CompoundName ,
286
284
OldNames.size () - 1 );
287
285
OldNames = OldNames.drop_back ();
288
286
continue ;
@@ -297,7 +295,7 @@ bool RenameRangeDetailCollector::renameLabelsLenient(
297
295
if ((OldNames = OldNames.drop_back ()).empty ())
298
296
return true ;
299
297
}
300
- splitAndRenameLabel (Label, LabelRangeType::Selector ,
298
+ splitAndRenameLabel (Label, LabelRangeType::CompoundName ,
301
299
OldNames.size () - 1 );
302
300
OldNames = OldNames.drop_back ();
303
301
continue ;
@@ -366,89 +364,153 @@ RegionType RenameRangeDetailCollector::getSyntacticRenameRegionType(
366
364
}
367
365
}
368
366
369
- RegionType RenameRangeDetailCollector::addSyntacticRenameRanges (
370
- const ResolvedLoc &Resolved, const RenameLoc &Config) {
367
+ enum class SpecialBaseName {
368
+ // / The function does not have one of the special base names.
369
+ None,
370
+ Subscript,
371
+ Init,
372
+ CallAsFunction
373
+ };
371
374
372
- if (!Resolved.range .isValid ())
373
- return RegionType::Unmatched;
375
+ static SpecialBaseName specialBaseNameFor (const DeclNameViewer &declName) {
376
+ if (!declName.isFunction ()) {
377
+ return SpecialBaseName::None;
378
+ }
379
+ if (declName.base () == " subscript" ) {
380
+ // FIXME: Don't handle as special name if it is backticked.
381
+ return SpecialBaseName::Subscript;
382
+ } else if (declName.base () == " init" ) {
383
+ // FIXME: Don't handle as special name if it is backticked.
384
+ return SpecialBaseName::Init;
385
+ } else if (declName.base () == " callAsFunction" ) {
386
+ // FIXME: this should only be treated specially for instance methods.
387
+ return SpecialBaseName::CallAsFunction;
388
+ } else {
389
+ return SpecialBaseName::None;
390
+ }
391
+ }
374
392
375
- auto RegionKind = getSyntacticRenameRegionType (Resolved);
376
- // Don't include unknown references coming from active code; if we don't
377
- // have a semantic NameUsage for them, then they're likely unrelated symbols
378
- // that happen to have the same name.
379
- if (RegionKind == RegionType::ActiveCode &&
380
- Config.Usage == NameUsage::Unknown)
381
- return RegionType::Unmatched;
393
+ RegionType RenameRangeDetailCollector::addSyntacticRenameRanges (
394
+ const ResolvedLoc &resolved, const RenameLoc &config) {
382
395
383
- assert (Config.Usage != NameUsage::Call || Config.IsFunctionLike );
396
+ if (!resolved.range .isValid ())
397
+ return RegionType::Unmatched;
384
398
385
- // FIXME: handle escaped keyword names `init`
386
- bool IsSubscript = Old.base () == " subscript" && Config.IsFunctionLike ;
387
- bool IsInit = Old.base () == " init" && Config.IsFunctionLike ;
399
+ NameUsage usage = config.Usage ;
388
400
389
- // FIXME: this should only be treated specially for instance methods.
390
- bool IsCallAsFunction =
391
- Old.base () == " callAsFunction" && Config.IsFunctionLike ;
401
+ auto regionKind = getSyntacticRenameRegionType (resolved);
392
402
393
- bool IsSpecialBase = IsInit || IsSubscript || IsCallAsFunction ;
403
+ SpecialBaseName specialBaseName = specialBaseNameFor (Old) ;
394
404
395
- // Filter out non-semantic special basename locations with no labels.
396
- // We've already filtered out those in active code, so these are
397
- // any appearance of just 'init', 'subscript', or 'callAsFunction' in
398
- // strings, comments, and inactive code.
399
- if (IsSpecialBase && (Config.Usage == NameUsage::Unknown &&
400
- Resolved.labelType == LabelRangeType::None))
401
- return RegionType::Unmatched;
405
+ if (usage == NameUsage::Unknown) {
406
+ // Unknown name usage occurs if we don't have an entry in the index that
407
+ // tells us whether the location is a call, reference or a definition. The
408
+ // most common reasons why this happens is if the editor is adding syntactic
409
+ // results (eg. from comments or string literals).
410
+ //
411
+ // Determine whether we should include them.
412
+ if (regionKind == RegionType::ActiveCode) {
413
+ // If the reference is in active code, we should have had a name usage
414
+ // from the index. Since we don't, they are likely unrelated symbols that
415
+ // happen to have the same name. Don't return them as matching ranges.
416
+ return RegionType::Unmatched;
417
+ }
418
+ if (specialBaseName != SpecialBaseName::None &&
419
+ resolved.labelType == LabelRangeType::None) {
420
+ // Filter out non-semantic special basename locations with no labels.
421
+ // We've already filtered out those in active code, so these are
422
+ // any appearance of just 'init', 'subscript', or 'callAsFunction' in
423
+ // strings, comments, and inactive code.
424
+ return RegionType::Unmatched;
425
+ }
426
+ }
402
427
403
- if (!Config.IsFunctionLike || !IsSpecialBase) {
404
- if (renameBase (Resolved.range , RefactoringRangeKind::BaseName))
428
+ switch (specialBaseName) {
429
+ case SpecialBaseName::None:
430
+ // If we don't have a special base name, we can just rename it.
431
+ if (renameBase (resolved.range , RefactoringRangeKind::BaseName)) {
405
432
return RegionType::Mismatch;
406
-
407
- } else if (IsInit || IsCallAsFunction) {
408
- if (renameBase (Resolved.range , RefactoringRangeKind::KeywordBaseName)) {
409
- // The base name doesn't need to match (but may) for calls, but
410
- // it should for definitions and references.
411
- if (Config.Usage == NameUsage::Definition ||
412
- Config.Usage == NameUsage::Reference) {
433
+ }
434
+ break ;
435
+ case SpecialBaseName::Init:
436
+ case SpecialBaseName::CallAsFunction:
437
+ if (renameBase (resolved.range , RefactoringRangeKind::KeywordBaseName)) {
438
+ // The base name doesn't need to match for calls, for example because
439
+ // an initializer can be called as `MyType()` and `callAsFunction` can
440
+ // be called as `myStruct()`, so even if the base fails to be renamed,
441
+ // continue.
442
+ // But the names do need to match for definitions and references.
443
+ if (usage == NameUsage::Definition || usage == NameUsage::Reference) {
413
444
return RegionType::Mismatch;
414
445
}
415
446
}
416
- } else if (IsSubscript && Config.Usage == NameUsage::Definition) {
417
- if (renameBase (Resolved.range , RefactoringRangeKind::KeywordBaseName))
418
- return RegionType::Mismatch;
447
+ break ;
448
+ case SpecialBaseName::Subscript:
449
+ // Only try renaming the base for definitions of the subscript.
450
+ // Accesses to the subscript are modelled as references with `[` as the
451
+ // base name, which does not match. Subscripts are never called in the
452
+ // index.
453
+ if (usage == NameUsage::Definition) {
454
+ if (renameBase (resolved.range , RefactoringRangeKind::KeywordBaseName)) {
455
+ return RegionType::Mismatch;
456
+ }
457
+ }
458
+ break ;
419
459
}
420
460
421
- bool HandleLabels = false ;
422
- if (Config.IsFunctionLike ) {
423
- switch (Config.Usage ) {
461
+ bool handleLabels = false ;
462
+ bool isCallSite = false ;
463
+ if (Old.isFunction ()) {
464
+ switch (usage) {
424
465
case NameUsage::Call:
425
- HandleLabels = !isOperator ();
466
+ // All calls except for operators have argument labels that should be
467
+ // renamed.
468
+ handleLabels = !Lexer::isOperator (Old.base ());
469
+ isCallSite = true ;
426
470
break ;
427
471
case NameUsage::Definition:
428
- HandleLabels = true ;
472
+ // All function definitions have argument labels that should be renamed.
473
+ handleLabels = true ;
474
+ isCallSite = false ;
429
475
break ;
430
476
case NameUsage::Reference:
431
- HandleLabels =
432
- Resolved.labelType == LabelRangeType::Selector || IsSubscript;
477
+ if (resolved.labelType == LabelRangeType::CompoundName) {
478
+ // If we have a compound name that specifies argument labels to
479
+ // disambiguate functions with the same base name, we always need to
480
+ // rename the labels.
481
+ handleLabels = true ;
482
+ isCallSite = false ;
483
+ } else if (specialBaseName == SpecialBaseName::Subscript) {
484
+ // Accesses to a subscript are modeled using a reference to the
485
+ // subscript (with base name `[`). We always need to rename argument
486
+ // labels here.
487
+ handleLabels = true ;
488
+ isCallSite = true ;
489
+ } else {
490
+ handleLabels = false ;
491
+ isCallSite = false ;
492
+ }
433
493
break ;
434
494
case NameUsage::Unknown:
435
- HandleLabels = Resolved.labelType != LabelRangeType::None;
495
+ // If we don't know where the function is used, fall back to trying to
496
+ // rename labels if there are some.
497
+ handleLabels = resolved.labelType != LabelRangeType::None;
498
+ isCallSite = resolved.labelType == LabelRangeType::CallArg;
436
499
break ;
437
500
}
438
501
}
439
502
440
- if (HandleLabels) {
441
- bool isCallSite = Config.Usage != NameUsage::Definition &&
442
- (Config.Usage != NameUsage::Reference || IsSubscript) &&
443
- Resolved.labelType == LabelRangeType::CallArg;
444
-
445
- if (renameLabels (Resolved.labelRanges , Resolved.firstTrailingLabel ,
446
- Resolved.labelType , isCallSite))
447
- return Config.Usage == NameUsage::Unknown ? RegionType::Unmatched
448
- : RegionType::Mismatch;
503
+ if (handleLabels) {
504
+ bool renameLabelsFailed =
505
+ renameLabels (resolved.labelRanges , resolved.firstTrailingLabel ,
506
+ resolved.labelType , isCallSite);
507
+ if (renameLabelsFailed) {
508
+ return usage == NameUsage::Unknown ? RegionType::Unmatched
509
+ : RegionType::Mismatch;
510
+ }
449
511
}
450
512
451
- return RegionKind ;
513
+ return regionKind ;
452
514
}
453
515
454
516
} // end anonymous namespace
0 commit comments