Path: blob/main/contrib/llvm-project/clang/lib/AST/CommentCommandTraits.cpp
35260 views
//===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/AST/CommentCommandTraits.h"9#include "llvm/ADT/STLExtras.h"10#include <cassert>1112namespace clang {13namespace comments {1415#include "clang/AST/CommentCommandInfo.inc"1617CommandTraits::CommandTraits(llvm::BumpPtrAllocator &Allocator,18const CommentOptions &CommentOptions)19: NextID(std::size(Commands)), Allocator(Allocator) {20registerCommentOptions(CommentOptions);21}2223void CommandTraits::registerCommentOptions(24const CommentOptions &CommentOptions) {25for (CommentOptions::BlockCommandNamesTy::const_iterator26I = CommentOptions.BlockCommandNames.begin(),27E = CommentOptions.BlockCommandNames.end();28I != E; I++) {29registerBlockCommand(*I);30}31}3233const CommandInfo *CommandTraits::getCommandInfoOrNULL(StringRef Name) const {34if (const CommandInfo *Info = getBuiltinCommandInfo(Name))35return Info;36return getRegisteredCommandInfo(Name);37}3839const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const {40if (const CommandInfo *Info = getBuiltinCommandInfo(CommandID))41return Info;42return getRegisteredCommandInfo(CommandID);43}4445const CommandInfo *46CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const {47// Single-character command impostures, such as \t or \n, should not go48// through the fixit logic.49if (Typo.size() <= 1)50return nullptr;5152// The maximum edit distance we're prepared to accept.53const unsigned MaxEditDistance = 1;5455unsigned BestEditDistance = MaxEditDistance;56SmallVector<const CommandInfo *, 2> BestCommand;5758auto ConsiderCorrection = [&](const CommandInfo *Command) {59StringRef Name = Command->Name;6061unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());62if (MinPossibleEditDistance <= BestEditDistance) {63unsigned EditDistance = Typo.edit_distance(Name, true, BestEditDistance);64if (EditDistance < BestEditDistance) {65BestEditDistance = EditDistance;66BestCommand.clear();67}68if (EditDistance == BestEditDistance)69BestCommand.push_back(Command);70}71};7273for (const auto &Command : Commands)74ConsiderCorrection(&Command);7576for (const auto *Command : RegisteredCommands)77if (!Command->IsUnknownCommand)78ConsiderCorrection(Command);7980return BestCommand.size() == 1 ? BestCommand[0] : nullptr;81}8283CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) {84char *Name = Allocator.Allocate<char>(CommandName.size() + 1);85memcpy(Name, CommandName.data(), CommandName.size());86Name[CommandName.size()] = '\0';8788// Value-initialize (=zero-initialize in this case) a new CommandInfo.89CommandInfo *Info = new (Allocator) CommandInfo();90Info->Name = Name;91// We only have a limited number of bits to encode command IDs in the92// CommandInfo structure, so the ID numbers can potentially wrap around.93assert((NextID < (1 << CommandInfo::NumCommandIDBits))94&& "Too many commands. We have limited bits for the command ID.");95Info->ID = NextID++;9697RegisteredCommands.push_back(Info);9899return Info;100}101102const CommandInfo *CommandTraits::registerUnknownCommand(103StringRef CommandName) {104CommandInfo *Info = createCommandInfoWithName(CommandName);105Info->IsUnknownCommand = true;106return Info;107}108109const CommandInfo *CommandTraits::registerBlockCommand(StringRef CommandName) {110CommandInfo *Info = createCommandInfoWithName(CommandName);111Info->IsBlockCommand = true;112return Info;113}114115const CommandInfo *CommandTraits::getBuiltinCommandInfo(116unsigned CommandID) {117if (CommandID < std::size(Commands))118return &Commands[CommandID];119return nullptr;120}121122const CommandInfo *CommandTraits::getRegisteredCommandInfo(123StringRef Name) const {124for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) {125if (RegisteredCommands[i]->Name == Name)126return RegisteredCommands[i];127}128return nullptr;129}130131const CommandInfo *CommandTraits::getRegisteredCommandInfo(132unsigned CommandID) const {133return RegisteredCommands[CommandID - std::size(Commands)];134}135136} // end namespace comments137} // end namespace clang138139140141