Candidates are now stored per type and filepath
This commit is contained in:
parent
ced1d0ad5a
commit
903452e855
@ -19,18 +19,24 @@
|
|||||||
#include "Completer.h"
|
#include "Completer.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using boost::python::len;
|
||||||
|
using boost::python::extract;
|
||||||
|
|
||||||
namespace YouCompleteMe
|
namespace YouCompleteMe
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
Completer::Completer( const Pylist &candidates )
|
Completer::Completer( const Pylist &candidates )
|
||||||
{
|
{
|
||||||
AddCandidatesToDatabase( candidates, "" );
|
AddCandidatesToDatabase( candidates, "", "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Completer::Completer( const Pylist &candidates, const std::string &filepath)
|
Completer::Completer( const Pylist &candidates,
|
||||||
|
const std::string &filetype,
|
||||||
|
const std::string &filepath)
|
||||||
{
|
{
|
||||||
AddCandidatesToDatabase( candidates, filepath );
|
AddCandidatesToDatabase( candidates, filetype, filepath );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -44,43 +50,64 @@ Completer::~Completer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Completer::AddCandidatesToDatabase( const Pylist &candidates,
|
void Completer::AddCandidatesToDatabase( const Pylist &new_candidates,
|
||||||
|
const std::string &filetype,
|
||||||
const std::string &filepath )
|
const std::string &filepath )
|
||||||
{
|
{
|
||||||
|
std::vector< Candidate *> &candidates =
|
||||||
|
GetCandidateVector( filetype, filepath );
|
||||||
|
|
||||||
|
int num_candidates = len( new_candidates );
|
||||||
|
candidates.clear();
|
||||||
|
candidates.reserve( num_candidates );
|
||||||
|
|
||||||
std::string candidate_text;
|
std::string candidate_text;
|
||||||
for (int i = 0; i < boost::python::len( candidates ); ++i)
|
for (int i = 0; i < num_candidates; ++i)
|
||||||
{
|
{
|
||||||
candidate_text = boost::python::extract< std::string >( candidates[ i ] );
|
candidate_text = extract< std::string >( new_candidates[ i ] );
|
||||||
Candidate *&candidate = GetValueElseInsert( candidate_repository_,
|
Candidate *&candidate = GetValueElseInsert( candidate_repository_,
|
||||||
candidate_text, NULL );
|
candidate_text, NULL );
|
||||||
if ( !candidate )
|
if ( !candidate )
|
||||||
{
|
|
||||||
candidate = new Candidate( candidate_text );
|
candidate = new Candidate( candidate_text );
|
||||||
candidates_.insert( candidate );
|
|
||||||
}
|
candidates.push_back( candidate );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Completer::GetCandidatesForQuery(
|
void Completer::CandidatesForQuery( const std::string &query,
|
||||||
const std::string &query, Pylist &candidates ) const
|
Pylist &candidates ) const
|
||||||
{
|
{
|
||||||
|
CandidatesForQueryAndType( query, "", candidates );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Completer::CandidatesForQueryAndType( const std::string &query,
|
||||||
|
const std::string &filetype,
|
||||||
|
Pylist &candidates ) const
|
||||||
|
{
|
||||||
|
FiletypeMap::const_iterator it = filetype_map_.find( filetype );
|
||||||
|
if ( it == filetype_map_.end() )
|
||||||
|
return;
|
||||||
|
|
||||||
Bitset query_bitset = LetterBitsetFromString( query );
|
Bitset query_bitset = LetterBitsetFromString( query );
|
||||||
std::vector< Result > results;
|
std::vector< Result > results;
|
||||||
|
|
||||||
foreach ( Candidate* candidate, candidates_ )
|
foreach ( const FilepathToCandidates::value_type &path_and_candidates,
|
||||||
|
*it->second )
|
||||||
{
|
{
|
||||||
if ( !candidate->MatchesQueryBitset( query_bitset ) )
|
foreach ( Candidate* candidate, *path_and_candidates.second )
|
||||||
continue;
|
{
|
||||||
|
if ( !candidate->MatchesQueryBitset( query_bitset ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
Result result = candidate->QueryMatchResult( query );
|
Result result = candidate->QueryMatchResult( query );
|
||||||
if ( result.IsSubsequence() )
|
if ( result.IsSubsequence() )
|
||||||
results.push_back( result );
|
results.push_back( result );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs to be stable to preserve the lexical sort of the candidates from the
|
std::sort( results.begin(), results.end() );
|
||||||
// candidates_ container
|
|
||||||
std::stable_sort( results.begin(), results.end() );
|
|
||||||
|
|
||||||
foreach ( const Result& result, results )
|
foreach ( const Result& result, results )
|
||||||
{
|
{
|
||||||
@ -89,4 +116,24 @@ void Completer::GetCandidatesForQuery(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector< Candidate* >& Completer::GetCandidateVector(
|
||||||
|
const std::string &filetype,
|
||||||
|
const std::string &filepath )
|
||||||
|
{
|
||||||
|
boost::shared_ptr< FilepathToCandidates > &path_to_candidates =
|
||||||
|
filetype_map_[ filetype ];
|
||||||
|
|
||||||
|
if ( !path_to_candidates )
|
||||||
|
path_to_candidates.reset( new FilepathToCandidates() );
|
||||||
|
|
||||||
|
boost::shared_ptr< std::vector< Candidate* > > &candidates =
|
||||||
|
(*path_to_candidates)[ filepath ];
|
||||||
|
|
||||||
|
if ( !candidates )
|
||||||
|
candidates.reset( new std::vector< Candidate* >() );
|
||||||
|
|
||||||
|
return *candidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace YouCompleteMe
|
} // namespace YouCompleteMe
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
#include <boost/python.hpp>
|
#include <boost/python.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -32,24 +32,49 @@ namespace YouCompleteMe
|
|||||||
{
|
{
|
||||||
|
|
||||||
typedef boost::python::list Pylist;
|
typedef boost::python::list Pylist;
|
||||||
|
|
||||||
|
// candidate text string -> candidate objects
|
||||||
typedef boost::unordered_map< std::string, Candidate* > CandidateRepository;
|
typedef boost::unordered_map< std::string, Candidate* > CandidateRepository;
|
||||||
|
|
||||||
|
// filepath -> *( *candidate )
|
||||||
|
typedef boost::unordered_map< std::string,
|
||||||
|
boost::shared_ptr< std::vector< Candidate* > > > FilepathToCandidates;
|
||||||
|
|
||||||
|
// filetype -> *( filepath -> *( *candidate ) )
|
||||||
|
typedef boost::unordered_map< std::string,
|
||||||
|
boost::shared_ptr< FilepathToCandidates > > FiletypeMap;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: resolve problems with noncopyable
|
||||||
// class Completer : boost::noncopyable
|
// class Completer : boost::noncopyable
|
||||||
class Completer
|
class Completer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Completer() {}
|
Completer() {}
|
||||||
Completer( const Pylist &candidates );
|
Completer( const Pylist &candidates );
|
||||||
Completer( const Pylist &candidates, const std::string &filepath );
|
Completer( const Pylist &candidates,
|
||||||
|
const std::string &filetype,
|
||||||
|
const std::string &filepath );
|
||||||
~Completer();
|
~Completer();
|
||||||
|
|
||||||
void AddCandidatesToDatabase( const Pylist &candidates,
|
void AddCandidatesToDatabase( const Pylist &new_candidates,
|
||||||
|
const std::string &filetype,
|
||||||
const std::string &filepath );
|
const std::string &filepath );
|
||||||
|
|
||||||
void GetCandidatesForQuery(
|
// Only provided for tests!
|
||||||
const std::string &query, Pylist &candidates ) const;
|
void CandidatesForQuery( const std::string &query,
|
||||||
|
Pylist &candidates ) const;
|
||||||
|
|
||||||
|
void CandidatesForQueryAndType( const std::string &query,
|
||||||
|
const std::string &filetype,
|
||||||
|
Pylist &candidates ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
std::vector< Candidate* >& GetCandidateVector(
|
||||||
|
const std::string &filetype,
|
||||||
|
const std::string &filepath );
|
||||||
|
|
||||||
struct CandidatePointerLess
|
struct CandidatePointerLess
|
||||||
{
|
{
|
||||||
bool operator() ( const Candidate *first, const Candidate *second )
|
bool operator() ( const Candidate *first, const Candidate *second )
|
||||||
@ -58,8 +83,10 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This data structure owns all the Candidate pointers
|
||||||
CandidateRepository candidate_repository_;
|
CandidateRepository candidate_repository_;
|
||||||
std::set< Candidate*, CandidatePointerLess > candidates_;
|
|
||||||
|
FiletypeMap filetype_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace YouCompleteMe
|
} // namespace YouCompleteMe
|
||||||
|
@ -27,6 +27,7 @@ namespace YouCompleteMe
|
|||||||
|
|
||||||
bool AlmostEqual( double a, double b );
|
bool AlmostEqual( double a, double b );
|
||||||
|
|
||||||
|
|
||||||
template <class Container, class Key>
|
template <class Container, class Key>
|
||||||
typename Container::mapped_type &
|
typename Container::mapped_type &
|
||||||
GetValueElseInsert( Container &container,
|
GetValueElseInsert( Container &container,
|
||||||
@ -37,6 +38,7 @@ GetValueElseInsert( Container &container,
|
|||||||
.first->second;
|
.first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class Container, class Key>
|
template <class Container, class Key>
|
||||||
bool ContainsKey( Container &container, Key const& key)
|
bool ContainsKey( Container &container, Key const& key)
|
||||||
{
|
{
|
||||||
|
@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
BOOST_PYTHON_MODULE(indexer)
|
BOOST_PYTHON_MODULE(indexer)
|
||||||
{
|
{
|
||||||
using namespace boost::python;
|
using namespace boost::python;
|
||||||
using namespace YouCompleteMe;
|
using namespace YouCompleteMe;
|
||||||
|
|
||||||
class_<Completer>( "Completer" )
|
class_<Completer>( "Completer" )
|
||||||
.def( "AddCandidatesToDatabase", &Completer::AddCandidatesToDatabase )
|
.def( "AddCandidatesToDatabase", &Completer::AddCandidatesToDatabase )
|
||||||
.def( "GetCandidatesForQuery", &Completer::GetCandidatesForQuery );
|
.def( "CandidatesForQueryAndType", &Completer::CandidatesForQueryAndType );
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ class CompleterTest : public ::testing::Test
|
|||||||
TEST_F( CompleterTest, OneCandidate )
|
TEST_F( CompleterTest, OneCandidate )
|
||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates( "foobar" ) ).GetCandidatesForQuery( "fbr", results );
|
Completer( Candidates( "foobar" ) ).CandidatesForQuery( "fbr", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ), ElementsAre( "foobar" ) );
|
EXPECT_THAT( ToStringVector( results ), ElementsAre( "foobar" ) );
|
||||||
}
|
}
|
||||||
@ -98,9 +98,9 @@ TEST_F( CompleterTest, ManyCandidateSimple )
|
|||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"foobar",
|
"foobar",
|
||||||
"foobartest",
|
"foobartest",
|
||||||
"Foobartest" ) ).GetCandidatesForQuery( "fbr", results );
|
"Foobartest" ) ).CandidatesForQuery( "fbr", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ),
|
EXPECT_THAT( ToStringVector( results ),
|
||||||
WhenSorted( ElementsAre( "Foobartest",
|
WhenSorted( ElementsAre( "Foobartest",
|
||||||
@ -112,8 +112,8 @@ TEST_F( CompleterTest, FirstCharSameAsQueryWins )
|
|||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"foobar",
|
"foobar",
|
||||||
"afoobar" ) ).GetCandidatesForQuery( "fbr", results );
|
"afoobar" ) ).CandidatesForQuery( "fbr", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ),
|
EXPECT_THAT( ToStringVector( results ),
|
||||||
ElementsAre( "foobar",
|
ElementsAre( "foobar",
|
||||||
@ -124,8 +124,8 @@ TEST_F( CompleterTest, CompleteMatchForWordBoundaryCharsWins )
|
|||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"FooBarQux",
|
"FooBarQux",
|
||||||
"FBaqux" ) ).GetCandidatesForQuery( "fbq", results );
|
"FBaqux" ) ).CandidatesForQuery( "fbq", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ),
|
EXPECT_THAT( ToStringVector( results ),
|
||||||
ElementsAre( "FooBarQux",
|
ElementsAre( "FooBarQux",
|
||||||
@ -133,9 +133,9 @@ TEST_F( CompleterTest, CompleteMatchForWordBoundaryCharsWins )
|
|||||||
|
|
||||||
Pylist results2;
|
Pylist results2;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"CompleterTest",
|
"CompleterTest",
|
||||||
"CompleteMatchForWordBoundaryCharsWins"
|
"CompleteMatchForWordBoundaryCharsWins"
|
||||||
) ).GetCandidatesForQuery( "ct", results2 );
|
) ).CandidatesForQuery( "ct", results2 );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results2 ),
|
EXPECT_THAT( ToStringVector( results2 ),
|
||||||
ElementsAre( "CompleterTest",
|
ElementsAre( "CompleterTest",
|
||||||
@ -143,9 +143,8 @@ TEST_F( CompleterTest, CompleteMatchForWordBoundaryCharsWins )
|
|||||||
|
|
||||||
Pylist results3;
|
Pylist results3;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"FooBar",
|
"FooBar",
|
||||||
"FooBarRux"
|
"FooBarRux" ) ).CandidatesForQuery( "fbr", results3 );
|
||||||
) ).GetCandidatesForQuery( "fbr", results3 );
|
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results3 ),
|
EXPECT_THAT( ToStringVector( results3 ),
|
||||||
ElementsAre( "FooBarRux",
|
ElementsAre( "FooBarRux",
|
||||||
@ -156,8 +155,8 @@ TEST_F( CompleterTest, RatioUtilizationTieBreak )
|
|||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"FooBarQux",
|
"FooBarQux",
|
||||||
"FooBarQuxZaa" ) ).GetCandidatesForQuery( "fbq", results );
|
"FooBarQuxZaa" ) ).CandidatesForQuery( "fbq", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ),
|
EXPECT_THAT( ToStringVector( results ),
|
||||||
ElementsAre( "FooBarQux",
|
ElementsAre( "FooBarQux",
|
||||||
@ -165,8 +164,8 @@ TEST_F( CompleterTest, RatioUtilizationTieBreak )
|
|||||||
|
|
||||||
Pylist results2;
|
Pylist results2;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"FooBar",
|
"FooBar",
|
||||||
"FooBarRux" ) ).GetCandidatesForQuery( "fba", results2 );
|
"FooBarRux" ) ).CandidatesForQuery( "fba", results2 );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results2 ),
|
EXPECT_THAT( ToStringVector( results2 ),
|
||||||
ElementsAre( "FooBar",
|
ElementsAre( "FooBar",
|
||||||
@ -177,8 +176,8 @@ TEST_F( CompleterTest, QueryPrefixOfCandidateWins )
|
|||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"foobar",
|
"foobar",
|
||||||
"fbaroo" ) ).GetCandidatesForQuery( "foo", results );
|
"fbaroo" ) ).CandidatesForQuery( "foo", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ),
|
EXPECT_THAT( ToStringVector( results ),
|
||||||
ElementsAre( "foobar",
|
ElementsAre( "foobar",
|
||||||
@ -189,8 +188,8 @@ TEST_F( CompleterTest, ShorterCandidateWins )
|
|||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"FooBarQux",
|
"FooBarQux",
|
||||||
"FaBarQux" ) ).GetCandidatesForQuery( "fbq", results );
|
"FaBarQux" ) ).CandidatesForQuery( "fbq", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ),
|
EXPECT_THAT( ToStringVector( results ),
|
||||||
ElementsAre( "FaBarQux",
|
ElementsAre( "FaBarQux",
|
||||||
@ -198,8 +197,8 @@ TEST_F( CompleterTest, ShorterCandidateWins )
|
|||||||
|
|
||||||
Pylist results2;
|
Pylist results2;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"CompleterT",
|
"CompleterT",
|
||||||
"CompleterTest" ) ).GetCandidatesForQuery( "co", results2 );
|
"CompleterTest" ) ).CandidatesForQuery( "co", results2 );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results2 ),
|
EXPECT_THAT( ToStringVector( results2 ),
|
||||||
ElementsAre( "CompleterT",
|
ElementsAre( "CompleterT",
|
||||||
@ -210,8 +209,8 @@ TEST_F( CompleterTest, SameLowercaseCandidateWins )
|
|||||||
{
|
{
|
||||||
Pylist results;
|
Pylist results;
|
||||||
Completer( Candidates(
|
Completer( Candidates(
|
||||||
"foobar",
|
"foobar",
|
||||||
"Foobar" ) ).GetCandidatesForQuery( "foo", results );
|
"Foobar" ) ).CandidatesForQuery( "foo", results );
|
||||||
|
|
||||||
EXPECT_THAT( ToStringVector( results ),
|
EXPECT_THAT( ToStringVector( results ),
|
||||||
ElementsAre( "foobar",
|
ElementsAre( "foobar",
|
||||||
|
@ -30,7 +30,10 @@ class CompletionSystem( object ):
|
|||||||
|
|
||||||
def CompletionCandidatesForQuery( self, query ):
|
def CompletionCandidatesForQuery( self, query ):
|
||||||
candidates = []
|
candidates = []
|
||||||
self.completer.GetCandidatesForQuery( SanitizeQuery( query ), candidates )
|
filetype = vim.eval( "&filetype" )
|
||||||
|
self.completer.CandidatesForQueryAndType( SanitizeQuery( query ),
|
||||||
|
filetype,
|
||||||
|
candidates )
|
||||||
return candidates
|
return candidates
|
||||||
|
|
||||||
def AddBufferIdentifiers( self ):
|
def AddBufferIdentifiers( self ):
|
||||||
@ -38,8 +41,9 @@ class CompletionSystem( object ):
|
|||||||
text = RemoveIdentFreeText( text )
|
text = RemoveIdentFreeText( text )
|
||||||
|
|
||||||
idents = re.findall( self.pattern, text )
|
idents = re.findall( self.pattern, text )
|
||||||
|
filetype = vim.eval( "&filetype" )
|
||||||
filepath = vim.eval( "expand('%:p')" )
|
filepath = vim.eval( "expand('%:p')" )
|
||||||
self.completer.AddCandidatesToDatabase( idents, filepath )
|
self.completer.AddCandidatesToDatabase( idents, filetype, filepath )
|
||||||
|
|
||||||
def CurrentColumn():
|
def CurrentColumn():
|
||||||
# vim's columns start at 1 while vim.current.line columns start at 0
|
# vim's columns start at 1 while vim.current.line columns start at 0
|
||||||
|
Loading…
Reference in New Issue
Block a user