1
+ /*
2
+ * This file is part of arduino-preprocessor.
3
+ *
4
+ * Copyright 2017 BCMI LABS SA
5
+ *
6
+ * arduino-preprocessor is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ *
20
+ * As a special exception, you may use this file as part of a free software
21
+ * library without restriction. Specifically, if other files instantiate
22
+ * templates or use macros or inline functions from this file, or you compile
23
+ * this file and link it with other files to produce an executable, this
24
+ * file does not by itself cause the resulting executable to be covered by
25
+ * the GNU General Public License. This exception does not however
26
+ * invalidate any other reasons why the executable file might be covered by
27
+ * the GNU General Public License.
28
+ */
29
+
30
+ #include < clang/Basic/TargetInfo.h>
31
+ #include < clang/Frontend/CompilerInstance.h>
32
+ #include < clang/Frontend/FrontendOptions.h>
33
+ #include < clang/Frontend/FrontendActions.h>
34
+ #include < clang/Lex/Preprocessor.h>
35
+ #include < clang/Lex/PreprocessorOptions.h>
36
+ #include < clang/Sema/Sema.h>
37
+ #include < clang/Sema/CodeCompleteOptions.h>
38
+ #include < clang/Sema/CodeCompleteConsumer.h>
39
+
40
+ #include < iostream>
41
+
42
+ #include " CommandLine.hpp"
43
+ #include " utils.hpp"
44
+
45
+ using namespace clang ;
46
+ using namespace llvm ;
47
+ using namespace std ;
48
+
49
+ class CustomCodeCompleteConsumer : public CodeCompleteConsumer {
50
+ CodeCompletionTUInfo TUInfo;
51
+
52
+ public:
53
+
54
+ CustomCodeCompleteConsumer (const CodeCompleteOptions &opts) : CodeCompleteConsumer(opts, false ),
55
+ TUInfo (std::make_shared<GlobalCodeCompletionAllocator>()) {
56
+ }
57
+
58
+ void ProcessCodeCompleteResults (Sema &s, CodeCompletionContext ctx, CodeCompletionResult *res, unsigned n) override {
59
+
60
+ }
61
+
62
+ /*
63
+ void ProcessOverloadCandidates(Sema &s, unsigned currArg, OverloadCandidate *candidates, unsigned n) {
64
+ }
65
+ */
66
+
67
+ virtual CodeCompletionAllocator &getAllocator () override {
68
+ return TUInfo.getAllocator ();
69
+ }
70
+
71
+ virtual CodeCompletionTUInfo &getCodeCompletionTUInfo () override {
72
+ return TUInfo;
73
+ }
74
+ };
75
+
76
+ int FindRealLineForCodeCompletion (string &code, string &filename, int line) {
77
+ int curr = 0 ;
78
+ int real = 0 ;
79
+ bool inFile = false ;
80
+ for (string &l : split (code, ' \n ' )) {
81
+ real++;
82
+ curr++;
83
+ if (startsWith (l, " # " ) || startsWith (l, " #line " )) {
84
+ vector<string> fields = split (l, ' ' );
85
+ int marker;
86
+ if (stringToInt (fields[1 ], &marker)) {
87
+ curr = marker;
88
+ }
89
+ if (fields[2 ].find (filename) != string::npos) {
90
+ inFile = true ;
91
+ } else {
92
+ inFile = false ;
93
+ }
94
+ }
95
+
96
+ if (inFile && curr == line) {
97
+ if (debugOutput) {
98
+ cerr << " Code-completions at line " << real << " \n " ;
99
+ }
100
+ return real;
101
+ }
102
+ }
103
+
104
+ // Not found... fallback to input line
105
+ if (debugOutput) {
106
+ cerr << " Sorry! source code line not found...\n " ;
107
+ }
108
+ return -1 ;
109
+ }
110
+
111
+ void DoCodeCompletion (const string &filename, const string &code, int line, int col) {
112
+ CompilerInstance ci;
113
+ ci.createDiagnostics ();
114
+
115
+ // Hide diagnostics
116
+ ci.getDiagnostics ().setClient (new IgnoringDiagConsumer ());
117
+
118
+ shared_ptr<clang::TargetOptions> tOpts = make_shared<clang::TargetOptions>();
119
+ tOpts->Triple = sys::getDefaultTargetTriple ();
120
+ ci.setTarget (TargetInfo::CreateTargetInfo (ci.getDiagnostics (), tOpts));
121
+
122
+ LangOptions &lOpts = ci.getLangOpts ();
123
+ lOpts.CPlusPlus = true ;
124
+ lOpts.CPlusPlus11 = true ;
125
+ lOpts.Bool = true ;
126
+ lOpts.GNUMode = true ;
127
+
128
+ CodeCompleteOptions ccOpts;
129
+ ccOpts.IncludeMacros = 1 ;
130
+ ccOpts.IncludeCodePatterns = 1 ;
131
+ ccOpts.IncludeGlobals = 1 ;
132
+ ccOpts.IncludeBriefComments = 1 ;
133
+ ci.setCodeCompletionConsumer (new CustomCodeCompleteConsumer (ccOpts));
134
+
135
+ FrontendOptions& fOpts = ci.getFrontendOpts ();
136
+ fOpts .Inputs .push_back (FrontendInputFile (filename, InputKind::IK_CXX));
137
+ fOpts .CodeCompletionAt .FileName = filename;
138
+ fOpts .CodeCompletionAt .Line = line;
139
+ fOpts .CodeCompletionAt .Column = col;
140
+
141
+ unique_ptr<MemoryBuffer> buff (MemoryBuffer::getMemBuffer (code, filename));
142
+
143
+ PreprocessorOptions& pOpts = ci.getPreprocessorOpts ();
144
+ pOpts.clearRemappedFiles ();
145
+ pOpts.addRemappedFile (filename, buff.release ());
146
+
147
+ SyntaxOnlyAction action;
148
+ if (action.BeginSourceFile (ci, ci.getFrontendOpts ().Inputs [0 ])) {
149
+ action.Execute ();
150
+ action.EndSourceFile ();
151
+ }
152
+ }
0 commit comments