diff --git a/cpp/Completer.cpp b/cpp/Completer.cpp index f5f1f334..bde4b29e 100644 --- a/cpp/Completer.cpp +++ b/cpp/Completer.cpp @@ -17,33 +17,51 @@ #include "standard.h" #include "Completer.h" +#include "Utils.h" namespace YouCompleteMe { Completer::Completer( const Pylist &candidates ) { - AddCandidatesToDatabase( candidates ); + AddCandidatesToDatabase( candidates, "" ); } + +Completer::Completer( const Pylist &candidates, const std::string &filepath) +{ + AddCandidatesToDatabase( candidates, filepath ); +} + + Completer::~Completer() { - foreach ( Candidate* candidate, candidates_ ) + foreach ( const CandidateRepository::value_type &pair, + candidate_repository_ ) { - delete candidate; + delete pair.second; } } -void Completer::AddCandidatesToDatabase( - const Pylist &candidates ) + +void Completer::AddCandidatesToDatabase( const Pylist &candidates, + const std::string &filepath ) { + std::string candidate_text; for (int i = 0; i < boost::python::len( candidates ); ++i) { - candidates_.insert( new Candidate( - boost::python::extract< std::string >( candidates[ i ] ) ) ); + candidate_text = boost::python::extract< std::string >( candidates[ i ] ); + Candidate *&candidate = GetValueElseInsert( candidate_repository_, + candidate_text, NULL ); + if ( !candidate ) + { + candidate = new Candidate( candidate_text ); + candidates_.insert( candidate ); + } } } + void Completer::GetCandidatesForQuery( const std::string &query, Pylist &candidates ) const { @@ -70,4 +88,5 @@ void Completer::GetCandidatesForQuery( } } + } // namespace YouCompleteMe diff --git a/cpp/Completer.h b/cpp/Completer.h index 94b690bb..c6528421 100644 --- a/cpp/Completer.h +++ b/cpp/Completer.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -31,6 +32,7 @@ namespace YouCompleteMe { typedef boost::python::list Pylist; +typedef boost::unordered_map< std::string, Candidate* > CandidateRepository; // class Completer : boost::noncopyable class Completer @@ -38,9 +40,11 @@ class Completer public: Completer() {} Completer( const Pylist &candidates ); + Completer( const Pylist &candidates, const std::string &filepath ); ~Completer(); - void AddCandidatesToDatabase( const Pylist &candidates ); + void AddCandidatesToDatabase( const Pylist &candidates, + const std::string &filepath ); void GetCandidatesForQuery( const std::string &query, Pylist &candidates ) const; @@ -54,6 +58,7 @@ private: } }; + CandidateRepository candidate_repository_; std::set< Candidate*, CandidatePointerLess > candidates_; }; diff --git a/cpp/Utils.h b/cpp/Utils.h index 95fd34b7..e02fd419 100644 --- a/cpp/Utils.h +++ b/cpp/Utils.h @@ -27,6 +27,22 @@ namespace YouCompleteMe bool AlmostEqual( double a, double b ); +template +typename Container::mapped_type & +GetValueElseInsert( Container &container, + Key const& key, + typename Container::mapped_type const& value ) +{ + return container.insert( typename Container::value_type( key, value ) ) + .first->second; +} + +template +bool ContainsKey( Container &container, Key const& key) +{ + return container.find( key ) != container.end(); +} + } // namespace YouCompleteMe #endif /* end of include guard: UTILS_H_KEPMRPBH */ diff --git a/python/ycm.py b/python/ycm.py index 367a673d..e5eac7cd 100644 --- a/python/ycm.py +++ b/python/ycm.py @@ -35,10 +35,11 @@ class CompletionSystem( object ): def AddBufferIdentifiers( self ): text = "\n".join( vim.current.buffer ) - text = RemoveCppComments( text ) + text = RemoveIdentFreeText( text ) idents = re.findall( self.pattern, text ) - self.completer.AddCandidatesToDatabase( idents ) + filepath = vim.eval( "expand('%:p')" ) + self.completer.AddCandidatesToDatabase( idents, filepath ) def CurrentColumn(): # vim's columns start at 1 while vim.current.line columns start at 0 @@ -74,7 +75,10 @@ def CurrentCursorText(): def SanitizeQuery( query ): return query.strip() -def RemoveCppComments( text ): +def RemoveIdentFreeText( text ): + """Removes commented-out code and code in quotes.""" + + # TODO: do we still need this sub-func? def replacer( match ): s = match.group( 0 ) if s.startswith( '/' ): @@ -83,7 +87,7 @@ def RemoveCppComments( text ): return s pattern = re.compile( - r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', + r'//.*?$|#.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) return re.sub( pattern, replacer, text )