Re: Class Variables - no attrAutoCompleteAfter patch

Andrew Lowe <[email protected]> Fri, 16 Feb 2007 17:23:50 +1100
Newsgroups gmane.comp.kde.devel.quanta
Message-ID <[email protected]>
Andras,
I have cleaned up the code, and implemented your suggestions.
Things should be pretty optimal, and I found some other ways to optimise...

Comments below inline...

Andras Mantia wrote:

>On Thursday 15 February 2007, Andrew Lowe wrote:
>  
>
>>You may want to autocomplete function arguments as normal variables
>>ie. when you type '$', but you do not want them as class arguments
>>ie. after the '->' so I would think we just need to remove the
>>className?
>>That should already work. Actually that non-member autocompletion is 
>>done in a different place, in the "group" autocompletion. Normal 
>>variables are added to the "variable" group. The userTagsList is only 
>>used for members. It is kind'a hack, but that is...
>>    
>>
That makes more sense now.... removed class function arguments from the 
userTagsList completly.

>  
>
>>>In the completion code, I don't understand something. You set
>>>
>>>completion.type = type[tagNameList[i]];
>>>
>>>But this will be wrong for XML, as in case of XML, type is
>>>unitialized. Shouldn't this be moved inside the
>>>+    if(completionDTD->family==Script)
>>>?
>>>
>>> 
>>>      
>>>
>>Yes, so it should - which incidently is what I moved from inside the
>>if block, when I said I had found a mistake :-)
>>    
>>
>
>I looked at your second patch and here there is:
>-    completions->append( completion );
>+    /* Author Andrew Lowe - [email protected]
>+     * Here we actually append the completion type
>+     */
>+    completion.type = type[tagNameList[i]];
>+    if(completionDTD->family==Script)
>
>So I don't understand why you think its a mistake to have that statement 
>inside the if block.
>  
>
I originally put the code their by mistake, however, as you have pointed 
out, it was correct to place it  there... I wrote the code in the if 
statement (sorting code) after putting the variable type in.  I thought 
it should be seperate because of this, however, as you point out, it 
should be there, because it makes no for XML families..

I have fixed this also

Also in SAGroupParser::parseForScriptGroup where I am checking if the 
variable is a function argument, I check if the tagStr contains an open 
and closing paretheses '(' &')' because if they do not, there is no need 
to run the loops to trim tagStr down to just one line, and test the 
variable.

I also included the diff against svn for the 
data/dtep/php/description.rc I forgot in earlier patches ( I was using 
my ~.kde/share/apps/quanta/dtep/php/ folder until just now)

Thanks..

-- 
Andrew Lowe
    System Administrator & Programmer
        Information Technology
            Manildra Group

Email:   [email protected]
Phone:   02 4423 8270
Mobile:  04 1323 8270
Fax:     02 4421 7760

_______________________________________________
quanta-devel mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/quanta-devel
class-completions.patch (text/plain, 7.2 KB)
Index: parsers/sagroupparser.cpp
===================================================================
--- parsers/sagroupparser.cpp	(revision 633713)
+++ parsers/sagroupparser.cpp	(working copy)
@@ -203,7 +203,9 @@
         if (group.appendToTags)
         {
           QTag *qTag = new QTag();
-          qTag->setName(s.left(s.find('(')));
+          // The location of the first open bracket '(', also the end of the tag name
+          int nameEnd = s.find('(');
+          qTag->setName(s.left(nameEnd));
           qTag->className = "";
           if (groupElement->parentNode)
           {
@@ -216,7 +218,61 @@
               }
             }
           }
-          m_write->userTagList.insert(s.lower(), qTag);
+           // Test for variable or function Type by checking for an opening bracket "(" used by functions
+           // and store the type in the QTag type variable.
+          bool isArgument=false;
+          if (nameEnd == -1)
+          {
+            qTag->type="variable";
+            // If this tag is a class function argument, it should not belong to the class, so we need to remove it
+            if(qTag->className.length() != 0 && tagStr.contains('(') && tagStr.contains(')'))
+            {
+            // First we want to determine the whole line the tag is on
+              QString tagWholeLineStr = tagStr;
+            // Remove lines before target line
+              while(tagWholeLineStr.length() > 0) // this stops infinit looping in case something goes wrong!
+              {
+                int firstNewline = tagWholeLineStr.find('\n');
+                if(firstNewline == -1) //no new lines so we must be on the last
+                  break; 
+                QString checkLineStr = tagWholeLineStr.mid(firstNewline+1,tagWholeLineStr.length());
+                if(checkLineStr.contains(s))
+                  tagWholeLineStr = checkLineStr;
+                else
+                  break;
+              }
+            // Remove lines after target line - essentially same as above
+              while(tagWholeLineStr.length() > 0)
+              {
+                int lastNewLine = tagWholeLineStr.findRev('\n');
+                if(lastNewLine == -1)
+                  break;
+                QString checkLineStr = tagWholeLineStr.mid(0,lastNewLine);
+                if(checkLineStr.contains(s))
+                  tagWholeLineStr = checkLineStr;
+                else
+                  break;
+              }
+            // Now we are left with the current line, lets check if the variable is inside parentheses
+              int lineOpenParenth=tagWholeLineStr.find('(');
+              if(lineOpenParenth != -1)
+              {
+                int lineCloseParenth=tagWholeLineStr.find(')');
+                if(lineCloseParenth != -1)
+                {
+                  int lineNameLocation=tagWholeLineStr.find(s);
+                  if(lineNameLocation > lineOpenParenth || lineNameLocation < lineCloseParenth) // Write the current tag to the list
+                    isArgument=true;
+                }
+              }
+            }
+          }
+          else
+          {
+            qTag->type="function";
+          }
+          if(!isArgument)
+            m_write->userTagList.insert(s.lower(), qTag);
         }
 
 
Index: src/document.cpp
===================================================================
--- src/document.cpp	(revision 633713)
+++ src/document.cpp	(working copy)
@@ -1285,6 +1285,8 @@
   completion.userdata = word + "|";
   QStringList tagNameList;
   QMap<QString, QString> comments;
+  //A QMap to hold the completion type (function/string/class/etc)
+  QMap<QString, QString> type;
   QString tagName;
   QDictIterator<QTag> it(*(completionDTD->tagsList));
   int i = 0;
@@ -1318,11 +1320,36 @@
       tagName = tag->name() + QString("%1").arg(i, 10);
       tagNameList += tagName;
       comments.insert(tagName, tag->comment);
-      i++;
+      
+       // If the completion family is script, then we want to update the tag type
+       // it appears we use "script" for adding the completionDTD->attrAutoCompleteAfter when we run the slotFilterCompletion
+       // so we will continue to use that for functions (they need the attribute added), but variables get a new type - and we do not
+       // have to auto-complete them
+      if(completionDTD->family==Script)
+      {
+        if(tag->type=="variable")
+          type.insert(tagName, tag->type);
+        else if(tag->type=="function")
+          type.insert(tagName, "script");
+        
+        // We add the type to the comment variable, so it displays on the screen, giving the user some feedback
+        if(comments[tagName].length())
+          comments[tagName] = tag->type + "\n" + comments[tagName];
+        else
+          comments[tagName] = tag->type + comments[tagName];
+        i++;
+      }
     }
   }
 
   tagNameList.sort();
+   // tagNameList is sorted above to sort the completions by name alphabetically
+   // Now we want to sort the completions by their types.
+   // We only want to do this if we are completing Script DTDs
+   // We are going to use a couple of iterators to sort the list by Type
+   // Type Sorting is as follows: 0:Other, 1:Variables, 2: Functions (script)
+  QValueList<KTextEditor::CompletionEntry>::Iterator otherIt=completions->begin();
+  QValueList<KTextEditor::CompletionEntry>::Iterator variableIt=completions->begin();
   for (uint i = 0; i < tagNameList.count(); i++)
   {
     if (completionDTD->family == Xml)
@@ -1331,10 +1358,42 @@
       completion.text = tagNameList[i];
     completion.text = completion.text.left(completion.text.length() - 10).stripWhiteSpace();
     completion.comment = comments[tagNameList[i]];
-    completions->append( completion );
+
+    if(completionDTD->family==Script)
+    {
+      // Here we actually append the completion type
+      completion.type = type[tagNameList[i]];
+      // And here is out sorting...
+      if(completion.type.contains("variable"))
+      {
+        // Insert after the last variable
+        variableIt++;
+        variableIt = completions->insert(variableIt, completion);
+      }
+      else
+      {
+        if(completion.type.contains("script"))
+        {
+          //Scripts can go at the end of the list
+          completions->append(completion);
+        }
+        else
+        {
+          // Other types go first, after the last other type
+          otherIt++;
+          otherIt = completions->insert(otherIt, completion);
+          // If we have no variables in the list, we need to point variableIt to otherIt, so they will go after the 'others'
+          if((*variableIt).text.length()==0)
+            variableIt=otherIt;
+        }
+      }
+    }
+    else
+      completions->append( completion );
   }
 
 //  completionInProgress = true;
+
   return completions;
 }
 
Index: data/dtep/php/description.rc
===================================================================
--- data/dtep/php/description.rc	(revision 633713)
+++ data/dtep/php/description.rc	(working copy)
@@ -50,6 +50,8 @@
 DefinitionRx = \$+([a-zA-Z0-9_\x7f-\xff]*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)
 UsageRx = \$+([a-zA-Z0-9_\x7f-\xff]*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)
 AutoCompleteAfter = \$+[a-zA-Z0-9_\x7f-\xff]*$
+AppendToTags = true
+ParentGroup = Classes
 
 [StructGroup_3]
 Name = Functions