MCPcopy Create free account
hub / github.com/clice-io/clice / complete_include_path

Function complete_include_path

src/syntax/completion.cpp:66–119  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

64bool follows_access_operator(llvm::StringRef text, std::uint32_t offset) {
65 auto before = text.take_front(offset);
66 if(before.ends_with("::")) {
67 return true;
68 }
69 /// `x-->y` is a postfix decrement followed by `>`.
70 if(before.ends_with("->")) {
71 return !before.ends_with("-->");
72 }
73 if(!before.ends_with(".") || before.ends_with("..")) {
74 return false;
75 }
76 /// A dot right after a numeric literal continues the literal (`3.`).
77 auto operand = before.drop_back(1);
78 auto start = operand.size();
79 while(start > 0 && is_identifier_char(operand[start - 1])) {
80 start -= 1;
81 }
82 return start == operand.size() || !clang::isDigit(operand[start]);
83}
84
85PreambleCompletionContext detect_completion_context(llvm::StringRef text, std::uint32_t offset) {
86 // TODO: cache newline offsets from incremental text updates to avoid
87 // the linear line-boundary scans on every completion trigger.
88 //
89 // The full (NUL-terminated) text is lexed and the cursor applies as a
90 // logical bound: a keyword must end at or before it to count as typed.
91 auto lexer = Lexer::from_line(text, offset);
92 auto before_cursor = [&](const Token& token) {
93 return token.range.end <= offset;
94 };
95
96 auto first = lexer.advance();
97
98 if(first.is_directive_hash() && before_cursor(first)) {
99 auto keyword = lexer.advance();
100 if(!keyword.is_identifier() || !before_cursor(keyword) || keyword.text(text) != "include") {
101 return {};
102 }
103 // The argument is likely half-typed, so its prefix is taken
104 // textually between the keyword token and the cursor.
105 auto argument = text.slice(keyword.range.end, offset).ltrim();
106 CompletionContext kind;
107 if(argument.consume_front("\"")) {
108 kind = CompletionContext::IncludeQuoted;
109 } else if(argument.consume_front("<")) {
110 kind = CompletionContext::IncludeAngled;
111 } else {
112 return {};
113 }
114 auto slash = argument.rfind('/');
115 auto component = slash == llvm::StringRef::npos ? argument : argument.drop_front(slash + 1);
116 // A closed directive may name a file with spaces; an unclosed one
117 // ends its name at the first space.
118 char closer = kind == CompletionContext::IncludeQuoted ? '"' : '>';
119 auto line = text.slice(offset, text.find_first_of("\r\n", offset));
120 bool closed = line.contains(closer);
121 auto end = offset;
122 while(end < offset + line.size() && text[end] != '/' && text[end] != closer &&

Callers 1

completionMethod · 0.85

Calls 2

resolve_dirFunction · 0.85
emptyMethod · 0.45

Tested by

no test coverage detected