Author Topic: CC plugin interface redesign  (Read 154714 times)

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #15 on: July 07, 2013, 10:41:54 pm »
Thoughts?
Hm, why don't you do a live refactoring, one step at a time?

I doubt you'll be able to predict what we'll be needed from the start.
Just move some code around and see how the interface is coming along.

For example - extract the autocompletion list to be in cbplugin.cpp and to be common for all cc plugins.
Then continue with the rest of it - toolbar, symbol browser, tooltips, etc.

For the autocompletion list you can take two approaches:
1. define an autocompletion list item structure
Code
struct Item{ 
  wxstring text, type;
  cbAutocompletionTokenType tokenType;
  cbAutocompletionScope scope;
};
2. allow the CC plugin to tell the core, what kind of tokens can it produce and then make a struct with ints
Code
struct Item{
  wxstring text; // contains the full text visible in the list
  int iconIndex; // used for the icon
}

Also you'll define a function which returns the icons:
CC::GetTokenIcons() or CC::GetTokenIcon(int index)

If you'd ask me I'd use the second approach, because it is more flexible and it will work for dynamic languages, where the type is not always available.
(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 Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #16 on: July 07, 2013, 11:49:10 pm »
My reason behind using simply a wxArrayString (and, now that I think about it, it could just be a wxString, because the next step would be to concatenate it anyway) is that a CC plugin would register the icons it wants, and just embed those values in the returned string(s).
Alternatively, should the main app be responsible for registration?

Since no filename is mentioned I am thinking one supposed to use
active editor right? This should be more generic and pass the filename
or better yet buffer as well
Active editor, because I can think of no circumstance in which one would want autocompletion on a non-active editor.  Passing a filename or cbEditor* would, in my opinion, be an unnecessary level of indirection.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #17 on: July 08, 2013, 01:33:00 am »
What about scripts or the watch window when typing an expression?

p.s. Please don't use wxArrayXXXX they are bloody dangerous to use, because the operator[] is defined in the maddest possible way! Use std::vector or std::deque instead!
(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 golgepapaz

  • Multiple posting newcomer
  • *
  • Posts: 44
Re: CC plugin interface redesign
« Reply #18 on: July 08, 2013, 03:55:47 am »
My reason behind using simply a wxArrayString (and, now that I think about it, it could just be a wxString, because the next step would be to concatenate it anyway) is that a CC plugin would register the icons it wants, and just embed those values in the returned string(s).
Alternatively, should the main app be responsible for registration?
IMHO, that's a bad idea because using strings as a container object and marshalling, demarshalling necessary information is absurd.
I am sure there will be more information that needs to be conveyed than a simple string. First thing that comes to mind is
displayed vs inserted text. For example the code completion result for function int foo (int param) you can display it in the
completion list as foo(int):int or any variation thereof but you only need to insert the foo (maybe with parentheses)
also there is other information that I've mentioned before. I am sure you are not proposing to embed all this information in one string
which is very hard to use. Some data structures like the ones obfuscated gave examples of and I've mentioned are absolutely necessary.

Active editor, because I can think of no circumstance in which one would want autocompletion on a non-active editor.  Passing a filename or cbEditor* would, in my opinion, be an unnecessary level of indirection.
Yeah, probably but, IsProviderFor() needs it anyway so there is no need to be stingy. Thing is it can help decouple the CC plugin from the Manager to some extent and
because singletons are evil  :D and there is an attempt in this direction(discussed http://forums.codeblocks.org/index.php/topic,17750.0.html). Also every method that is using active editor need boilerplate code something like this;
Code
    cbEditor* editor = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
    if (!editor)
        return;

    if (IsProviderFor(editor))
    {
          //Do stuff probably involving further indirection to cbStyledTextCtrl.
    }
Pass a viable and healthy editor and save the plugin developer from some suffering. :)

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #19 on: July 08, 2013, 03:53:33 pm »
(This forum begins to annoy me: I spent a little over an hour yesterday, trying to submit this post, but gave up and am trying again now.)

It has occurred to me (and I am very surprised it did not occur earlier) that the modifications I plan for the sdk are larger, and should receive their own class; however, I am unsure where to hook it into the main application (as I have never changed something like this before in Code::Blocks).  @devs: Suggestions?
The creation of, for example, a CCManager would fit... but I would prefer an option other than a new manager.

IMHO, that's a bad idea because using strings as a container object and marshalling, demarshalling necessary information is absurd.
I am sure there will be more information that needs to be conveyed than a simple string.
Actually, not exactly; for the specific purpose I had in mind, communicating with Scintilla, no other information is required.
From (wx)Scintilla api:
Code
    // Display a auto-completion list.
    // The lenEntered parameter indicates how many characters before
    // the caret should be used to provide context.
    void AutoCompShow(int lenEntered, const wxString& itemList);
However, you have made me think ;).  Having the additional information available will be useful in the future if, ex., we someday hook CC plugins into dialogue boxes, entry forms, etc.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #20 on: July 08, 2013, 05:41:03 pm »
What do you want to store in this class? What functions will it has?
(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 Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #21 on: July 08, 2013, 05:50:15 pm »
Instead of each CC plugin subscribing to editor events, I want this class to register the common ones that most (all) CC plugins would use.  This class would then call the appropriate function from the appropriate CC plugin.  For example: asking to rebuild the scope toolbar, asking for tooltips, asking for call tips, asking to launch/get data for the autocomple popup, asking for documentation on a symbol.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #22 on: July 08, 2013, 06:03:28 pm »
Ok, then you'll need a manager :)
Another option is to define an interface class and to set the implementation in the Manager.

Code
struct cbCCManagerInterface
{
};

struct CCManager : cbCCManagerInterface {};

Manager::Get()->SetCCManager(new CCManager)

Manager::Get()->GetCCManager();
(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 p2rkw

  • Almost regular
  • **
  • Posts: 142
Re: CC plugin interface redesign
« Reply #23 on: July 08, 2013, 11:03:23 pm »
Last time I rarely use codeblocks, but some time ago I spend some time with CC source code, so I share my thoughts with you :)
Most modern IDEs collects and caches all token's data when it gets selected. Take a look at netbeans or eclipse: you selects token, and in next few moments
all matchig occurences are hightlighted. Rest of token data are probably cached, Why CB doesn't go this way?  This may speed up token related operations such as autocomplete, go to definition/declaration, etc Also some kind of "find usages" are faster in those IDEs.

So here is my proposiotnion (I dont have to much time to write rich description, I hope you got the idea):
Code
struct TokenID;
struct TypeID;

struct TokenInfo{
  std::string name;
  
  TypeID typeID;
  TypeID parentTypeID;
};

struct TypeInfo{
  std::string name;
  
  //std::vector<TypeID> childs, bases, etc...
};

struct CodeComplete{
  // callback called when cursor position has been changed
  virtual void onCursorPositionChange(int fileID, int cursorPosition);

  // returns ID of token at currnet position
  virtual TokenID getCurrnetTokenID();

  // returns all useful informations about current token
  virtual TokenInfo getTokenInfo();

  // returns all useful informations about given token
  virtual TokenInfo getTokenInfo(TokenID);

  // returns all useful informations about given type (class, function, enum)
  virtual TypeInfo getTypeInfo(TypeID);

  // returs all occurrences of current token in open file
  virtual std::vector<int> getOccurrences();

  enum AccessBit{
    abAll = 0,
    abAccessible = 1,
    abPrivate = 2,
    abProtected = 4,
    //etc
  };
  // returns IDs of members that have specified acces from current token
  virtual std::vector<TokenID> getMembers(int accesBit);
  

  int currentPosition;
  int currentFileID;
  TokenID currentTokenID;
};
And possible autocomplete implementation:
Code
// object.mem|ber - '|' as always means caret position, "ber" is a rest of matching member name
TokenInfo ti = cc->getTokenInfo();
cc->setCurrentToken(ti.parentID);
std::vector<TokenID> members = cc->getMembers(abAccessible);
std::string autocomplete;
for(auto mem : members){
  TokenInfo memInfo = cc->getTokenInfo(mem);
  if(memInfo.name.startsWith(ti.name)) // ti.name == "mem" in this case
    autocomplete += memInfo.fullName + "\n";
}
//send autocomplete string to scintilla here
cc->setCurrnetToken(ti.ID);
Most imporntant thing is that CC doesnt touch UI code at all.  
« Last Edit: July 08, 2013, 11:07:30 pm by p2rkw »

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #25 on: July 15, 2013, 05:17:07 am »
Tooltips are mostly migrated to the new CCManager; it functions almost exactly the same, except for a few of my improvements that should make CC tooltips try to be the optimal size/shape when squished into small monitors.  (To compile, you may have to patch the appropriate build system; I only added the files to the unix cbp currently.)

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #26 on: July 15, 2013, 10:39:38 am »
1. Please don't use wxArrayXXX it is bloody dangerous, because there is only one operator[], which is const and which returns a reference to the element. This allows the user to change the content of a const wxArrayXXX. This has led to very mysterious bugs in the past. At least this is the situation in wx2.8. They might have fixed it in 2.9, but I doubt. Use std::vector<wxString> instead.
2. Do you still display the current parameter bold?
(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 Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #27 on: July 15, 2013, 02:50:42 pm »
1.  Sorry, I forgot you had asked that; I will switch it.
2.  Only the tooltips (show full name of symbol under mouse) have been migrated.  The calltips (which show bold parameters) are currently still provided by the CC plugin.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC plugin interface redesign
« Reply #28 on: July 15, 2013, 02:54:10 pm »
Hm, I'm a bit confused here...
What is the difference between a calltip and a tooltip?
I don't think there is any and the code should be combined somehow :)
(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 Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: CC plugin interface redesign
« Reply #29 on: July 15, 2013, 10:41:52 pm »
What is the difference between a calltip and a tooltip?
Not much, really.  They used to be more different: calltips would only show when you either type '(' after a function, or press Ctrl-Shift-Space; and tooltips by a mouse dwell event.  However some time ago, I changed the mouse dwell to also show calltips if no tooltips are available.  The main difference at the source level is that calltips have an extra section of code specifying what needs to be highlighted.
I will look to see how easily these could be merged.