diff --git a/include/AST/ParsedAST.h b/include/AST/ParsedAST.h index 0ea733ee..98dd4de5 100644 --- a/include/AST/ParsedAST.h +++ b/include/AST/ParsedAST.h @@ -5,6 +5,7 @@ namespace clice { struct ParsedAST { + clang::FileManager& fm; clang::Preprocessor& pp; clang::SourceManager& sm; clang::ASTContext& context; diff --git a/include/Feature/SemanticTokens.h b/include/Feature/SemanticTokens.h new file mode 100644 index 00000000..6484e19e --- /dev/null +++ b/include/Feature/SemanticTokens.h @@ -0,0 +1,3 @@ +#pragma once + +namespace clice::feature {} diff --git a/src/AST/ParsedAST.cpp b/src/AST/ParsedAST.cpp index 109dd1d4..5067aa27 100644 --- a/src/AST/ParsedAST.cpp +++ b/src/AST/ParsedAST.cpp @@ -62,6 +62,7 @@ std::unique_ptr ParsedAST::build(llvm::StringRef filename, } auto result = new ParsedAST{ + .fm = instance->getFileManager(), .pp = instance->getPreprocessor(), .sm = instance->getSourceManager(), .context = instance->getASTContext(), diff --git a/src/Feature/SemanticTokens.cpp b/src/Feature/SemanticTokens.cpp new file mode 100644 index 00000000..c3a18a96 --- /dev/null +++ b/src/Feature/SemanticTokens.cpp @@ -0,0 +1,162 @@ +#include "AST/ParsedAST.h" +#include "Feature/SemanticTokens.h" + +namespace clice::feature { + +namespace { + +#define Traverse(NAME) bool Traverse##NAME(clang::NAME* node) +#define WalkUpFrom(NAME) bool WalkUpFrom##NAME(clang::NAME* node) +#define VISIT(NAME) bool Visit##NAME(clang::NAME* node) +#define VISIT_TYPE(NAME) bool Visit##NAME(clang::NAME node) + +class SemanticToken {}; + +class Highlighter : public clang::RecursiveASTVisitor { +public: + Highlighter(ParsedAST& ast) : fm(ast.fm), pp(ast.pp), sm(ast.sm), context(ast.context), tb(ast.tb) {} + + std::vector highlight(llvm::StringRef filepath) { + std::vector result; + + auto entry = fm.getFileRef(filepath); + if(auto error = entry.takeError()) { + // TODO: + } + auto fileID = sm.translateFile(entry.get()); + + this->fileID = fileID; + this->result = &result; + + // highlight from tokens + // TODO: use TokenBuffer to get tokens + + // TODO: highlight from directive + + // highlight from AST + TraverseDecl(context.getTranslationUnitDecl()); + + return {}; + } + +private: + void addAngle(clang::SourceLocation left, clang::SourceLocation right) {} + +public: + Traverse(TranslationUnitDecl) { + for(auto decl: node->decls()) { + // we only need to highlight the token in main file. + // so filter out the nodes which are in headers for better performance. + if(sm.isInFileID(decl->getLocation(), fileID)) { + TraverseDecl(decl); + } + } + return true; + } + + WalkUpFrom(NamespaceDecl) {} + + VISIT(DeclaratorDecl) { + for(unsigned i = 0; i < node->getNumTemplateParameterLists(); ++i) { + if(auto params = node->getTemplateParameterList(i)) { + addAngle(params->getLAngleLoc(), params->getRAngleLoc()); + } + } + return true; + } + + VISIT(TagDecl) { + for(unsigned i = 0; i < node->getNumTemplateParameterLists(); ++i) { + if(auto params = node->getTemplateParameterList(i)) { + addAngle(params->getLAngleLoc(), params->getRAngleLoc()); + } + } + return true; + } + + VISIT(FunctionDecl) { + if(auto args = node->getTemplateSpecializationArgsAsWritten()) { + addAngle(args->getLAngleLoc(), args->getRAngleLoc()); + } + return true; + } + + VISIT(TemplateDecl) { + if(auto params = node->getTemplateParameters()) { + addAngle(params->getLAngleLoc(), params->getRAngleLoc()); + } + return true; + } + + VISIT(ClassTemplateSpecializationDecl) { + if(auto args = node->getTemplateArgsAsWritten()) { + addAngle(args->getLAngleLoc(), args->getRAngleLoc()); + } + return true; + } + + VISIT(ClassTemplatePartialSpecializationDecl) { + if(auto params = node->getTemplateParameters()) { + addAngle(params->getLAngleLoc(), params->getRAngleLoc()); + } + return true; + } + + VISIT(VarTemplateSpecializationDecl) { + if(auto args = node->getTemplateArgsAsWritten()) { + addAngle(args->LAngleLoc, args->RAngleLoc); + } + return true; + } + + VISIT(VarTemplatePartialSpecializationDecl) { + if(auto params = node->getTemplateParameters()) { + addAngle(params->getLAngleLoc(), params->getRAngleLoc()); + } + return true; + } + + VISIT(CXXNamedCastExpr) { + addAngle(node->getAngleBrackets().getBegin(), node->getAngleBrackets().getEnd()); + return true; + } + + VISIT(OverloadExpr) { + addAngle(node->getLAngleLoc(), node->getRAngleLoc()); + return true; + } + + VISIT(CXXDependentScopeMemberExpr) { + addAngle(node->getLAngleLoc(), node->getRAngleLoc()); + return true; + } + + VISIT(DependentScopeDeclRefExpr) { + addAngle(node->getLAngleLoc(), node->getRAngleLoc()); + return true; + } + + VISIT_TYPE(TemplateSpecializationTypeLoc) { + addAngle(node.getLAngleLoc(), node.getRAngleLoc()); + return true; + } + + VISIT_TYPE(DependentTemplateSpecializationTypeLoc) { + addAngle(node.getLAngleLoc(), node.getRAngleLoc()); + return true; + } + +private: + clang::FileManager& fm; + clang::Preprocessor& pp; + clang::SourceManager& sm; + clang::ASTContext& context; + clang::syntax::TokenBuffer& tb; + + clang::FileID fileID; + std::vector* result; +}; + +} // namespace + +} // namespace clice::feature