@@ -52,8 +52,6 @@ class RenameRangeDetailCollector {
5252 llvm::Optional<unsigned > FirstTrailingLabel,
5353 LabelRangeType RangeType, bool isCallSite);
5454
55- bool isOperator () const { return Lexer::isOperator (Old.base ()); }
56-
5755private:
5856 // / Returns the range of the (possibly escaped) identifier at the start of
5957 // / \p Range and updates \p IsEscaped to indicate whether it's escaped or not.
@@ -151,7 +149,7 @@ void RenameRangeDetailCollector::splitAndRenameLabel(CharSourceRange Range,
151149 case LabelRangeType::NoncollapsibleParam:
152150 return splitAndRenameParamLabel (Range, NameIndex,
153151 /* IsCollapsible=*/ false );
154- case LabelRangeType::Selector :
152+ case LabelRangeType::CompoundName :
155153 return addRenameRange (Range, RefactoringRangeKind::SelectorArgumentLabel,
156154 NameIndex);
157155 case LabelRangeType::None:
@@ -250,7 +248,7 @@ bool RenameRangeDetailCollector::labelRangeMatches(CharSourceRange Range,
250248 LLVM_FALLTHROUGH;
251249 case LabelRangeType::CallArg:
252250 case LabelRangeType::Param:
253- case LabelRangeType::Selector :
251+ case LabelRangeType::CompoundName :
254252 return ExistingLabel == (Expected.empty () ? " _" : Expected);
255253 case LabelRangeType::None:
256254 llvm_unreachable (" Unhandled label range type" );
@@ -277,12 +275,12 @@ bool RenameRangeDetailCollector::renameLabelsLenient(
277275 if (OldNames.empty ())
278276 return true ;
279277
280- while (!labelRangeMatches (Label, LabelRangeType::Selector ,
278+ while (!labelRangeMatches (Label, LabelRangeType::CompoundName ,
281279 OldNames.back ())) {
282280 if ((OldNames = OldNames.drop_back ()).empty ())
283281 return true ;
284282 }
285- splitAndRenameLabel (Label, LabelRangeType::Selector ,
283+ splitAndRenameLabel (Label, LabelRangeType::CompoundName ,
286284 OldNames.size () - 1 );
287285 OldNames = OldNames.drop_back ();
288286 continue ;
@@ -297,7 +295,7 @@ bool RenameRangeDetailCollector::renameLabelsLenient(
297295 if ((OldNames = OldNames.drop_back ()).empty ())
298296 return true ;
299297 }
300- splitAndRenameLabel (Label, LabelRangeType::Selector ,
298+ splitAndRenameLabel (Label, LabelRangeType::CompoundName ,
301299 OldNames.size () - 1 );
302300 OldNames = OldNames.drop_back ();
303301 continue ;
@@ -366,89 +364,153 @@ RegionType RenameRangeDetailCollector::getSyntacticRenameRegionType(
366364 }
367365}
368366
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+ };
371374
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+ }
374392
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) {
382395
383- assert (Config.Usage != NameUsage::Call || Config.IsFunctionLike );
396+ if (!resolved.range .isValid ())
397+ return RegionType::Unmatched;
384398
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 ;
388400
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);
392402
393- bool IsSpecialBase = IsInit || IsSubscript || IsCallAsFunction ;
403+ SpecialBaseName specialBaseName = specialBaseNameFor (Old) ;
394404
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+ }
402427
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)) {
405432 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) {
413444 return RegionType::Mismatch;
414445 }
415446 }
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 ;
419459 }
420460
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) {
424465 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 ;
426470 break ;
427471 case NameUsage::Definition:
428- HandleLabels = true ;
472+ // All function definitions have argument labels that should be renamed.
473+ handleLabels = true ;
474+ isCallSite = false ;
429475 break ;
430476 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+ }
433493 break ;
434494 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;
436499 break ;
437500 }
438501 }
439502
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+ }
449511 }
450512
451- return RegionKind ;
513+ return regionKind ;
452514}
453515
454516} // end anonymous namespace
0 commit comments