зеркало из https://github.com/microsoft/clang-1.git
Fix up the calls to CorrectTypo in Sema*ObjC.cpp to use callback
objects, and add a basic CorrectionCandidateCallback template class to simplify the fixups. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148085 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
a150fa3080
Коммит
2f4d88f441
|
@ -110,6 +110,12 @@ public:
|
|||
CorrectionDecls.front() == 0;
|
||||
}
|
||||
|
||||
// Check if this TypoCorrection is the given keyword.
|
||||
template<std::size_t StrLen>
|
||||
bool isKeyword(const char (&Str)[StrLen]) const {
|
||||
return isKeyword() && getCorrectionAsIdentifierInfo()->isStr(Str);
|
||||
}
|
||||
|
||||
// Returns true if the correction either is a keyword or has a known decl.
|
||||
bool isResolved() const { return !CorrectionDecls.empty(); }
|
||||
|
||||
|
@ -135,8 +141,8 @@ private:
|
|||
unsigned EditDistance;
|
||||
};
|
||||
|
||||
// @brief Base class for callback objects used by Sema::CorrectTypo to check the
|
||||
// validity of a potential typo correction.
|
||||
/// @brief Base class for callback objects used by Sema::CorrectTypo to check
|
||||
/// the validity of a potential typo correction.
|
||||
class CorrectionCandidateCallback {
|
||||
public:
|
||||
CorrectionCandidateCallback()
|
||||
|
@ -163,6 +169,16 @@ class CorrectionCandidateCallback {
|
|||
bool IsObjCIvarLookup;
|
||||
};
|
||||
|
||||
/// @brief Simple template class for restricting typo correction candidates
|
||||
/// to ones having a single Decl* of the given type.
|
||||
template <class C>
|
||||
class DeclFilterCCC : public CorrectionCandidateCallback {
|
||||
public:
|
||||
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
|
||||
return candidate.getCorrectionDeclAs<C>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -347,6 +347,28 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Callback to only accept typo corrections that are Objective-C classes.
|
||||
// If an ObjCInterfaceDecl* is given to the constructor, then the validation
|
||||
// function will reject corrections to that class.
|
||||
class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
|
||||
public:
|
||||
ObjCInterfaceValidatorCCC() : CurrentIDecl(0) {}
|
||||
explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
|
||||
: CurrentIDecl(IDecl) {}
|
||||
|
||||
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
|
||||
ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();
|
||||
return ID && !declaresSameEntity(ID, CurrentIDecl);
|
||||
}
|
||||
|
||||
private:
|
||||
ObjCInterfaceDecl *CurrentIDecl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Decl *Sema::
|
||||
ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||
|
@ -396,20 +418,17 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
LookupOrdinaryName);
|
||||
|
||||
if (!PrevDecl) {
|
||||
// Try to correct for a typo in the superclass name.
|
||||
TypoCorrection Corrected = CorrectTypo(
|
||||
// Try to correct for a typo in the superclass name without correcting
|
||||
// to the class we're defining.
|
||||
ObjCInterfaceValidatorCCC Validator(IDecl);
|
||||
if (TypoCorrection Corrected = CorrectTypo(
|
||||
DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
|
||||
NULL, NULL, false, CTC_NoKeywords);
|
||||
if ((PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
|
||||
if (declaresSameEntity(PrevDecl, IDecl)) {
|
||||
// Don't correct to the class we're defining.
|
||||
PrevDecl = 0;
|
||||
} else {
|
||||
Diag(SuperLoc, diag::err_undef_superclass_suggest)
|
||||
<< SuperName << ClassName << PrevDecl->getDeclName();
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_decl)
|
||||
<< PrevDecl->getDeclName();
|
||||
}
|
||||
NULL, &Validator)) {
|
||||
PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
|
||||
Diag(SuperLoc, diag::err_undef_superclass_suggest)
|
||||
<< SuperName << ClassName << PrevDecl->getDeclName();
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_decl)
|
||||
<< PrevDecl->getDeclName();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,9 +652,10 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
|
|||
ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
|
||||
ProtocolId[i].second);
|
||||
if (!PDecl) {
|
||||
DeclFilterCCC<ObjCProtocolDecl> Validator;
|
||||
TypoCorrection Corrected = CorrectTypo(
|
||||
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
|
||||
LookupObjCProtocolName, TUScope, NULL, NULL, false, CTC_NoKeywords);
|
||||
LookupObjCProtocolName, TUScope, NULL, &Validator);
|
||||
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {
|
||||
Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
|
||||
<< ProtocolId[i].first << Corrected.getCorrection();
|
||||
|
@ -870,15 +890,16 @@ Decl *Sema::ActOnStartClassImplementation(
|
|||
} else {
|
||||
// We did not find anything with the name ClassName; try to correct for
|
||||
// typos in the class name.
|
||||
TypoCorrection Corrected = CorrectTypo(
|
||||
ObjCInterfaceValidatorCCC Validator;
|
||||
if (TypoCorrection Corrected = CorrectTypo(
|
||||
DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
|
||||
NULL, NULL, false, CTC_NoKeywords);
|
||||
if ((IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
|
||||
NULL, &Validator)) {
|
||||
// Suggest the (potentially) correct interface name. However, put the
|
||||
// fix-it hint itself in a separate note, since changing the name in
|
||||
// the warning would make the fix-it change semantics.However, don't
|
||||
// provide a code-modification hint or use the typo name for recovery,
|
||||
// because this is just a warning. The program may actually be correct.
|
||||
IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
|
||||
DeclarationName CorrectedName = Corrected.getCorrection();
|
||||
Diag(ClassLoc, diag::warn_undef_interface_suggest)
|
||||
<< ClassName << CorrectedName;
|
||||
|
|
|
@ -703,11 +703,12 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
}
|
||||
|
||||
// Attempt to correct for typos in property names.
|
||||
TypoCorrection Corrected = CorrectTypo(
|
||||
DeclFilterCCC<ObjCPropertyDecl> Validator;
|
||||
if (TypoCorrection Corrected = CorrectTypo(
|
||||
DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
|
||||
NULL, IFace, false, CTC_NoKeywords, OPT);
|
||||
if (ObjCPropertyDecl *Property =
|
||||
Corrected.getCorrectionDeclAs<ObjCPropertyDecl>()) {
|
||||
NULL, &Validator, IFace, false, OPT)) {
|
||||
ObjCPropertyDecl *Property =
|
||||
Corrected.getCorrectionDeclAs<ObjCPropertyDecl>();
|
||||
DeclarationName TypoResult = Corrected.getCorrection();
|
||||
Diag(MemberLoc, diag::err_property_not_found_suggest)
|
||||
<< MemberName << QualType(OPT, 0) << TypoResult
|
||||
|
@ -847,6 +848,24 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
|
|||
<< &propertyName << Context.getObjCInterfaceType(IFace));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback {
|
||||
public:
|
||||
ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
|
||||
// Determine whether "super" is acceptable in the current context.
|
||||
if (Method && Method->getClassInterface())
|
||||
WantObjCSuper = Method->getClassInterface()->getSuperClass();
|
||||
}
|
||||
|
||||
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
|
||||
return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
|
||||
candidate.isKeyword("super");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
|
||||
IdentifierInfo *Name,
|
||||
SourceLocation NameLoc,
|
||||
|
@ -916,39 +935,32 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
|
|||
}
|
||||
}
|
||||
|
||||
// Determine our typo-correction context.
|
||||
CorrectTypoContext CTC = CTC_Expression;
|
||||
if (ObjCMethodDecl *Method = getCurMethodDecl())
|
||||
if (Method->getClassInterface() &&
|
||||
Method->getClassInterface()->getSuperClass())
|
||||
CTC = CTC_ObjCMessageReceiver;
|
||||
|
||||
ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
|
||||
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
|
||||
Result.getLookupKind(), S, NULL,
|
||||
NULL, false, CTC)) {
|
||||
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
|
||||
// If we found a declaration, correct when it refers to an Objective-C
|
||||
// class.
|
||||
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) {
|
||||
Diag(NameLoc, diag::err_unknown_receiver_suggest)
|
||||
<< Name << Corrected.getCorrection()
|
||||
<< FixItHint::CreateReplacement(SourceRange(NameLoc),
|
||||
ND->getNameAsString());
|
||||
Diag(ND->getLocation(), diag::note_previous_decl)
|
||||
<< Corrected.getCorrection();
|
||||
|
||||
QualType T = Context.getObjCInterfaceType(Class);
|
||||
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
|
||||
ReceiverType = CreateParsedType(T, TSInfo);
|
||||
return ObjCClassMessage;
|
||||
}
|
||||
} else if (Corrected.isKeyword() &&
|
||||
Corrected.getCorrectionAsIdentifierInfo()->isStr("super")) {
|
||||
// If we've found the keyword "super", this is a send to super.
|
||||
&Validator)) {
|
||||
if (Corrected.isKeyword()) {
|
||||
// If we've found the keyword "super" (the only keyword that would be
|
||||
// returned by CorrectTypo), this is a send to super.
|
||||
Diag(NameLoc, diag::err_unknown_receiver_suggest)
|
||||
<< Name << Corrected.getCorrection()
|
||||
<< FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
|
||||
return ObjCSuperMessage;
|
||||
} else if (ObjCInterfaceDecl *Class =
|
||||
Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
|
||||
// If we found a declaration, correct when it refers to an Objective-C
|
||||
// class.
|
||||
Diag(NameLoc, diag::err_unknown_receiver_suggest)
|
||||
<< Name << Corrected.getCorrection()
|
||||
<< FixItHint::CreateReplacement(SourceRange(NameLoc),
|
||||
Class->getNameAsString());
|
||||
Diag(Class->getLocation(), diag::note_previous_decl)
|
||||
<< Corrected.getCorrection();
|
||||
|
||||
QualType T = Context.getObjCInterfaceType(Class);
|
||||
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
|
||||
ReceiverType = CreateParsedType(T, TSInfo);
|
||||
return ObjCClassMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче