Author Topic: code completion enhancement request  (Read 10655 times)

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5529
code completion enhancement request
« on: December 28, 2012, 07:33:25 pm »
recently the code completion was enhanced by recognizing declaration in if / for/while constructs, this is great.

I would like to take it one step small further : range based for :

* say you have a container ==> vector/list/... "container"

Code

for (auto foo : container)

for (const auto foo : container)

for (auto& foo : container)

for (const auto& foo : container)


foo is of the value type (disregarding const and references here) of the container.

Example :
std::vector<MyType> container;   ===> foo is of type MyType

So the syntax seems simple in the "for( ... : ...)", the challenge probably is, do we know the 'container' its value type ? And can we deduce this second level of determination ?


What do our CC experts think ?

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: code completion enhancement request
« Reply #1 on: December 28, 2012, 08:11:44 pm »
So the syntax seems simple in the "for( ... : ...)", the challenge probably is, do we know the 'container' its value type ? And can we deduce this second level of determination ?
Read the standard, I'm sure it explains how the type is deduced. ::)
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ptDev

  • Almost regular
  • **
  • Posts: 222
Re: code completion enhancement request
« Reply #2 on: December 29, 2012, 12:35:44 am »
recently the code completion was enhanced by recognizing declaration in if / for/while constructs, this is great.

I would like to take it one step small further : range based for :

* say you have a container ==> vector/list/... "container"

Code

for (auto foo : container)

for (const auto foo : container)

for (auto& foo : container)

for (const auto& foo : container)


foo is of the value type (disregarding const and references here) of the container.

Example :
std::vector<MyType> container;   ===> foo is of type MyType

So the syntax seems simple in the "for( ... : ...)", the challenge probably is, do we know the 'container' its value type ? And can we deduce this second level of determination ?


What do our CC experts think ?


In your examples, the only issue for CC is that "auto" uses template type deduction.
I don't think CC can handle that yet.

Try explicitly declaring the type in those range based loops, and CC won't have a problem.

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5529
Re: code completion enhancement request
« Reply #3 on: December 29, 2012, 08:51:31 am »
I know that, that's why I call it a challenge.
The auto keyword is there to make life easier, and don't repeat types anymore.

So the question is, is our CC able to do such a thing with let's +- minimal effort. That's the extra level is was talking about, (by limiting the complexity), looking at what is at the right hand side of the ":" and then get the type of it. And once CC knows what's the thing on the right hand side (vector<MyType>) can it then easily determine that "MyType" ? )

So still some static analysis, by avoiding turning our CC into a compiler.

FOr that I am gonna start another thread, but our CC is going to have to use compiler backends, I think there was already an experiemtn with clang ?

But in this topic I just want to see if this particular use case might be easier to achieve ...

Offline ptDev

  • Almost regular
  • **
  • Posts: 222
Re: code completion enhancement request
« Reply #4 on: January 01, 2013, 04:55:54 pm »
I know that, that's why I call it a challenge.
The auto keyword is there to make life easier, and don't repeat types anymore.

So the question is, is our CC able to do such a thing with let's +- minimal effort. That's the extra level is was talking about, (by limiting the complexity), looking at what is at the right hand side of the ":" and then get the type of it. And once CC knows what's the thing on the right hand side (vector<MyType>) can it then easily determine that "MyType" ? )

I thought of that before. If CC was to able to parametrize some classes by known types, then this use case would be simplified, yes. This change alone, however, does require quite a bit of refactoring as it is.

Quote
So still some static analysis, by avoiding turning our CC into a compiler.

FOr that I am gonna start another thread, but our CC is going to have to use compiler backends, I think there was already an experiemtn with clang ?

But in this topic I just want to see if this particular use case might be easier to achieve ...

I remember reading in the forum about someone experimenting with a Clang-based CC, but never heard of any results since...

Offline p2rkw

  • Almost regular
  • **
  • Posts: 142
Re: code completion enhancement request
« Reply #5 on: January 01, 2013, 09:36:25 pm »
Code
for (auto foo : container)
Keep in mind that instead of container there might be expression. And "auto" have different meaning in c++03.

As you can see here: http://en.cppreference.com/w/cpp/language/range-for , loop declaration:
Code
for ( range_declaration : range_expression) loop_statement
is equals to
Code
    auto && __range = range_expression ;
    auto __begin = __range.begin(); // or begin(__range);
    auto __end = __range.end();      // or end(__range);
    for (;__begin != __end; ++__begin) {
        range_declaration = *__begin;
        loop_statement
    }

and declaration
Code
auto foo = expression
is logically equals to
Code
decltype(expression) foo = expression

To implement decltype parser might use NativeParser::AI to find out type of expression (all required tokens should be already in tree), but actually ParserThread doesn't have access to NativeParser object.

Offline p2rkw

  • Almost regular
  • **
  • Posts: 142
Re: code completion enhancement request
« Reply #6 on: March 30, 2013, 03:55:34 am »
I have tried to implement this feature, result here: http://imgur.com/WTWdDPz
but it seems CC cant find "operator*" in std::vector::const_iterator, so it doesn't work for std::vector and probably for all templates.

@developers: can m_NativeParser pointer be pass down to ParserThread?
« Last Edit: March 30, 2013, 04:01:00 am by p2rkw »

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: code completion enhancement request
« Reply #7 on: July 17, 2013, 03:27:28 am »
@developers: can m_NativeParser pointer be pass down to ParserThread?
Why do you want to do that, you want let the ParserThread to access NativeParser class?

I think the control level is: (the most left is the most hight control level)

CodeCompletion class -> NativeParser -> Parser -> ParserThread -> Tokenizer
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline p2rkw

  • Almost regular
  • **
  • Posts: 142
Re: code completion enhancement request
« Reply #8 on: July 17, 2013, 10:46:33 pm »
Quote
CodeCompletion class -> NativeParser -> Parser -> ParserThread -> Tokenizer
Thats true, but:
source file is parsed in ParserThread, and TokenTree is build there. So what can parser do when "auto" or "decltype" token occurs?
My idea was to detect real type of variable defined as "decltype" using  NativeParserBase::ResolveActualType or somethin like that. All tokens required to detect real type of "auto" variable or function probably will be already in tree.

Lets assume you have access to nativeParser in ParserThread, so you can write something like this in DoParse:
Code
if(token == ParserConsts::dectype)
{
  m_Tokenizer.GetToken(); // eat "decltype"
  m_Tokenizer.GetToken(); // eat "("
  string type = m_Tokenizer.GetToken();
  //release lock here
  TokenIdxSet result;
  nativeParser->resolveActualType(m_tree, type, ..., result) // or AI( ..., type, result)
  //lock again
  Token *newToken = DoAddToken(tkVariable, token, smallTokenizer.GetLineNumber());
  newToken->m_FullType = tree[result.begin()]->m_FullType;
}

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: code completion enhancement request
« Reply #9 on: July 18, 2013, 03:51:41 am »
I understand your idea.
Code
size_t NativeParserBase::ResolveActualType(TokenTree*         tree,
                                           wxString           searchText,
                                           const TokenIdxSet& searchScope,
                                           TokenIdxSet&       result)
See the third parameter, it is the searchScope, which is a C++ exposed scope(context). It can be introduced by
1, using directive
2, class inheritance
3, scope exposed in its include files
4, other cases
So, how do you get them?

The dirty thing is C++ grammar is context sensitive, it is hard to solve which type when the Parserthread meet a decltype.

Another thing is:
Is it possible to introduce a Token, which has type string named "undefined" or "lasy", then when NativeParser need to show tooltip or code suggestion, it can solve them. (I mean solve the types later when needed)

Final thought, type solving is related to semantic check stage, but our CC's parser mostly do a syntax check, so if we need precise information, a full parser (Clang or GCC) is needed.

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.