|
|
|
|
@ -367,6 +367,25 @@ void Source::ClangViewParse::update_diagnostics() {
|
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
}; |
|
|
|
|
auto add_include_fixit = [this, &diagnostic, &get_new_include_offsets](bool has_std, bool has_using_std, const std::string &token) { |
|
|
|
|
auto headers = Documentation::CppReference::get_headers(has_std || has_using_std ? "std::" + token : token); |
|
|
|
|
if(headers.empty() && !has_std && has_using_std) |
|
|
|
|
headers = Documentation::CppReference::get_headers(token); |
|
|
|
|
if(!headers.empty()) { |
|
|
|
|
std::string *c_header = nullptr; |
|
|
|
|
std::string *cpp_header = nullptr; |
|
|
|
|
for(auto &header : headers) { |
|
|
|
|
if(!c_header && header.find(".h") != std::string::npos) |
|
|
|
|
c_header = &header; |
|
|
|
|
else if(!cpp_header) |
|
|
|
|
cpp_header = &header; |
|
|
|
|
} |
|
|
|
|
if(c_header && (is_c || !cpp_header)) |
|
|
|
|
diagnostic.fix_its.emplace_back(clangmm::Diagnostic::FixIt{"#include <" + *c_header + ">\n", file_path.string(), get_new_include_offsets()}); |
|
|
|
|
else if(cpp_header && is_cpp) |
|
|
|
|
diagnostic.fix_its.emplace_back(clangmm::Diagnostic::FixIt{"#include <" + *cpp_header + ">\n", file_path.string(), get_new_include_offsets()}); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
if(diagnostic.fix_its.empty() && diagnostic.severity >= clangmm::Diagnostic::Severity::Error && is_token_char(*start)) { |
|
|
|
|
auto token_string = get_token(start); |
|
|
|
|
for(size_t c = 0; c < clang_tokens->size(); c++) { |
|
|
|
|
@ -379,18 +398,19 @@ void Source::ClangViewParse::update_diagnostics() {
|
|
|
|
|
if(cursor.get_referenced()) { |
|
|
|
|
auto type_description = cursor.get_type_description(); |
|
|
|
|
bool has_std = false; |
|
|
|
|
if(type_description.compare(0, 5, "std::") == 0) { |
|
|
|
|
has_std = true; |
|
|
|
|
type_description.erase(0, 5); |
|
|
|
|
if(is_cpp) { |
|
|
|
|
if(type_description.compare(0, 5, "std::") == 0) { |
|
|
|
|
has_std = true; |
|
|
|
|
type_description.erase(0, 5); |
|
|
|
|
} |
|
|
|
|
if(type_description.compare(0, 5, "__1::") == 0) |
|
|
|
|
type_description.erase(0, 5); |
|
|
|
|
auto pos = type_description.find('<'); |
|
|
|
|
if(pos != std::string::npos) |
|
|
|
|
type_description.erase(pos); |
|
|
|
|
} |
|
|
|
|
if(type_description.compare(0, 5, "__1::") == 0) |
|
|
|
|
type_description.erase(0, 5); |
|
|
|
|
auto pos = type_description.find('<'); |
|
|
|
|
if(pos != std::string::npos) |
|
|
|
|
type_description.erase(pos); |
|
|
|
|
auto header = Documentation::CppReference::get_header(is_cpp && (has_std || has_using_namespace_std(c)) ? "std::" + type_description : type_description); |
|
|
|
|
if(!header.empty()) |
|
|
|
|
diagnostic.fix_its.emplace_back(clangmm::Diagnostic::FixIt{"#include <" + header + ">\n", file_path.string(), get_new_include_offsets()}); |
|
|
|
|
|
|
|
|
|
add_include_fixit(has_std, is_cpp && has_using_namespace_std(c), type_description); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(diagnostic.spelling.compare(0, 17, "unknown type name") == 0 || |
|
|
|
|
@ -401,19 +421,20 @@ void Source::ClangViewParse::update_diagnostics() {
|
|
|
|
|
diagnostic.spelling.compare(0, 44, "implicit instantiation of undefined template") == 0 || |
|
|
|
|
diagnostic.spelling.compare(0, 79, "no viable constructor or deduction guide for deduction of template arguments of") == 0) { |
|
|
|
|
bool has_std = false; |
|
|
|
|
if(token_string == "std" && c + 2 < clang_tokens->size() && (*clang_tokens)[c + 2].get_kind() == clangmm::Token::Kind::Identifier) { |
|
|
|
|
token_string = (*clang_tokens)[c + 2].get_spelling(); |
|
|
|
|
has_std = true; |
|
|
|
|
if(is_cpp) { |
|
|
|
|
if(token_string == "std" && c + 2 < clang_tokens->size() && (*clang_tokens)[c + 2].get_kind() == clangmm::Token::Kind::Identifier) { |
|
|
|
|
token_string = (*clang_tokens)[c + 2].get_spelling(); |
|
|
|
|
has_std = true; |
|
|
|
|
} |
|
|
|
|
else if(c >= 2 && |
|
|
|
|
(*clang_tokens)[c - 1].get_kind() == clangmm::Token::Punctuation && |
|
|
|
|
(*clang_tokens)[c - 2].get_kind() == clangmm::Token::Identifier && |
|
|
|
|
(*clang_tokens)[c - 1].get_spelling() == "::" && |
|
|
|
|
(*clang_tokens)[c - 2].get_spelling() == "std") |
|
|
|
|
has_std = true; |
|
|
|
|
} |
|
|
|
|
else if(c >= 2 && |
|
|
|
|
(*clang_tokens)[c - 1].get_kind() == clangmm::Token::Punctuation && |
|
|
|
|
(*clang_tokens)[c - 2].get_kind() == clangmm::Token::Identifier && |
|
|
|
|
(*clang_tokens)[c - 1].get_spelling() == "::" && |
|
|
|
|
(*clang_tokens)[c - 2].get_spelling() == "std") |
|
|
|
|
has_std = true; |
|
|
|
|
auto header = Documentation::CppReference::get_header(is_cpp && (has_std || has_using_namespace_std(c)) ? "std::" + token_string : token_string); |
|
|
|
|
if(!header.empty()) |
|
|
|
|
diagnostic.fix_its.emplace_back(clangmm::Diagnostic::FixIt{"#include <" + header + ">\n", file_path.string(), get_new_include_offsets()}); |
|
|
|
|
|
|
|
|
|
add_include_fixit(has_std, is_cpp && has_using_namespace_std(c), token_string); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|