1*e5dd7070Spatrick //===- ARCMigrate.cpp - Clang-C ARC Migration Library ---------------------===//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick // This file implements the main API hooks in the Clang-C ARC Migration library.
10*e5dd7070Spatrick //
11*e5dd7070Spatrick //===----------------------------------------------------------------------===//
12*e5dd7070Spatrick
13*e5dd7070Spatrick #include "clang-c/Index.h"
14*e5dd7070Spatrick #include "CXString.h"
15*e5dd7070Spatrick #include "clang/ARCMigrate/ARCMT.h"
16*e5dd7070Spatrick #include "clang/Config/config.h"
17*e5dd7070Spatrick #include "clang/Frontend/TextDiagnosticBuffer.h"
18*e5dd7070Spatrick #include "llvm/Support/FileSystem.h"
19*e5dd7070Spatrick
20*e5dd7070Spatrick using namespace clang;
21*e5dd7070Spatrick using namespace arcmt;
22*e5dd7070Spatrick
23*e5dd7070Spatrick namespace {
24*e5dd7070Spatrick
25*e5dd7070Spatrick struct Remap {
26*e5dd7070Spatrick std::vector<std::pair<std::string, std::string> > Vec;
27*e5dd7070Spatrick };
28*e5dd7070Spatrick
29*e5dd7070Spatrick } // anonymous namespace.
30*e5dd7070Spatrick
31*e5dd7070Spatrick //===----------------------------------------------------------------------===//
32*e5dd7070Spatrick // libClang public APIs.
33*e5dd7070Spatrick //===----------------------------------------------------------------------===//
34*e5dd7070Spatrick
clang_getRemappings(const char * migrate_dir_path)35*e5dd7070Spatrick CXRemapping clang_getRemappings(const char *migrate_dir_path) {
36*e5dd7070Spatrick #if !CLANG_ENABLE_ARCMT
37*e5dd7070Spatrick llvm::errs() << "error: feature not enabled in this build\n";
38*e5dd7070Spatrick return nullptr;
39*e5dd7070Spatrick #else
40*e5dd7070Spatrick bool Logging = ::getenv("LIBCLANG_LOGGING");
41*e5dd7070Spatrick
42*e5dd7070Spatrick if (!migrate_dir_path) {
43*e5dd7070Spatrick if (Logging)
44*e5dd7070Spatrick llvm::errs() << "clang_getRemappings was called with NULL parameter\n";
45*e5dd7070Spatrick return nullptr;
46*e5dd7070Spatrick }
47*e5dd7070Spatrick
48*e5dd7070Spatrick if (!llvm::sys::fs::exists(migrate_dir_path)) {
49*e5dd7070Spatrick if (Logging) {
50*e5dd7070Spatrick llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path
51*e5dd7070Spatrick << "\")\n";
52*e5dd7070Spatrick llvm::errs() << "\"" << migrate_dir_path << "\" does not exist\n";
53*e5dd7070Spatrick }
54*e5dd7070Spatrick return nullptr;
55*e5dd7070Spatrick }
56*e5dd7070Spatrick
57*e5dd7070Spatrick TextDiagnosticBuffer diagBuffer;
58*e5dd7070Spatrick std::unique_ptr<Remap> remap(new Remap());
59*e5dd7070Spatrick
60*e5dd7070Spatrick bool err = arcmt::getFileRemappings(remap->Vec, migrate_dir_path,&diagBuffer);
61*e5dd7070Spatrick
62*e5dd7070Spatrick if (err) {
63*e5dd7070Spatrick if (Logging) {
64*e5dd7070Spatrick llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path
65*e5dd7070Spatrick << "\")\n";
66*e5dd7070Spatrick for (TextDiagnosticBuffer::const_iterator
67*e5dd7070Spatrick I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I)
68*e5dd7070Spatrick llvm::errs() << I->second << '\n';
69*e5dd7070Spatrick }
70*e5dd7070Spatrick return nullptr;
71*e5dd7070Spatrick }
72*e5dd7070Spatrick
73*e5dd7070Spatrick return remap.release();
74*e5dd7070Spatrick #endif
75*e5dd7070Spatrick }
76*e5dd7070Spatrick
clang_getRemappingsFromFileList(const char ** filePaths,unsigned numFiles)77*e5dd7070Spatrick CXRemapping clang_getRemappingsFromFileList(const char **filePaths,
78*e5dd7070Spatrick unsigned numFiles) {
79*e5dd7070Spatrick #if !CLANG_ENABLE_ARCMT
80*e5dd7070Spatrick llvm::errs() << "error: feature not enabled in this build\n";
81*e5dd7070Spatrick return nullptr;
82*e5dd7070Spatrick #else
83*e5dd7070Spatrick bool Logging = ::getenv("LIBCLANG_LOGGING");
84*e5dd7070Spatrick
85*e5dd7070Spatrick std::unique_ptr<Remap> remap(new Remap());
86*e5dd7070Spatrick
87*e5dd7070Spatrick if (numFiles == 0) {
88*e5dd7070Spatrick if (Logging)
89*e5dd7070Spatrick llvm::errs() << "clang_getRemappingsFromFileList was called with "
90*e5dd7070Spatrick "numFiles=0\n";
91*e5dd7070Spatrick return remap.release();
92*e5dd7070Spatrick }
93*e5dd7070Spatrick
94*e5dd7070Spatrick if (!filePaths) {
95*e5dd7070Spatrick if (Logging)
96*e5dd7070Spatrick llvm::errs() << "clang_getRemappingsFromFileList was called with "
97*e5dd7070Spatrick "NULL filePaths\n";
98*e5dd7070Spatrick return nullptr;
99*e5dd7070Spatrick }
100*e5dd7070Spatrick
101*e5dd7070Spatrick TextDiagnosticBuffer diagBuffer;
102*e5dd7070Spatrick SmallVector<StringRef, 32> Files(filePaths, filePaths + numFiles);
103*e5dd7070Spatrick
104*e5dd7070Spatrick bool err = arcmt::getFileRemappingsFromFileList(remap->Vec, Files,
105*e5dd7070Spatrick &diagBuffer);
106*e5dd7070Spatrick
107*e5dd7070Spatrick if (err) {
108*e5dd7070Spatrick if (Logging) {
109*e5dd7070Spatrick llvm::errs() << "Error by clang_getRemappingsFromFileList\n";
110*e5dd7070Spatrick for (TextDiagnosticBuffer::const_iterator
111*e5dd7070Spatrick I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I)
112*e5dd7070Spatrick llvm::errs() << I->second << '\n';
113*e5dd7070Spatrick }
114*e5dd7070Spatrick return remap.release();
115*e5dd7070Spatrick }
116*e5dd7070Spatrick
117*e5dd7070Spatrick return remap.release();
118*e5dd7070Spatrick #endif
119*e5dd7070Spatrick }
120*e5dd7070Spatrick
clang_remap_getNumFiles(CXRemapping map)121*e5dd7070Spatrick unsigned clang_remap_getNumFiles(CXRemapping map) {
122*e5dd7070Spatrick return static_cast<Remap *>(map)->Vec.size();
123*e5dd7070Spatrick
124*e5dd7070Spatrick }
125*e5dd7070Spatrick
clang_remap_getFilenames(CXRemapping map,unsigned index,CXString * original,CXString * transformed)126*e5dd7070Spatrick void clang_remap_getFilenames(CXRemapping map, unsigned index,
127*e5dd7070Spatrick CXString *original, CXString *transformed) {
128*e5dd7070Spatrick if (original)
129*e5dd7070Spatrick *original = cxstring::createDup(
130*e5dd7070Spatrick static_cast<Remap *>(map)->Vec[index].first);
131*e5dd7070Spatrick if (transformed)
132*e5dd7070Spatrick *transformed = cxstring::createDup(
133*e5dd7070Spatrick static_cast<Remap *>(map)->Vec[index].second);
134*e5dd7070Spatrick }
135*e5dd7070Spatrick
clang_remap_dispose(CXRemapping map)136*e5dd7070Spatrick void clang_remap_dispose(CXRemapping map) {
137*e5dd7070Spatrick delete static_cast<Remap *>(map);
138*e5dd7070Spatrick }
139