Author Topic: question on how to trigger evt(cbEVT_COMPLETE_CODE)  (Read 65289 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #15 on: August 31, 2017, 07:30:02 am »
It looks like there are some item sort issue.

I see the CC gives the suggestion list as:
Code
"
aaa(): int\n13\r
Bbb(): int\n13\r
Gethod6(): void\n13\r
Kethod1(): void\n13\r
Kethod2(): void\n13\r
Method3(): void\n13\r
method4(): void\n13\r
method5(): void\n13
"
Look, it is case insensitive, but I see in the function void AutoComplete::Select(const char *word), it use this
Code
				if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
else
cond = strncmp(word, item, lenWord);
The strncmp is used, so it cause errors, in this case, CompareNCaseInsensitive should be used.

In CC, we have a sorter:
Code
    bool isPureAlphabetical = true;
    TokenSorter sortFunctor(isPureAlphabetical);
    std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor);
But it looks like TokenSorter is always case insensitive.
Code
// priority, then alphabetical
struct TokenSorter
{
    bool& m_PureAlphabetical;

    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
    {
        m_PureAlphabetical = true;
    }

    bool operator()(const cbCodeCompletionPlugin::CCToken& a, const cbCodeCompletionPlugin::CCToken& b)
    {
        int diff = a.weight - b.weight;
        if (diff == 0)
        {
            // cannot use CmpNoCase() because it compares lower case but Scintilla compares upper
            diff = a.displayName.Upper().Cmp(b.displayName.Upper());
            if (diff == 0)
                diff = a.displayName.Cmp(b.displayName);
        }
        else
            m_PureAlphabetical = false;
        return diff < 0;
    }
};
So, we should set "case insensitive" in our CC option, otherwise, this bug happens.
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 ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #16 on: September 03, 2017, 12:05:39 am »
This bug also happens in wx 2.8.12 based CodeBlocks. The method to solve this is to sort the item list depending on the "case sensitive" option of the Editor dialog.
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 ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #17 on: September 03, 2017, 01:00:00 am »
Here are patches to fix this issue:
Code
@@ -461,26 +461,31 @@ bool CCManager::ProcessArrow(int key)
 }
 
 // priority, then alphabetical
 struct TokenSorter
 {
-    bool& m_PureAlphabetical;
+    bool& m_PureAlphabetical;  // modify the passed argument(set to false) if weight are different
+    bool m_CaseSensitive;
 
-    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
+    TokenSorter(bool& alphabetical, bool& caseSensitive): m_PureAlphabetical(alphabetical), m_CaseSensitive(caseSensitive)
     {
         m_PureAlphabetical = true;
     }
 
     bool operator()(const cbCodeCompletionPlugin::CCToken& a, const cbCodeCompletionPlugin::CCToken& b)
     {
         int diff = a.weight - b.weight;
         if (diff == 0)
         {
-            // cannot use CmpNoCase() because it compares lower case but Scintilla compares upper
-            diff = a.displayName.Upper().Cmp(b.displayName.Upper());
-            if (diff == 0)
+            if (m_CaseSensitive)
                 diff = a.displayName.Cmp(b.displayName);
+            else
+            {   // cannot use CmpNoCase() because it compares lower case but Scintilla compares upper
+                diff = a.displayName.Upper().Cmp(b.displayName.Upper());
+                if (diff == 0)
+                    diff = a.displayName.Cmp(b.displayName);
+            }
         }
         else
             m_PureAlphabetical = false;
         return diff < 0;
     }
@@ -537,11 +542,12 @@ void CCManager::OnCompleteCode(CodeBlocksEvent& event)
 
         return;
     }
 
     bool isPureAlphabetical = true;
-    TokenSorter sortFunctor(isPureAlphabetical);
+    bool isCaseSensitive = cfg->ReadBool(wxT("/case_sensitive"), false);
+    TokenSorter sortFunctor(isPureAlphabetical, isCaseSensitive);
     std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor);
     if (isPureAlphabetical)
         stc->AutoCompSetOrder(wxSCI_ORDER_PRESORTED);
     else
         stc->AutoCompSetOrder(wxSCI_ORDER_CUSTOM);
@@ -559,11 +565,11 @@ void CCManager::OnCompleteCode(CodeBlocksEvent& event)
     items.RemoveLast();
 
     if (!stc->CallTipActive() && !stc->AutoCompActive())
         m_CallTipActive = wxSCI_INVALID_POSITION;
 
-    stc->AutoCompSetIgnoreCase(!cfg->ReadBool(wxT("/case_sensitive"), false));
+    stc->AutoCompSetIgnoreCase(!isCaseSensitive);
     stc->AutoCompSetMaxHeight(14);
     stc->AutoCompSetTypeSeparator(wxT('\n'));
     stc->AutoCompSetSeparator(wxT('\r'));
     Manager::Get()->GetLogManager()->DebugLog(F(_T("CCManager::OnCompleteCode(): before calling stc->AutoCompShow()")));
     stc->AutoCompShow(tknEnd - tknStart, items);


This obeys the "case_sensitive" option setting by the user.

One question: why the m_PureAlphabetical = false, when weights are different? I think is if this is false, we can't call the Select function later, as it is not purely sorted by alphabetical.

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 Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #18 on: September 03, 2017, 06:24:50 pm »
Code
    bool isPureAlphabetical = true;
    TokenSorter sortFunctor(isPureAlphabetical);
    std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor);
    if (isPureAlphabetical)
        stc->AutoCompSetOrder(wxSCI_ORDER_PRESORTED);
    else
        stc->AutoCompSetOrder(wxSCI_ORDER_CUSTOM);
wxSCI_ORDER_CUSTOM tells scintilla to do some extra processing and maintain a search index internally so that we can supply an arbitrary order.  I suppose the cost for this extra sort is not very large compared to initially computing what tokens to even suggest, so maybe it makes sense to simplify and just always specify wxSCI_ORDER_CUSTOM.

Code
-    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
+    TokenSorter(bool& alphabetical, bool& caseSensitive): m_PureAlphabetical(alphabetical), m_CaseSensitive(caseSensitive)
Probably pass caseSensitive by value.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #19 on: September 04, 2017, 01:30:23 am »
Code
-    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
+    TokenSorter(bool& alphabetical, bool& caseSensitive): m_PureAlphabetical(alphabetical), m_CaseSensitive(caseSensitive)
Probably pass caseSensitive by value.
Thanks, I committed in r11157.

Quote
wxSCI_ORDER_CUSTOM tells scintilla to do some extra processing and maintain a search index internally...
I may need some test later. Thanks.
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 ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #20 on: September 05, 2017, 03:59:21 am »
(Also, self plug.  I cross linked our generated documentation, so wxWidgets classes link to their documentation.)
I never noticed this before, just found it now. :)
This is quite a nice feature, how do you achieve this? Thanks.
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 Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #21 on: September 05, 2017, 07:24:09 pm »
I ran doxygen for wxWidgets with GENERATE_TAGFILE enabled.  Then set TAGFILES = wxTagFile.xml=http://docs.wxwidgets.org/3.0 when building our docs.  The tricky part was that in order to match up, the tag file for wxWidgets needed to be built via the same version of doxygen as the wxWidgets team uses.

If there is interest, I could share the tag file.

Offline yvesdm3000

  • Almost regular
  • **
  • Posts: 225
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #22 on: September 07, 2017, 03:51:36 pm »
Hi,

Has anything changed related to  evt(cbEVT_COMPLETE_CODE) with latest SVN version ? When I use ClangCC and send this event, the CC window opens and closes quickly again. This has always worked correctly in 16.01

Yves
Clang based code completion for Code::Blocks:   http://github.com/yvesdm3000/ClangLib

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #23 on: September 07, 2017, 04:08:38 pm »
Hi,

Has anything changed related to  evt(cbEVT_COMPLETE_CODE) with latest SVN version ? When I use ClangCC and send this event, the CC window opens and closes quickly again. This has always worked correctly in 16.01

Yves
I have a commit to fix your described issue days before, discussions and analysis are put in this thread,  Strange it breaks something.
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.