Loading .ycm_clang_options files now
These files can contain flags that are passed to clang.
This commit is contained in:
parent
b703138cac
commit
cdb8dfc86b
@ -21,10 +21,13 @@
|
||||
#include "standard.h"
|
||||
#include "CandidateRepository.h"
|
||||
#include "ConcurrentLatestValue.h"
|
||||
#include "Utils.h"
|
||||
#include "ClangUtils.h"
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
using boost::packaged_task;
|
||||
using boost::bind;
|
||||
using boost::unique_future;
|
||||
@ -258,7 +261,8 @@ void ClangCompleter::SetFileCompileFlags(
|
||||
const std::string &filename,
|
||||
const std::vector< std::string > &flags )
|
||||
{
|
||||
flags_for_file_[ filename ] = flags;
|
||||
flags_for_file_[ filename ] =
|
||||
make_shared< std::vector< std::string > >( flags );
|
||||
}
|
||||
|
||||
|
||||
@ -393,7 +397,14 @@ CXTranslationUnit ClangCompleter::CreateTranslationUnit(
|
||||
const std::string &filename,
|
||||
const std::vector< UnsavedFile > &unsaved_files )
|
||||
{
|
||||
std::vector< const char* > flags = ClangFlagsForFilename( filename );
|
||||
std::vector< const char* > flags = FlagsForFilename( filename );
|
||||
flags.reserve( flags.size() + global_flags_.size() );
|
||||
|
||||
foreach ( const std::string &flag, global_flags_ )
|
||||
{
|
||||
flags.push_back( flag.c_str() );
|
||||
}
|
||||
|
||||
std::vector< CXUnsavedFile > cxunsaved_files = ToCXUnsavedFiles(
|
||||
unsaved_files );
|
||||
|
||||
@ -408,20 +419,30 @@ CXTranslationUnit ClangCompleter::CreateTranslationUnit(
|
||||
}
|
||||
|
||||
|
||||
std::vector< const char* > ClangCompleter::ClangFlagsForFilename(
|
||||
const std::string &filename )
|
||||
// The implementation of this function is somewhat non-obvious because we need
|
||||
// to make sure that the data pointed to by the const char* pointers returned
|
||||
// outlives this function. We want to make sure that we are calling c_str on the
|
||||
// string objects that are actually stored in flags_for_file_
|
||||
std::vector< const char* > ClangCompleter::FlagsForFilename(
|
||||
const std::string &filename)
|
||||
{
|
||||
std::vector< const char* > flags;
|
||||
FlagsForFile::iterator it =
|
||||
flags_for_file_.find( filename );
|
||||
|
||||
std::vector< std::string > file_flags = flags_for_file_[ filename ];
|
||||
flags.reserve( file_flags.size() + global_flags_.size() );
|
||||
|
||||
foreach ( const std::string &flag, global_flags_ )
|
||||
if ( it == flags_for_file_.end() )
|
||||
{
|
||||
flags.push_back( flag.c_str() );
|
||||
flags_for_file_[ filename ] = make_shared< std::vector< std::string > >(
|
||||
SanitizeClangFlags(
|
||||
SplitFlags(
|
||||
GetNearestClangOptions( filename ) ) ) );
|
||||
|
||||
it = flags_for_file_.find( filename );
|
||||
}
|
||||
|
||||
foreach ( const std::string &flag, file_flags )
|
||||
// TODO: assert it != end
|
||||
|
||||
std::vector< const char* > flags;
|
||||
foreach ( const std::string &flag, *it->second )
|
||||
{
|
||||
flags.push_back( flag.c_str() );
|
||||
}
|
||||
|
@ -38,13 +38,15 @@ struct CompletionData;
|
||||
|
||||
typedef boost::shared_ptr< std::vector< CompletionData > > AsyncCompletions;
|
||||
|
||||
typedef boost::unordered_map< std::string, std::vector< std::string > >
|
||||
FlagsForFile;
|
||||
typedef boost::unordered_map< std::string,
|
||||
boost::shared_ptr<
|
||||
std::vector< std::string > > > FlagsForFile;
|
||||
|
||||
typedef boost::unordered_map< std::string, CXTranslationUnit >
|
||||
TranslationUnitForFilename;
|
||||
|
||||
|
||||
// TODO: document that all filename parameters must be absolute paths
|
||||
class ClangCompleter : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
@ -84,8 +86,7 @@ private:
|
||||
const std::string &filename,
|
||||
const std::vector< UnsavedFile > &unsaved_files );
|
||||
|
||||
std::vector< const char* > ClangFlagsForFilename(
|
||||
const std::string &filename );
|
||||
std::vector< const char* > FlagsForFilename( const std::string &filename );
|
||||
|
||||
CXTranslationUnit GetTranslationUnitForFile(
|
||||
const std::string &filename,
|
||||
|
118
cpp/ycm/ClangUtils.cpp
Normal file
118
cpp/ycm/ClangUtils.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
|
||||
//
|
||||
// This file is part of YouCompleteMe.
|
||||
//
|
||||
// YouCompleteMe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// YouCompleteMe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "ClangUtils.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
const char *CLANG_OPTIONS_FILENAME = ".ycm_clang_options";
|
||||
|
||||
std::vector< std::string > SanitizeClangFlags(
|
||||
const std::vector< std::string > &flags )
|
||||
{
|
||||
std::vector< std::string > sanitized_flags = flags;
|
||||
std::vector< std::string >::iterator it = sanitized_flags.begin();
|
||||
|
||||
while ( it != sanitized_flags.end() )
|
||||
{
|
||||
if ( *it == "-arch" )
|
||||
{
|
||||
if ( it + 1 != sanitized_flags.end() )
|
||||
sanitized_flags.erase( it, it + 2 );
|
||||
else
|
||||
sanitized_flags.erase( it, it + 1 );
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
return sanitized_flags;
|
||||
}
|
||||
|
||||
|
||||
std::vector< std::string > SplitFlags( const std::string &flags_string )
|
||||
{
|
||||
std::vector< std::string > flags;
|
||||
|
||||
bool in_quotes = false;
|
||||
uint flag_start = 0;
|
||||
uint flag_length = 0;
|
||||
for ( uint i = 0; i < flags_string.size(); ++i )
|
||||
{
|
||||
char current_char = flags_string[ i ];
|
||||
if ( isspace( current_char ) and !in_quotes )
|
||||
{
|
||||
if ( flag_length != 0 )
|
||||
{
|
||||
flags.push_back( flags_string.substr( flag_start, flag_length ) );
|
||||
flag_length = 0;
|
||||
}
|
||||
|
||||
flag_start = i + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( current_char == '\'' || current_char == '\"' )
|
||||
{
|
||||
in_quotes = !in_quotes;
|
||||
}
|
||||
|
||||
++flag_length;
|
||||
}
|
||||
|
||||
if ( flag_length != 0 )
|
||||
flags.push_back( flags_string.substr( flag_start, flag_length ) );
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
std::string GetNearestClangOptions( const std::string &filename )
|
||||
{
|
||||
fs::path parent_folder = fs::path( filename ).parent_path();
|
||||
fs::path clang_options_filename( CLANG_OPTIONS_FILENAME );
|
||||
|
||||
std::string options_file_contents;
|
||||
fs::path old_parent_folder = parent_folder;
|
||||
|
||||
do
|
||||
{
|
||||
fs::path current_file = parent_folder / clang_options_filename;
|
||||
if ( fs::exists( current_file ) )
|
||||
{
|
||||
options_file_contents = ReadUtf8File( current_file );
|
||||
break;
|
||||
}
|
||||
|
||||
old_parent_folder = parent_folder;
|
||||
parent_folder = parent_folder.parent_path();
|
||||
}
|
||||
while ( old_parent_folder != parent_folder );
|
||||
|
||||
return options_file_contents;
|
||||
}
|
||||
|
||||
} // namespace YouCompleteMe
|
40
cpp/ycm/ClangUtils.h
Normal file
40
cpp/ycm/ClangUtils.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
|
||||
//
|
||||
// This file is part of YouCompleteMe.
|
||||
//
|
||||
// YouCompleteMe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// YouCompleteMe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CLANGUTILS_H_9MVHQLJS
|
||||
#define CLANGUTILS_H_9MVHQLJS
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
// TODO: move most of the anon funcs in ClangCompleter.cpp to here
|
||||
|
||||
// Removes flags that are either unnecessary or cause clang to crash
|
||||
std::vector< std::string > SanitizeClangFlags(
|
||||
const std::vector< std::string > &flags );
|
||||
|
||||
std::vector< std::string > SplitFlags( const std::string &flags_string );
|
||||
|
||||
std::string GetNearestClangOptions( const std::string &filename );
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
||||
#endif /* end of include guard: CLANGUTILS_H_9MVHQLJS */
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "Utils.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
@ -29,4 +33,26 @@ bool AlmostEqual( double a, double b )
|
||||
std::max( std::abs( a ), std::abs( b ) ) );
|
||||
}
|
||||
|
||||
|
||||
std::string ReadUtf8File( const fs::path &filepath )
|
||||
{
|
||||
fs::ifstream file( filepath, std::ios::in | std::ios::binary );
|
||||
std::vector< char > contents( (std::istreambuf_iterator< char >( file )),
|
||||
std::istreambuf_iterator< char >() );
|
||||
|
||||
if ( contents.size() == 0 )
|
||||
return std::string();
|
||||
|
||||
return std::string( contents.begin(), contents.end() );
|
||||
}
|
||||
|
||||
|
||||
void WriteUtf8File( const fs::path &filepath, const std::string &contents )
|
||||
{
|
||||
fs::ofstream file;
|
||||
file.open( filepath );
|
||||
file << contents;
|
||||
file.close();
|
||||
}
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
@ -18,15 +18,23 @@
|
||||
#ifndef UTILS_H_KEPMRPBH
|
||||
#define UTILS_H_KEPMRPBH
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/filesystem.hpp>
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
bool AlmostEqual( double a, double b );
|
||||
|
||||
// Reads the entire contents of the specified file. If the file does not exist,
|
||||
// an exception is thrown.
|
||||
std::string ReadUtf8File( const fs::path &filepath );
|
||||
|
||||
// Writes the entire contents of the specified file. If the file does not exist,
|
||||
// an exception is thrown.
|
||||
void WriteUtf8File( const fs::path &filepath, const std::string &contents );
|
||||
|
||||
template <class Container, class Key>
|
||||
typename Container::mapped_type &
|
||||
|
104
cpp/ycm/tests/ClangUtils_test.cpp
Normal file
104
cpp/ycm/tests/ClangUtils_test.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
|
||||
//
|
||||
// This file is part of YouCompleteMe.
|
||||
//
|
||||
// YouCompleteMe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// YouCompleteMe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "ClangUtils.h"
|
||||
#include "Utils.h"
|
||||
#include "TestUtils.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::WhenSorted;
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
extern const char *CLANG_OPTIONS_FILENAME;
|
||||
|
||||
TEST( ClangUtilsTest, SanitizeClangFlagsWorks )
|
||||
{
|
||||
EXPECT_THAT( SanitizeClangFlags( StringVector(
|
||||
"foo",
|
||||
"-arch",
|
||||
"die",
|
||||
"-arch",
|
||||
"die2",
|
||||
"bar" ) ),
|
||||
ElementsAre( "foo",
|
||||
"bar" ) );
|
||||
|
||||
EXPECT_THAT( SanitizeClangFlags( StringVector(
|
||||
"foo",
|
||||
"-arch",
|
||||
"die" ) ),
|
||||
ElementsAre( "foo" ) );
|
||||
|
||||
EXPECT_THAT( SanitizeClangFlags( StringVector(
|
||||
"-arch",
|
||||
"die" ) ),
|
||||
ElementsAre() );
|
||||
|
||||
EXPECT_THAT( SanitizeClangFlags( StringVector(
|
||||
"-arch" ) ),
|
||||
ElementsAre() );
|
||||
}
|
||||
|
||||
|
||||
TEST( ClangUtilsTest, SplitFlagsWorks )
|
||||
{
|
||||
EXPECT_THAT( SplitFlags( "-f --bar=qux" ),
|
||||
ElementsAre( "-f",
|
||||
"--bar=qux" ) );
|
||||
|
||||
EXPECT_THAT( SplitFlags( "foo" ),
|
||||
ElementsAre( "foo" ) );
|
||||
|
||||
EXPECT_THAT( SplitFlags( "foo \n\n\t\v bar" ),
|
||||
ElementsAre( "foo",
|
||||
"bar" ) );
|
||||
|
||||
EXPECT_THAT( SplitFlags( " a ' a b c ' q " ),
|
||||
ElementsAre( "a",
|
||||
"' a b c '",
|
||||
"q" ) );
|
||||
|
||||
EXPECT_THAT( SplitFlags( "-I../a/b/c -I\"foo/b/c\" -I\"a c\" -I'a/b/c'" ),
|
||||
ElementsAre( "-I../a/b/c",
|
||||
"-I\"foo/b/c\"",
|
||||
"-I\"a c\"",
|
||||
"-I'a/b/c'" ) );
|
||||
}
|
||||
|
||||
|
||||
TEST( ClangUtilsTest, GetNearestClangOptionsWorks )
|
||||
{
|
||||
fs::path temp_root = fs::temp_directory_path() / fs::unique_path();
|
||||
fs::create_directories( temp_root );
|
||||
|
||||
std::string contents = "foo bar";
|
||||
WriteUtf8File( temp_root / fs::path( CLANG_OPTIONS_FILENAME ), contents );
|
||||
|
||||
fs::path parent = temp_root / fs::unique_path();
|
||||
fs::create_directories( parent );
|
||||
|
||||
EXPECT_STREQ( contents.c_str(),
|
||||
GetNearestClangOptions(
|
||||
( parent / fs::unique_path() ).string() ).c_str() );
|
||||
}
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include "IdentifierCompleter.h"
|
||||
#include "Utils.h"
|
||||
#include "TestUtils.h"
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::WhenSorted;
|
||||
@ -26,56 +27,19 @@ using ::testing::WhenSorted;
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::vector< std::string > Candidates( const std::string &a,
|
||||
const std::string &b = std::string(),
|
||||
const std::string &c = std::string(),
|
||||
const std::string &d = std::string(),
|
||||
const std::string &e = std::string(),
|
||||
const std::string &f = std::string(),
|
||||
const std::string &g = std::string(),
|
||||
const std::string &h = std::string(),
|
||||
const std::string &i = std::string() )
|
||||
{
|
||||
std::vector< std::string > candidates;
|
||||
candidates.push_back( a );
|
||||
if ( !b.empty() )
|
||||
candidates.push_back( b );
|
||||
if ( !c.empty() )
|
||||
candidates.push_back( c );
|
||||
if ( !d.empty() )
|
||||
candidates.push_back( d );
|
||||
if ( !e.empty() )
|
||||
candidates.push_back( e );
|
||||
if ( !f.empty() )
|
||||
candidates.push_back( f );
|
||||
if ( !g.empty() )
|
||||
candidates.push_back( g );
|
||||
if ( !h.empty() )
|
||||
candidates.push_back( h );
|
||||
if ( !i.empty() )
|
||||
candidates.push_back( i );
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
|
||||
// This differs from what we expect from the ClangCompleter. That one should
|
||||
// return results for an empty query.
|
||||
TEST( IdentifierCompleterTest, EmptyQueryNoResults )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"foobar" ) ).CandidatesForQuery( "" ),
|
||||
ElementsAre() );
|
||||
}
|
||||
|
||||
TEST( IdentifierCompleterTest, NoDuplicatesReturned )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"foobar",
|
||||
"foobar",
|
||||
"foobar" ) ).CandidatesForQuery( "foo" ),
|
||||
@ -85,14 +49,14 @@ TEST( IdentifierCompleterTest, NoDuplicatesReturned )
|
||||
|
||||
TEST( IdentifierCompleterTest, OneCandidate )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"foobar" ) ).CandidatesForQuery( "fbr" ),
|
||||
ElementsAre( "foobar" ) );
|
||||
}
|
||||
|
||||
TEST( IdentifierCompleterTest, ManyCandidateSimple )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"foobar",
|
||||
"foobartest",
|
||||
"Foobartest" ) ).CandidatesForQuery( "fbr" ),
|
||||
@ -103,7 +67,7 @@ TEST( IdentifierCompleterTest, ManyCandidateSimple )
|
||||
|
||||
TEST( IdentifierCompleterTest, FirstCharSameAsQueryWins )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"foobar",
|
||||
"afoobar" ) ).CandidatesForQuery( "fbr" ),
|
||||
ElementsAre( "foobar",
|
||||
@ -112,20 +76,20 @@ TEST( IdentifierCompleterTest, FirstCharSameAsQueryWins )
|
||||
|
||||
TEST( IdentifierCompleterTest, CompleteMatchForWordBoundaryCharsWins )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"FooBarQux",
|
||||
"FBaqux" ) ).CandidatesForQuery( "fbq" ),
|
||||
ElementsAre( "FooBarQux",
|
||||
"FBaqux" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"CompleterTest",
|
||||
"CompleteMatchForWordBoundaryCharsWins" ) )
|
||||
.CandidatesForQuery( "ct" ),
|
||||
ElementsAre( "CompleterTest",
|
||||
"CompleteMatchForWordBoundaryCharsWins" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"FooBar",
|
||||
"FooBarRux" ) ).CandidatesForQuery( "fbr" ),
|
||||
ElementsAre( "FooBarRux",
|
||||
@ -134,37 +98,37 @@ TEST( IdentifierCompleterTest, CompleteMatchForWordBoundaryCharsWins )
|
||||
|
||||
TEST( IdentifierCompleterTest, RatioUtilizationTieBreak )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"aGaaFooBarQux",
|
||||
"aBaafbq" ) ).CandidatesForQuery( "fbq" ),
|
||||
ElementsAre( "aGaaFooBarQux",
|
||||
"aBaafbq" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"aFooBarQux",
|
||||
"afbq" ) ).CandidatesForQuery( "fbq" ),
|
||||
ElementsAre( "aFooBarQux",
|
||||
"afbq" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"acaaCaaFooGxx",
|
||||
"aCaafoog" ) ).CandidatesForQuery( "caafoo" ),
|
||||
ElementsAre( "acaaCaaFooGxx",
|
||||
"aCaafoog" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"acaaCaaFooGxx",
|
||||
"aCaafoog" ) ).CandidatesForQuery( "caaFoo" ),
|
||||
ElementsAre( "acaaCaaFooGxx",
|
||||
"aCaafoog" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"FooBarQux",
|
||||
"FooBarQuxZaa" ) ).CandidatesForQuery( "fbq" ),
|
||||
ElementsAre( "FooBarQux",
|
||||
"FooBarQuxZaa" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"FooBar",
|
||||
"FooBarRux" ) ).CandidatesForQuery( "fba" ),
|
||||
ElementsAre( "FooBar",
|
||||
@ -173,7 +137,7 @@ TEST( IdentifierCompleterTest, RatioUtilizationTieBreak )
|
||||
|
||||
TEST( IdentifierCompleterTest, QueryPrefixOfCandidateWins )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"foobar",
|
||||
"fbaroo" ) ).CandidatesForQuery( "foo" ),
|
||||
ElementsAre( "foobar",
|
||||
@ -182,26 +146,26 @@ TEST( IdentifierCompleterTest, QueryPrefixOfCandidateWins )
|
||||
|
||||
TEST( IdentifierCompleterTest, LowerMatchCharIndexSumWins )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"ratio_of_word_boundary_chars_in_query_",
|
||||
"first_char_same_in_query_and_text_") )
|
||||
.CandidatesForQuery( "charinq" ),
|
||||
ElementsAre( "first_char_same_in_query_and_text_",
|
||||
"ratio_of_word_boundary_chars_in_query_") );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"barfooq",
|
||||
"barquxfoo" ) ).CandidatesForQuery( "foo" ),
|
||||
ElementsAre( "barfooq",
|
||||
"barquxfoo") );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"xxxxxxabc",
|
||||
"xxabcxxxx" ) ).CandidatesForQuery( "abc" ),
|
||||
ElementsAre( "xxabcxxxx",
|
||||
"xxxxxxabc") );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"FooBarQux",
|
||||
"FaBarQux" ) ).CandidatesForQuery( "fbq" ),
|
||||
ElementsAre( "FaBarQux",
|
||||
@ -210,13 +174,13 @@ TEST( IdentifierCompleterTest, LowerMatchCharIndexSumWins )
|
||||
|
||||
TEST( IdentifierCompleterTest, ShorterCandidateWins )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"CompleterT",
|
||||
"CompleterTest" ) ).CandidatesForQuery( "co" ),
|
||||
ElementsAre( "CompleterT",
|
||||
"CompleterTest" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"CompleterT",
|
||||
"CompleterTest" ) ).CandidatesForQuery( "plet" ),
|
||||
ElementsAre( "CompleterT",
|
||||
@ -225,7 +189,7 @@ TEST( IdentifierCompleterTest, ShorterCandidateWins )
|
||||
|
||||
TEST( IdentifierCompleterTest, SameLowercaseCandidateWins )
|
||||
{
|
||||
EXPECT_THAT( IdentifierCompleter( Candidates(
|
||||
EXPECT_THAT( IdentifierCompleter( StringVector(
|
||||
"foobar",
|
||||
"Foobar" ) ).CandidatesForQuery( "foo" ),
|
||||
ElementsAre( "foobar",
|
||||
|
56
cpp/ycm/tests/TestUtils.cpp
Normal file
56
cpp/ycm/tests/TestUtils.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
|
||||
//
|
||||
// This file is part of YouCompleteMe.
|
||||
//
|
||||
// YouCompleteMe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// YouCompleteMe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "TestUtils.h"
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
std::vector< std::string > StringVector( const std::string &a,
|
||||
const std::string &b,
|
||||
const std::string &c,
|
||||
const std::string &d,
|
||||
const std::string &e,
|
||||
const std::string &f,
|
||||
const std::string &g,
|
||||
const std::string &h,
|
||||
const std::string &i )
|
||||
{
|
||||
std::vector< std::string > string_vector;
|
||||
string_vector.push_back( a );
|
||||
if ( !b.empty() )
|
||||
string_vector.push_back( b );
|
||||
if ( !c.empty() )
|
||||
string_vector.push_back( c );
|
||||
if ( !d.empty() )
|
||||
string_vector.push_back( d );
|
||||
if ( !e.empty() )
|
||||
string_vector.push_back( e );
|
||||
if ( !f.empty() )
|
||||
string_vector.push_back( f );
|
||||
if ( !g.empty() )
|
||||
string_vector.push_back( g );
|
||||
if ( !h.empty() )
|
||||
string_vector.push_back( h );
|
||||
if ( !i.empty() )
|
||||
string_vector.push_back( i );
|
||||
|
||||
return string_vector;
|
||||
}
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
40
cpp/ycm/tests/TestUtils.h
Normal file
40
cpp/ycm/tests/TestUtils.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
|
||||
//
|
||||
// This file is part of YouCompleteMe.
|
||||
//
|
||||
// YouCompleteMe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// YouCompleteMe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef TESTUTILS_H_G4RKMGUD
|
||||
#define TESTUTILS_H_G4RKMGUD
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace YouCompleteMe
|
||||
{
|
||||
|
||||
std::vector< std::string > StringVector( const std::string &a,
|
||||
const std::string &b = std::string(),
|
||||
const std::string &c = std::string(),
|
||||
const std::string &d = std::string(),
|
||||
const std::string &e = std::string(),
|
||||
const std::string &f = std::string(),
|
||||
const std::string &g = std::string(),
|
||||
const std::string &h = std::string(),
|
||||
const std::string &i = std::string() );
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
||||
#endif /* end of include guard: TESTUTILS_H_G4RKMGUD */
|
||||
|
@ -121,6 +121,7 @@ class ClangCompleter( Completer ):
|
||||
self.contents_holder = []
|
||||
self.filename_holder = []
|
||||
|
||||
|
||||
def CandidatesForQueryAsync( self, query ):
|
||||
# TODO: sanitize query
|
||||
files = indexer.UnsavedFileVec()
|
||||
@ -164,6 +165,11 @@ class ClangCompleter( Completer ):
|
||||
return [ CompletionDataToDict( x ) for x in self.future.GetResults() ]
|
||||
|
||||
|
||||
def OnFileEnter( self ):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def GetUnsavedBuffers():
|
||||
def BufferModified( buffer_number ):
|
||||
to_eval = 'getbufvar({0}, "&mod")'.format( buffer_number )
|
||||
|
Loading…
Reference in New Issue
Block a user