Skip to content

Commit 5e7d18a

Browse files
committed
chore: Add APIs to request code completion at a specific location
Signed-off-by: Roberto Raggi <[email protected]>
1 parent a754ac8 commit 5e7d18a

File tree

2 files changed

+59
-17
lines changed

2 files changed

+59
-17
lines changed

src/parser/cxx/preprocessor.cc

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -637,24 +637,37 @@ struct SourceFile {
637637
initLineMap();
638638
}
639639

640-
void getTokenStartPosition(unsigned offset, unsigned *line, unsigned *column,
641-
std::string_view *fileName) const {
640+
[[nodiscard]] auto getTokenStartPosition(unsigned offset) const
641+
-> SourcePosition {
642642
auto it = std::lower_bound(lines.cbegin(), lines.cend(),
643643
static_cast<int>(offset));
644644
if (*it != static_cast<int>(offset)) --it;
645645

646646
assert(*it <= int(offset));
647647

648-
if (line) *line = int(std::distance(cbegin(lines), it) + 1);
648+
auto line = std::uint32_t(std::distance(cbegin(lines), it) + 1);
649649

650-
if (column) {
651-
const auto start = cbegin(source) + *it;
652-
const auto end = cbegin(source) + offset;
650+
const auto start = cbegin(source) + *it;
651+
const auto end = cbegin(source) + offset;
653652

654-
*column = utf8::unchecked::distance(start, end) + 1;
655-
}
653+
const auto column =
654+
std::uint32_t(utf8::unchecked::distance(start, end) + 1);
656655

657-
if (fileName) *fileName = this->fileName;
656+
return SourcePosition{fileName, line, column};
657+
}
658+
659+
[[nodiscard]] auto offsetAt(std::uint32_t line, std::uint32_t column) const
660+
-> std::uint32_t {
661+
if (line == 0 && column == 0) return 0;
662+
if (line > lines.size()) return static_cast<std::uint32_t>(source.size());
663+
const auto start = source.data();
664+
const auto end = start + source.size();
665+
const auto offsetOfTheLine = lines[line - 1];
666+
auto it = start + offsetOfTheLine;
667+
for (std::uint32_t i = 1; i < column; ++i) {
668+
utf8::unchecked::next(it);
669+
}
670+
return static_cast<std::uint32_t>(it - start);
658671
}
659672

660673
private:
@@ -713,6 +726,8 @@ struct Preprocessor::Private {
713726
};
714727
std::vector<Dep> dependencies_;
715728
std::function<auto()->std::optional<PreprocessingState>> continuation_;
729+
std::optional<SourcePosition> codeCompletionLocation_;
730+
std::uint32_t codeCompletionOffset_ = 0;
716731
int localCount_ = 0;
717732

718733
int counter_ = 0;
@@ -1593,6 +1608,18 @@ void Preprocessor::Private::finalizeToken(std::vector<Token> &tokens,
15931608
const auto fileId = tk->sourceFile;
15941609
TokenValue value{};
15951610

1611+
if (tk->sourceFile == 1 && codeCompletionLocation_.has_value()) {
1612+
if (codeCompletionOffset_ < tk->offset ||
1613+
(codeCompletionOffset_ >= tk->offset &&
1614+
codeCompletionOffset_ < tk->offset + tk->length)) {
1615+
auto &completionToken =
1616+
tokens.emplace_back(TokenKind::T_CODE_COMPLETION, tk->offset, 0);
1617+
completionToken.setFileId(fileId);
1618+
1619+
codeCompletionLocation_ = std::nullopt;
1620+
}
1621+
}
1622+
15961623
switch (tk->kind) {
15971624
case TokenKind::T_IDENTIFIER: {
15981625
kind = Lexer::classifyKeyword(tk->text);
@@ -2987,6 +3014,10 @@ void Preprocessor::beginPreprocessing(std::string source, std::string fileName,
29873014
if (tokens.empty()) {
29883015
tokens.emplace_back(TokenKind::T_ERROR);
29893016
}
3017+
3018+
if (auto loc = d->codeCompletionLocation_) {
3019+
d->codeCompletionOffset_ = sourceFile->offsetAt(loc->line, loc->column);
3020+
}
29903021
}
29913022

29923023
void Preprocessor::endPreprocessing(std::vector<Token> &tokens) {
@@ -3002,6 +3033,16 @@ void Preprocessor::endPreprocessing(std::vector<Token> &tokens) {
30023033

30033034
// place the EOF token at the end of the main source file
30043035
const auto offset = d->sourceFiles_[mainSourceFileId - 1]->source.size();
3036+
3037+
if (d->codeCompletionLocation_.has_value()) {
3038+
auto sourceFile = d->sourceFiles_[0].get();
3039+
3040+
auto &tk = tokens.emplace_back(TokenKind::T_CODE_COMPLETION, offset, 0);
3041+
tk.setFileId(mainSourceFileId);
3042+
3043+
d->codeCompletionLocation_ = std::nullopt;
3044+
}
3045+
30053046
auto &tk = tokens.emplace_back(TokenKind::T_EOF_SYMBOL, offset);
30063047
tk.setFileId(mainSourceFileId);
30073048
}
@@ -3165,10 +3206,7 @@ auto Preprocessor::tokenStartPosition(const Token &token) const
31653206
}
31663207

31673208
auto &sourceFile = *d->sourceFiles_[token.fileId() - 1];
3168-
SourcePosition pos;
3169-
sourceFile.getTokenStartPosition(token.offset(), &pos.line, &pos.column,
3170-
&pos.fileName);
3171-
return pos;
3209+
return sourceFile.getTokenStartPosition(token.offset());
31723210
}
31733211

31743212
auto Preprocessor::tokenEndPosition(const Token &token) const
@@ -3179,10 +3217,7 @@ auto Preprocessor::tokenEndPosition(const Token &token) const
31793217

31803218
auto &sourceFile = *d->sourceFiles_[token.fileId() - 1];
31813219

3182-
SourcePosition pos;
3183-
sourceFile.getTokenStartPosition(token.offset() + token.length(), &pos.line,
3184-
&pos.column, &pos.fileName);
3185-
return pos;
3220+
return sourceFile.getTokenStartPosition(token.offset() + token.length());
31863221
}
31873222

31883223
auto Preprocessor::getTextLine(const Token &token) const -> std::string_view {
@@ -3215,6 +3250,11 @@ auto Preprocessor::resolve(const Include &include, bool isIncludeNext) const
32153250
return d->resolve(include, isIncludeNext);
32163251
}
32173252

3253+
void Preprocessor::requestCodeCompletionAt(std::uint32_t line,
3254+
std::uint32_t column) {
3255+
d->codeCompletionLocation_ = SourcePosition{{}, line, column};
3256+
}
3257+
32183258
void DefaultPreprocessorState::operator()(const ProcessingComplete &) {
32193259
done = true;
32203260
}

src/parser/cxx/preprocessor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class Preprocessor {
115115
[[nodiscard]] auto resolve(const Include &include, bool isIncludeNext) const
116116
-> std::optional<std::string>;
117117

118+
void requestCodeCompletionAt(std::uint32_t line, std::uint32_t column);
119+
118120
void squeeze();
119121

120122
private:

0 commit comments

Comments
 (0)