Code::Completion Rewrite
Background
The current Code::Completion plug-in has some flaws, and is currently development frozen. The current plug-in lacks full support for:
- function and class templates
 - default arguments in some cases
 - some of the more complicated c++ mucky business
 
Current Effort
Structure
The current C::C is a monolithic library of features, which could be de-coupled and split up for use in multiple plugins, providing extra functionality and flexibility in the future. Therefore, I propose the C::C be broken up into the following components:
- Code::SymbolTable
- Provide a list of valid symbols in the workspace, along with relevant scope information
 
 - Code::Completion
- Provide Auto-complete features
 
 - Code::SymbolOutline
- Provide Symbol browser, find symbol, function jump features
 
 - Code::Refactoring
- Provide code refactoring features
 
 - Code::Documentation
- Provide automatic code generation features
 
 
Code::Completion
Purpose Statement
The current Code::Completion plugin is outdated, and needs a complete rewrite. The purpose of the Code::Completion plugin is thus:
- Provide a list of likely symbols in the current scope as possible solutions to the current symbol.
 - Provide function tooltips
- Parameter list
 - Relevant documentation
 
 - Provide variable tooltips
- type and modifiers
 - scope
 
 - Provide preprocessor tooltips
- replacement value of a macro
 - parameter list when applicable
 
 - Provide completion features for class constructors
 - Provide completion features for initializer lists
 
Process
- The user requests a completion of the current symbol.
- Call CC::EventSymbolHover
- When the mouse hovers over a symbol after a timeout
 
 - Call CC::EventSymbolTip
- When the user types in any of the following: . :: ->
 - When the user presses the keystroke CTRL-SPACE
 
 - Call CC::EventCallTip
