Difference between revisions of "Code::Completion Rewrite"
Stevenkaras (talk | contribs)  | 
				m (add category)  | 
				||
| (10 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
| + | [[Category:Code::Blocks Documentation]]  | ||
| + | [[Category:Developer Documentation]]  | ||
| + | Here you'll find some discussion on the Code::Completion rewrite, and some useful links to related materials online.  | ||
| + | |||
== Background ==  | == Background ==  | ||
The current Code::Completion plug-in has some flaws, and is currently development frozen.  | The current Code::Completion plug-in has some flaws, and is currently development frozen.  | ||
| Line 41: | Line 45: | ||
==== Process ====  | ==== 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)  | ||
| + | * 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 ===  | === Code::SymbolTable ===  | ||
There will be 3 symbol lists:  | 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 the   | + | Here's a good link for further reading on the subject and the problems:  | 
| + | [http://en.wikipedia.org/wiki/C%2B%2B#Parsing_and_processing_C.2B.2B_source_code On Wikipedia]  | ||
| + | |||
| + | ==== Data Proposal ====  | ||
  class symbol  |   class symbol  | ||
| Line 63: | Line 81: | ||
      int    filepos_end;       // Position where declaration of the symbol ends  |       int    filepos_end;       // Position where declaration of the symbol ends  | ||
      int    type;              // Type of the symbol: macro / class / typedef / variable / function  |       int    type;              // Type of the symbol: macro / class / typedef / variable / function  | ||
| − |       flags  modifiers;         // Bitfield used to mark some   | + |       flags  modifiers;         // Bitfield used to mark some extra properties of symbol  | 
                                // like that it is static or inline  |                                 // like that it is static or inline  | ||
      int    value_type_id;     // Id of symbol which represents c++ type of current symbol  |       int    value_type_id;     // Id of symbol which represents c++ type of current symbol  | ||
| Line 204: | Line 222: | ||
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  | 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>  |   #include <string>  | ||
| Line 215: | Line 233: | ||
  }  |   }  | ||
| − | ===   | + | === Template classes ===  | 
  template<typename T> class Template  |   template<typename T> class Template  | ||
| Line 237: | Line 255: | ||
  }  |   }  | ||
| − | ===   | + | === Automated deduction of template arguments from passed function arguments ===  | 
  #include <stdio.h>  |   #include <stdio.h>  | ||
| Line 259: | Line 277: | ||
  }  |   }  | ||
| − | ===   | + | === Template arguments for templates ===  | 
  #include <stdio.h>  |   #include <stdio.h>  | ||
| Line 291: | Line 309: | ||
  }  |   }  | ||
| − | ===   | + | === Partial specializations ===  | 
  #include <stdio.h>  |   #include <stdio.h>  | ||
| Line 318: | Line 336: | ||
  }  |   }  | ||
| − | ===   | + | === Advanced template argument deduction ===  | 
  #include <stdio.h>  |   #include <stdio.h>  | ||
| Line 408: | Line 426: | ||
      Invoke( &Function3 ).'''Call2'''();  |       Invoke( &Function3 ).'''Call2'''();  | ||
      return 0;  |       return 0;  | ||
| + |  }  | ||
| + | |||
| + | === Hidden virtual functions ===  | ||
| + | |||
| + |  class Base  | ||
| + |  {  | ||
| + |  public:  | ||
| + |      virtual void stam(int);  | ||
| + |  };  | ||
| + | |||
| + |  class Derived : Base  | ||
| + |  {  | ||
| + |  public:  | ||
| + |      void stam(double, int);  | ||
| + |  };  | ||
| + | |||
| + |  main()  | ||
| + |  {  | ||
| + |      Base *pBase = new Base;  | ||
| + |      pBase->'''stam('''  | ||
| + |              ^ Function tip should show stam(int)  | ||
| + |      Derived * pDerived = new Derived;  | ||
| + |      pDerived->'''stam('''  | ||
| + |                 ^ Function tip should show stam(double, int)  | ||
| + |                                            Base::stam(int)  | ||
| + |  }  | ||
| + | |||
| + | === Macros hiding include files ===  | ||
| + | in header.h  | ||
| + |  int x;  | ||
| + | in main.cpp  | ||
| + |  #define myHeader "header.h"  | ||
| + |  #include myHeader  | ||
| + | |||
| + |  main()  | ||
| + |  {  | ||
| + |      int '''x''';  | ||
  }  |   }  | ||
Latest revision as of 13:15, 16 February 2009
Here you'll find some discussion on the Code::Completion rewrite, and some useful links to related materials online.
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 Base;
    pBase->stam(
            ^ Function tip should show stam(int)
    Derived * pDerived = new Derived;
    pDerived->stam(
               ^ Function tip should show stam(double, int)
                                          Base::stam(int)
}
Macros hiding include files
in header.h
int x;
in main.cpp
#define myHeader "header.h"
#include myHeader
main()
{
    int x;
}