|
51 | 51 | #endif
|
52 | 52 |
|
53 | 53 | #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
|
| 54 | +#include "Plugins/Language/ObjC/ObjCLanguage.h" |
54 | 55 |
|
55 | 56 | #include "llvm/ADT/STLExtras.h"
|
56 | 57 | #include "llvm/Support/Compiler.h"
|
@@ -634,81 +635,101 @@ void Module::FindCompileUnits(const FileSpec &path,
|
634 | 635 |
|
635 | 636 | Module::LookupInfo::LookupInfo(ConstString name,
|
636 | 637 | FunctionNameType name_type_mask,
|
637 |
| - LanguageType language_type) |
638 |
| - : m_name(name), m_lookup_name(name), m_language_type(language_type), |
| 638 | + LanguageType language) |
| 639 | + : m_name(name), m_lookup_name(), m_language(language), |
639 | 640 | m_name_type_mask(eFunctionNameTypeNone),
|
640 | 641 | m_match_name_after_lookup(false) {
|
| 642 | + const char *name_cstr = name.GetCString(); |
641 | 643 | llvm::StringRef basename;
|
642 | 644 | llvm::StringRef context;
|
643 | 645 |
|
644 |
| - std::vector<Language *> languages; |
645 |
| - Language::ForEach([&languages](Language *l) { |
646 |
| - languages.push_back(l); |
647 |
| - return true; |
648 |
| - }); |
649 |
| - |
650 | 646 | if (name_type_mask & eFunctionNameTypeAuto) {
|
651 |
| - if (language_type == eLanguageTypeUnknown) { |
652 |
| - for (Language *lang : languages) { |
653 |
| - Language::FunctionNameInfo info = lang->GetFunctionNameInfo(name); |
654 |
| - if (info.func_name_type != eFunctionNameTypeNone) { |
655 |
| - m_name_type_mask = info.func_name_type; |
656 |
| - basename = info.basename; |
657 |
| - context = info.context; |
658 |
| - break; |
659 |
| - } |
660 |
| - } |
| 647 | + if (CPlusPlusLanguage::IsCPPMangledName(name_cstr)) |
| 648 | + m_name_type_mask = eFunctionNameTypeFull; |
| 649 | + else if ((language == eLanguageTypeUnknown || |
| 650 | + Language::LanguageIsObjC(language)) && |
| 651 | + ObjCLanguage::IsPossibleObjCMethodName(name_cstr)) |
| 652 | + m_name_type_mask = eFunctionNameTypeFull; |
| 653 | + else if (Language::LanguageIsC(language)) { |
| 654 | + m_name_type_mask = eFunctionNameTypeFull; |
661 | 655 | } else {
|
662 |
| - if (auto *lang = Language::FindPlugin(language_type)) { |
663 |
| - Language::FunctionNameInfo info = lang->GetFunctionNameInfo(name); |
664 |
| - m_name_type_mask = info.func_name_type; |
665 |
| - basename = info.basename; |
666 |
| - context = info.context; |
| 656 | + if ((language == eLanguageTypeUnknown || |
| 657 | + Language::LanguageIsObjC(language)) && |
| 658 | + ObjCLanguage::IsPossibleObjCSelector(name_cstr)) |
| 659 | + m_name_type_mask |= eFunctionNameTypeSelector; |
| 660 | + |
| 661 | + CPlusPlusLanguage::MethodName cpp_method(name); |
| 662 | + basename = cpp_method.GetBasename(); |
| 663 | + if (basename.empty()) { |
| 664 | + if (CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, |
| 665 | + basename)) |
| 666 | + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); |
| 667 | + else |
| 668 | + m_name_type_mask |= eFunctionNameTypeFull; |
| 669 | + } else { |
| 670 | + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); |
667 | 671 | }
|
668 | 672 | }
|
669 |
| - |
670 |
| - // NOTE: There are several ways to get here, but this is a fallback path in |
671 |
| - // case the above does not succeed at extracting any useful information from |
672 |
| - // the loaded language plugins. |
673 |
| - if (m_name_type_mask == eFunctionNameTypeNone) |
674 |
| - m_name_type_mask = eFunctionNameTypeFull; |
675 |
| - |
676 | 673 | } else {
|
677 | 674 | m_name_type_mask = name_type_mask;
|
678 |
| - if (language_type != eLanguageTypeUnknown) { |
679 |
| - if (auto *lang = Language::FindPlugin(language_type)) { |
680 |
| - Language::FunctionNameInfo info = lang->GetFunctionNameInfo(name); |
681 |
| - if (info.func_name_type & m_name_type_mask) { |
682 |
| - // If the user asked for FunctionNameTypes that aren't possible, |
683 |
| - // then filter those out. (e.g. asking for Selectors on |
684 |
| - // C++ symbols, or even if the symbol given can't be a selector in |
685 |
| - // ObjC) |
686 |
| - m_name_type_mask &= info.func_name_type; |
687 |
| - basename = info.basename; |
688 |
| - context = info.context; |
| 675 | + if (name_type_mask & eFunctionNameTypeMethod || |
| 676 | + name_type_mask & eFunctionNameTypeBase) { |
| 677 | + // If they've asked for a CPP method or function name and it can't be |
| 678 | + // that, we don't even need to search for CPP methods or names. |
| 679 | + CPlusPlusLanguage::MethodName cpp_method(name); |
| 680 | + if (cpp_method.IsValid()) { |
| 681 | + basename = cpp_method.GetBasename(); |
| 682 | + |
| 683 | + if (!cpp_method.GetQualifiers().empty()) { |
| 684 | + // There is a "const" or other qualifier following the end of the |
| 685 | + // function parens, this can't be a eFunctionNameTypeBase |
| 686 | + m_name_type_mask &= ~(eFunctionNameTypeBase); |
| 687 | + if (m_name_type_mask == eFunctionNameTypeNone) |
| 688 | + return; |
689 | 689 | }
|
| 690 | + } else { |
| 691 | + // If the CPP method parser didn't manage to chop this up, try to fill |
| 692 | + // in the base name if we can. If a::b::c is passed in, we need to just |
| 693 | + // look up "c", and then we'll filter the result later. |
| 694 | + CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, |
| 695 | + basename); |
690 | 696 | }
|
691 |
| - } else { |
692 |
| - for (Language *lang : languages) { |
693 |
| - Language::FunctionNameInfo info = lang->GetFunctionNameInfo(name); |
694 |
| - if (info.func_name_type & m_name_type_mask) { |
695 |
| - m_name_type_mask &= info.func_name_type; |
696 |
| - basename = info.basename; |
697 |
| - context = info.context; |
698 |
| - break; |
699 |
| - } |
| 697 | + } |
| 698 | + |
| 699 | + if (name_type_mask & eFunctionNameTypeSelector) { |
| 700 | + if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) { |
| 701 | + m_name_type_mask &= ~(eFunctionNameTypeSelector); |
| 702 | + if (m_name_type_mask == eFunctionNameTypeNone) |
| 703 | + return; |
| 704 | + } |
| 705 | + } |
| 706 | + |
| 707 | + // Still try and get a basename in case someone specifies a name type mask |
| 708 | + // of eFunctionNameTypeFull and a name like "A::func" |
| 709 | + if (basename.empty()) { |
| 710 | + if (name_type_mask & eFunctionNameTypeFull && |
| 711 | + !CPlusPlusLanguage::IsCPPMangledName(name_cstr)) { |
| 712 | + CPlusPlusLanguage::MethodName cpp_method(name); |
| 713 | + basename = cpp_method.GetBasename(); |
| 714 | + if (basename.empty()) |
| 715 | + CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, |
| 716 | + basename); |
700 | 717 | }
|
701 | 718 | }
|
702 | 719 | }
|
703 | 720 |
|
704 | 721 | if (!basename.empty()) {
|
705 |
| - // The name supplied was incomplete for lookup purposes. For example, in C++ |
706 |
| - // we may have gotten something like "a::count". In this case, we want to do |
707 |
| - // a lookup on the basename "count" and then make sure any matching results |
708 |
| - // contain "a::count" so that it would match "b::a::count" and "a::count". |
709 |
| - // This is why we set match_name_after_lookup to true. |
| 722 | + // The name supplied was a partial C++ path like "a::count". In this case |
| 723 | + // we want to do a lookup on the basename "count" and then make sure any |
| 724 | + // matching results contain "a::count" so that it would match "b::a::count" |
| 725 | + // and "a::count". This is why we set "match_name_after_lookup" to true |
710 | 726 | m_lookup_name.SetString(basename);
|
711 | 727 | m_match_name_after_lookup = true;
|
| 728 | + } else { |
| 729 | + // The name is already correct, just use the exact name as supplied, and we |
| 730 | + // won't need to check if any matches contain "name" |
| 731 | + m_lookup_name = name; |
| 732 | + m_match_name_after_lookup = false; |
712 | 733 | }
|
713 | 734 | }
|
714 | 735 |
|
|
0 commit comments