- When the user types in any of the following: ( ,
 - When the user presses the keystroke CTRL-SHIFT-SPACE
 
 - Call CC::EventPreprocTip
- When the user types in any of the following: < " when in preproc context (# at the start of the line)
 
 
 - Call CC::EventSymbolHover
 - the C::C plugin determines the proper scope, when applicable (global, local, class)
 - Compare the current symbol against the symbol table of proper scope.
 - Provide a composite list to the user.
 
Code::SymbolTable
There will be 3 symbol lists:
- global namespace
 - local scope (2 options)
- the local scope can be generated by smartly parsing the current file on every request
 - keep a running count, and add/remove symbols from the table as the file is edited
 
 - class scope
 
Here's a good link for further reading on the subject and the problems: On Wikipedia
Data Proposal
class symbol
{
    string name;              // name of the symbol
    int    id;                // Id of the symbol, should be unique in the workspace
    int    file_id;           // Id of file where the symbol has been declared
    int    filepos_begin;     // Position where declaration of the symbol starts
    int    filepos_end;       // Position where declaration of the symbol ends
    int    type;              // Type of the symbol: macro / class / typedef / variable / function
    flags  modifiers;         // Bitfield used to mark some extra properties of symbol
                              // like that it is static or inline
    int    value_type_id;     // Id of symbol which represents c++ type of current symbol
                              // (like type of variable or type of returned value from function)
    int    extra_type_id;     // Extra type used in some cases
    list   children;          // List of child elements of this symbol (members in class etc)
    list   extra_lists[3];    // See table below
    map    extra_values;      // int -> string map which can keep some extra data
}
class list_entry
{
    int    symbol_id;         // ID of the symbol referenced
    int    storage_class;     // Storage class of the symbol (private/protected/public)
}
Explanation of symbol::extra_lists[]
| type | modifiers | value_type_id | extra_type | children | extra_lists[0] | extra_lists[1] | extra_lists[2] | 
|---|---|---|---|---|---|---|---|
| namespace | declarations in namespace | "using" namespaces | |||||
| class / struct / union | members of class | base classes | template args | friends of class | |||
| variable | extern, static, volatile, const | type of variable | |||||
| function | static, inline, const ... | returned value | arguments | template arguments | |||
| typedef | pointer, array, reference, pointer_to_member | base type | type of class in pointer_to_member | ||||
| enum | items in enum | ||||||
| enum item | id of enum | ||||||
| macro | macro parts | ||||||
| macro part | arg_to_string, va_args | number of arg or -1 | 
Comments:
- Such representation would require some extra "hidden" symbols - for example when some complex type is returned from function, extra symbol of typedef representing proper value would be required.
 - Also in case of templates, typeid's should be threated in special way - negative value could mean to use template argument instead of some real type. Base types (the POD ones) should have some predefined type ids.
 
Questions:
- why are we storing filepos_end? Wouldn't it be much more useful to store declaration, definition info?
 
More complex cases of C::C usage
Here we can put some more complex examples of c++ code where C::C may fail. Symbols that may be hard to find should be marked in bold
Fetching type of operator call
#include <string>
using namespace std;
int main(int,char**)
{
    ( string("first") + "second" + "third" ) . c_str();
    return 0;
}
Template classes
template<typename T> class Template
{
public:
    T& GetInstance() { return m_Instance; }
private:
    T m_Instance;
};
class Parameter
{
public:
    void PrintfText() { printf("Text"); }
};
int main(int,char**)
{
    Template<Parameter> Object;
    Object.GetInstance().PrintfText();
}
Automated deduction of template arguments from passed function arguments
#include <stdio.h>
class Class
{
	public:
		void SomeFunction()  { printf("SomeFunction\n"); }
};
template< class T > T& Function( T& arg )
{
	return arg;
}
int main( int, char** )
{
	Class f;
	Function(f).SomeFunction();
	return 0;
}
Template arguments for templates
#include <stdio.h>
template< template<class> class InternalTemplate, typename Type > class Test
{
    public:
        InternalTemplate<Type> m_Member;
};
template< class T > class TestInt
{
    public:
        T m_IntMember;
};
class Class
{
    public:
        void Print() { printf("Class::Print\n"); }
};
int main( int, char** )
{
    Test<TestInt,Class> Object;
    Object.m_Member.m_IntMember.Print();
    return 0;
}
Partial specializations
#include <stdio.h>
template< class T > class Template
{
    public:
        void Print() { printf("Generic specialization\n"); }
};
template<> class Template<float>
{
    public:
        void PrintFloat() { printf("Partial specialization\n"); }
};
int main(int,char**)
{
    Template<int> TInt;
    TInt.Print();         // PrintFloat() should not be available here
    Template<float> TFloat;
    TFloat.PrintFloat();  // Print() should not be available here
    return 0;
}
Advanced template argument deduction
#include <stdio.h>
// Class encapsulating function without arguments
class Caller0
{
        void (* m_Func )( void );
    public:
        Caller0( void (* Func )( void ) ) : m_Func(Func) {}
        void Call0() { m_Func(); }
};
// Template for class encapsulating function with one argument
template < class T > class Caller1
{
        void (* m_Func )( T );
    public:
        Caller1( void (* Func )( T ) ) : m_Func(Func) {}
        void Call1() { m_Func( T() ); }
};
// Template for class encapsulating function with two arguments
template < class T1, class T2 > class Caller2
{
        void (* m_Func )( T1, T2 );
    public:
        Caller2( void (* Func )( T1, T2 ) ) : m_Func(Func) {}
        void Call2() { m_Func ( T1(), T2() ); }
};
// This one will be used for functions without arguments
Caller0 Invoke( void (* Func )( void ) )
{
    return Caller0( Func );
}
// This one will be used for functions with one argument
template < class T > Caller1<T> Invoke( void (* Func )( T ) )
{
    return Caller1<T>( Func );
}
// This one will be used for functions with two arguments
template < class T1, class T2 > Caller2<T1,T2> Invoke( void (* Func )( T1, T2 ) )
{
    return Caller2<T1,T2> ( Func );
}
void Function0(void)
{
    printf("Function0\n");
}
void Function1(float)
{
    printf("Function1\n");
}
void Function2(int)
{
    printf("Function2\n");
}
void Function3(int,float)
{
    printf("Function3\n");
}
int main(int,char**)
{
    Invoke( Function0 ).Call0();
    Invoke( Function1 ).Call1();
    Invoke( Function2 ).Call1();
    Invoke( Function3 ).Call2();
    Invoke( &Function0 ).Call0();
    Invoke( &Function1 ).Call1();
    Invoke( &Function2 ).Call1();
    Invoke( &Function3 ).Call2();
    return 0;
}
Hidden virtual functions
class Base
{
public:
    virtual void stam(int);
};
class Derived : Base
{
public:
    void stam(double, int);
};
main()
{
    Base * pBase = new Derived;
    pBase->stam(
               ^ Function tip should show stam(double, int)
}