зеркало из https://github.com/microsoft/clang-1.git
documentation parsing. Patch to do typo correction for
documentation commands. Patch was reviewed, along with great suggestions for improvement, by Doug. // rdar://12381408 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181458 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
4b7b104c2c
Коммит
0089bc4dde
|
@ -142,6 +142,8 @@ public:
|
|||
llvm_unreachable("the command should be known");
|
||||
}
|
||||
|
||||
const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const;
|
||||
|
||||
const CommandInfo *getCommandInfo(unsigned CommandID) const;
|
||||
|
||||
const CommandInfo *registerUnknownCommand(StringRef CommandName);
|
||||
|
|
|
@ -159,5 +159,9 @@ def warn_verbatim_block_end_without_start : Warning<
|
|||
def warn_unknown_comment_command_name : Warning<
|
||||
"unknown command tag name">, InGroup<Documentation>, DefaultIgnore;
|
||||
|
||||
def warn_correct_comment_command_name : Warning<
|
||||
"unknown command tag name '%0'; did you mean '%1'?">,
|
||||
InGroup<Documentation>;
|
||||
|
||||
} // end of documentation issue category
|
||||
} // end of AST component
|
||||
|
|
|
@ -43,6 +43,33 @@ const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {
|
|||
return getRegisteredCommandInfo(CommandID);
|
||||
}
|
||||
|
||||
const CommandInfo *
|
||||
CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const {
|
||||
const unsigned MaxEditDistance = 1;
|
||||
unsigned BestEditDistance = MaxEditDistance + 1;
|
||||
SmallVector<const CommandInfo *, 2> BestCommand;
|
||||
|
||||
int NumOfCommands = sizeof(Commands) / sizeof(CommandInfo);
|
||||
for (int i = 0; i < NumOfCommands; i++) {
|
||||
StringRef Name = Commands[i].Name;
|
||||
unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
|
||||
if (MinPossibleEditDistance > 0 &&
|
||||
Typo.size() / MinPossibleEditDistance < 1)
|
||||
continue;
|
||||
unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
|
||||
if (EditDistance > MaxEditDistance)
|
||||
continue;
|
||||
if (EditDistance == BestEditDistance)
|
||||
BestCommand.push_back(&Commands[i]);
|
||||
else if (EditDistance < BestEditDistance) {
|
||||
BestCommand.clear();
|
||||
BestCommand.push_back(&Commands[i]);
|
||||
BestEditDistance = EditDistance;
|
||||
}
|
||||
}
|
||||
return (BestCommand.size() != 1) ? NULL : BestCommand[0];
|
||||
}
|
||||
|
||||
CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) {
|
||||
char *Name = Allocator.Allocate<char>(CommandName.size() + 1);
|
||||
memcpy(Name, CommandName.data(), CommandName.size());
|
||||
|
|
|
@ -265,6 +265,7 @@ const char *findCCommentEnd(const char *BufferPtr, const char *BufferEnd) {
|
|||
}
|
||||
llvm_unreachable("buffer end hit before '*/' was seen");
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
void Lexer::lexCommentText(Token &T) {
|
||||
|
@ -354,8 +355,17 @@ void Lexer::lexCommentText(Token &T) {
|
|||
if (!Info) {
|
||||
formTokenWithChars(T, TokenPtr, tok::unknown_command);
|
||||
T.setUnknownCommandName(CommandName);
|
||||
Diag(T.getLocation(), diag::warn_unknown_comment_command_name);
|
||||
return;
|
||||
if (Info = Traits.getTypoCorrectCommandInfo(CommandName)) {
|
||||
StringRef CorrectedName = Info->Name;
|
||||
SourceRange CommandRange(T.getLocation().getLocWithOffset(1),
|
||||
T.getEndLocation());
|
||||
Diag(T.getLocation(), diag::warn_correct_comment_command_name)
|
||||
<< CommandName << CorrectedName
|
||||
<< FixItHint::CreateReplacement(CommandRange, CorrectedName);
|
||||
} else {
|
||||
Diag(T.getLocation(), diag::warn_unknown_comment_command_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Info->IsVerbatimBlockCommand) {
|
||||
setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info);
|
||||
|
|
|
@ -57,6 +57,12 @@ struct test_deprecated_6 {
|
|||
/// \deprecated
|
||||
void test_deprecated_9(int a);
|
||||
|
||||
// rdar://12381408
|
||||
// expected-warning@+2 {{unknown command tag name 'retur'; did you mean 'return'?}}
|
||||
/// \brief testing fixit
|
||||
/// \retur int in FooBar
|
||||
int FooBar();
|
||||
|
||||
// CHECK: fix-it:"{{.*}}":{5:12-5:22}:"a"
|
||||
// CHECK: fix-it:"{{.*}}":{9:12-9:15}:"aaa"
|
||||
// CHECK: fix-it:"{{.*}}":{13:13-13:23}:"T"
|
||||
|
@ -68,4 +74,4 @@ void test_deprecated_9(int a);
|
|||
// CHECK: fix-it:"{{.*}}":{46:27-46:27}:" __attribute__((deprecated))"
|
||||
// CHECK: fix-it:"{{.*}}":{50:27-50:27}:" __attribute__((deprecated))"
|
||||
// CHECK: fix-it:"{{.*}}":{58:30-58:30}:" MY_ATTR_DEPRECATED"
|
||||
|
||||
// CHECK: fix-it:"{{.*}}":{63:6-63:11}:"return"
|
||||
|
|
Загрузка…
Ссылка в новой задаче