clang: lib/Tooling/RefactoringCallbacks.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

15

16using llvm::StringError;

17using llvm::make_error;

18

21

26

28 std::map<std::string, Replacements> &FileToReplaces)

29 : FileToReplaces(FileToReplaces) {}

30

32 const ast_matchers::internal::DynTypedMatcher &Matcher,

34 MatchFinder.addDynamicMatcher(Matcher, Callback);

35 Callbacks.push_back(Callback);

36}

37

39public:

41 : Refactoring(Refactoring) {}

42

44

45

46 for (const auto &Callback : Refactoring.Callbacks) {

47 Callback->getReplacements().clear();

48 }

49 Refactoring.MatchFinder.matchAST(Context);

50 for (const auto &Callback : Refactoring.Callbacks) {

51 for (const auto &Replacement : Callback->getReplacements()) {

52 llvm::Error Err =

55 if (Err) {

57 << " due to this error:\n"

58 << toString(std::move(Err)) << "\n";

59 }

60 }

61 }

62 }

63

64private:

66};

67

69 return std::make_unique(*this);

70}

71

78 const Stmt &To) {

80 Sources, From,

83}

84

86 : FromId(std::string(FromId)), ToText(std::string(ToText)) {}

87

90 if (const Stmt *FromMatch = Result.Nodes.getNodeAs<Stmt>(FromId)) {

92 *Result.SourceManager,

94

95

96 if (Err) {

97 llvm::errs() << llvm::toString(std::move(Err)) << "\n";

98 assert(false);

99 }

100 }

101}

102

104 : FromId(std::string(FromId)), ToId(std::string(ToId)) {}

105

108 const Stmt *FromMatch = Result.Nodes.getNodeAs<Stmt>(FromId);

109 const Stmt *ToMatch = Result.Nodes.getNodeAs<Stmt>(ToId);

110 if (FromMatch && ToMatch) {

113

114

115 if (Err) {

116 llvm::errs() << llvm::toString(std::move(Err)) << "\n";

117 assert(false);

118 }

119 }

120}

121

123 bool PickTrueBranch)

124 : Id(std::string(Id)), PickTrueBranch(PickTrueBranch) {}

125

129 const Stmt *Body = PickTrueBranch ? Node->getThen() : Node->getElse();

130 if (Body) {

131 auto Err =

133

134

135 if (Err) {

136 llvm::errs() << llvm::toString(std::move(Err)) << "\n";

137 assert(false);

138 }

139 } else if (!PickTrueBranch) {

140

141

142 auto Err =

144

145

146 if (Err) {

147 llvm::errs() << llvm::toString(std::move(Err)) << "\n";

148 assert(false);

149 }

150 }

151 }

152}

153

154ReplaceNodeWithTemplate::ReplaceNodeWithTemplate(

155 llvm::StringRef FromId, std::vector Template)

157

160 std::vector ParsedTemplate;

161 for (size_t Index = 0; Index < ToTemplate.size();) {

162 if (ToTemplate[Index] == '$') {

163 if (ToTemplate.substr(Index, 2) == "$$") {

164 Index += 2;

165 ParsedTemplate.push_back(

166 TemplateElement{TemplateElement::Literal, "$"});

167 } else if (ToTemplate.substr(Index, 2) == "${") {

168 size_t EndOfIdentifier = ToTemplate.find("}", Index);

169 if (EndOfIdentifier == std:🧵:npos) {

170 return make_error(

171 "Unterminated ${...} in replacement template near " +

172 ToTemplate.substr(Index),

173 llvm::inconvertibleErrorCode());

174 }

175 std::string SourceNodeName = std::string(

176 ToTemplate.substr(Index + 2, EndOfIdentifier - Index - 2));

177 ParsedTemplate.push_back(

178 TemplateElement{TemplateElement::Identifier, SourceNodeName});

179 Index = EndOfIdentifier + 1;

180 } else {

181 return make_error(

182 "Invalid $ in replacement template near " +

183 ToTemplate.substr(Index),

184 llvm::inconvertibleErrorCode());

185 }

186 } else {

187 size_t NextIndex = ToTemplate.find('$', Index + 1);

188 ParsedTemplate.push_back(TemplateElement{

189 TemplateElement::Literal,

190 std::string(ToTemplate.substr(Index, NextIndex - Index))});

191 Index = NextIndex;

192 }

193 }

194 return std::unique_ptr(

195 new ReplaceNodeWithTemplate(FromId, std::move(ParsedTemplate)));

196}

197

200 const auto &NodeMap = Result.Nodes.getMap();

201

202 std::string ToText;

203 for (const auto &Element : Template) {

204 switch (Element.Type) {

205 case TemplateElement::Literal:

206 ToText += Element.Value;

207 break;

208 case TemplateElement::Identifier: {

209 auto NodeIter = NodeMap.find(Element.Value);

210 if (NodeIter == NodeMap.end()) {

211 llvm::errs() << "Node " << Element.Value

212 << " used in replacement template not bound in Matcher \n";

213 llvm::report_fatal_error("Unbound node in replacement template.");

214 }

218 Result.Context->getLangOpts());

219 break;

220 }

221 }

222 }

223 auto It = NodeMap.find(FromId);

224 if (It == NodeMap.end()) {

225 llvm::errs() << "Node to be replaced " << FromId

226 << " not bound in query.\n";

227 llvm::report_fatal_error("FromId node not bound in MatchResult");

228 }

231 Result.Context->getLangOpts());

233 if (Err) {

235 << "! " << llvm::toString(std::move(Err)) << "\n";

236 llvm::report_fatal_error("Replacement failed");

237 }

238}

239

240}

241}

static std::string toString(const clang::SanitizerSet &Sanitizers)

Produce a string containing comma-separated names of sanitizers in Sanitizers set.

Defines the clang::SourceLocation class and associated facilities.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

Represents a character-granular source range.

static CharSourceRange getTokenRange(SourceRange R)

IfStmt - This represents an if/then/else.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)

Returns a string for the source that the range encompasses.

This class handles loading and caching of source files into memory.

Stmt - This represents one statement.

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch)

Definition RefactoringCallbacks.cpp:122

void run(const ast_matchers::MatchFinder::MatchResult &Result) override

Called on every match by the MatchFinder.

Definition RefactoringCallbacks.cpp:126

ReplaceStmtWithText(StringRef FromId, StringRef ToText)

Definition RefactoringCallbacks.cpp:85

void run(const ast_matchers::MatchFinder::MatchResult &Result) override

Called on every match by the MatchFinder.

Definition RefactoringCallbacks.cpp:88

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

@ Template

We are parsing a template declaration.

Contains all information for a given match.