forked from OSchip/llvm-project
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. llvm-svn: 148085
This commit is contained in:
parent
04ea962144
commit
e31b88833a
|
@ -110,6 +110,12 @@ public:
|
||||||
CorrectionDecls.front() == 0;
|
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.
|
// Returns true if the correction either is a keyword or has a known decl.
|
||||||
bool isResolved() const { return !CorrectionDecls.empty(); }
|
bool isResolved() const { return !CorrectionDecls.empty(); }
|
||||||
|
|
||||||
|
@ -135,8 +141,8 @@ private:
|
||||||
unsigned EditDistance;
|
unsigned EditDistance;
|
||||||
};
|
};
|
||||||
|
|
||||||
// @brief Base class for callback objects used by Sema::CorrectTypo to check the
|
/// @brief Base class for callback objects used by Sema::CorrectTypo to check
|
||||||
// validity of a potential typo correction.
|
/// the validity of a potential typo correction.
|
||||||
class CorrectionCandidateCallback {
|
class CorrectionCandidateCallback {
|
||||||
public:
|
public:
|
||||||
CorrectionCandidateCallback()
|
CorrectionCandidateCallback()
|
||||||
|
@ -163,6 +169,16 @@ class CorrectionCandidateCallback {
|
||||||
bool IsObjCIvarLookup;
|
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
|
#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::
|
Decl *Sema::
|
||||||
ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||||
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
IdentifierInfo *ClassName, SourceLocation ClassLoc,
|
||||||
|
@ -396,20 +418,17 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
||||||
LookupOrdinaryName);
|
LookupOrdinaryName);
|
||||||
|
|
||||||
if (!PrevDecl) {
|
if (!PrevDecl) {
|
||||||
// Try to correct for a typo in the superclass name.
|
// Try to correct for a typo in the superclass name without correcting
|
||||||
TypoCorrection Corrected = CorrectTypo(
|
// to the class we're defining.
|
||||||
|
ObjCInterfaceValidatorCCC Validator(IDecl);
|
||||||
|
if (TypoCorrection Corrected = CorrectTypo(
|
||||||
DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
|
DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,
|
||||||
NULL, NULL, false, CTC_NoKeywords);
|
NULL, &Validator)) {
|
||||||
if ((PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
|
PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
|
||||||
if (declaresSameEntity(PrevDecl, IDecl)) {
|
Diag(SuperLoc, diag::err_undef_superclass_suggest)
|
||||||
// Don't correct to the class we're defining.
|
<< SuperName << ClassName << PrevDecl->getDeclName();
|
||||||
PrevDecl = 0;
|
Diag(PrevDecl->getLocation(), diag::note_previous_decl)
|
||||||
} else {
|
<< PrevDecl->getDeclName();
|
||||||
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,
|
ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
|
||||||
ProtocolId[i].second);
|
ProtocolId[i].second);
|
||||||
if (!PDecl) {
|
if (!PDecl) {
|
||||||
|
DeclFilterCCC<ObjCProtocolDecl> Validator;
|
||||||
TypoCorrection Corrected = CorrectTypo(
|
TypoCorrection Corrected = CorrectTypo(
|
||||||
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
|
DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
|
||||||
LookupObjCProtocolName, TUScope, NULL, NULL, false, CTC_NoKeywords);
|
LookupObjCProtocolName, TUScope, NULL, &Validator);
|
||||||
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {
|
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {
|
||||||
Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
|
Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
|
||||||
<< ProtocolId[i].first << Corrected.getCorrection();
|
<< ProtocolId[i].first << Corrected.getCorrection();
|
||||||
|
@ -870,15 +890,16 @@ Decl *Sema::ActOnStartClassImplementation(
|
||||||
} else {
|
} else {
|
||||||
// We did not find anything with the name ClassName; try to correct for
|
// We did not find anything with the name ClassName; try to correct for
|
||||||
// typos in the class name.
|
// typos in the class name.
|
||||||
TypoCorrection Corrected = CorrectTypo(
|
ObjCInterfaceValidatorCCC Validator;
|
||||||
|
if (TypoCorrection Corrected = CorrectTypo(
|
||||||
DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
|
DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,
|
||||||
NULL, NULL, false, CTC_NoKeywords);
|
NULL, &Validator)) {
|
||||||
if ((IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
|
|
||||||
// Suggest the (potentially) correct interface name. However, put the
|
// Suggest the (potentially) correct interface name. However, put the
|
||||||
// fix-it hint itself in a separate note, since changing the name in
|
// 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
|
// the warning would make the fix-it change semantics.However, don't
|
||||||
// provide a code-modification hint or use the typo name for recovery,
|
// provide a code-modification hint or use the typo name for recovery,
|
||||||
// because this is just a warning. The program may actually be correct.
|
// because this is just a warning. The program may actually be correct.
|
||||||
|
IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
|
||||||
DeclarationName CorrectedName = Corrected.getCorrection();
|
DeclarationName CorrectedName = Corrected.getCorrection();
|
||||||
Diag(ClassLoc, diag::warn_undef_interface_suggest)
|
Diag(ClassLoc, diag::warn_undef_interface_suggest)
|
||||||
<< ClassName << CorrectedName;
|
<< ClassName << CorrectedName;
|
||||||
|
|
|
@ -703,11 +703,12 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to correct for typos in property names.
|
// Attempt to correct for typos in property names.
|
||||||
TypoCorrection Corrected = CorrectTypo(
|
DeclFilterCCC<ObjCPropertyDecl> Validator;
|
||||||
|
if (TypoCorrection Corrected = CorrectTypo(
|
||||||
DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
|
DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
|
||||||
NULL, IFace, false, CTC_NoKeywords, OPT);
|
NULL, &Validator, IFace, false, OPT)) {
|
||||||
if (ObjCPropertyDecl *Property =
|
ObjCPropertyDecl *Property =
|
||||||
Corrected.getCorrectionDeclAs<ObjCPropertyDecl>()) {
|
Corrected.getCorrectionDeclAs<ObjCPropertyDecl>();
|
||||||
DeclarationName TypoResult = Corrected.getCorrection();
|
DeclarationName TypoResult = Corrected.getCorrection();
|
||||||
Diag(MemberLoc, diag::err_property_not_found_suggest)
|
Diag(MemberLoc, diag::err_property_not_found_suggest)
|
||||||
<< MemberName << QualType(OPT, 0) << TypoResult
|
<< MemberName << QualType(OPT, 0) << TypoResult
|
||||||
|
@ -847,6 +848,24 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
|
||||||
<< &propertyName << Context.getObjCInterfaceType(IFace));
|
<< &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,
|
Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
|
||||||
IdentifierInfo *Name,
|
IdentifierInfo *Name,
|
||||||
SourceLocation NameLoc,
|
SourceLocation NameLoc,
|
||||||
|
@ -916,39 +935,32 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine our typo-correction context.
|
ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
|
||||||
CorrectTypoContext CTC = CTC_Expression;
|
|
||||||
if (ObjCMethodDecl *Method = getCurMethodDecl())
|
|
||||||
if (Method->getClassInterface() &&
|
|
||||||
Method->getClassInterface()->getSuperClass())
|
|
||||||
CTC = CTC_ObjCMessageReceiver;
|
|
||||||
|
|
||||||
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
|
if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
|
||||||
Result.getLookupKind(), S, NULL,
|
Result.getLookupKind(), S, NULL,
|
||||||
NULL, false, CTC)) {
|
&Validator)) {
|
||||||
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
|
if (Corrected.isKeyword()) {
|
||||||
// If we found a declaration, correct when it refers to an Objective-C
|
// If we've found the keyword "super" (the only keyword that would be
|
||||||
// class.
|
// returned by CorrectTypo), this is a send to super.
|
||||||
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.
|
|
||||||
Diag(NameLoc, diag::err_unknown_receiver_suggest)
|
Diag(NameLoc, diag::err_unknown_receiver_suggest)
|
||||||
<< Name << Corrected.getCorrection()
|
<< Name << Corrected.getCorrection()
|
||||||
<< FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
|
<< FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
|
||||||
return ObjCSuperMessage;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue