SVN commit 634153 by amantia: Autocompletion for member variables. Patch by Andrew Lowe . Reparse the script areas before $this completion (fix needed for the above feature). M +3 -0 ChangeLog M +2 -0 data/dtep/php/description.rc M +1 -1 parsers/parser.cpp M +58 -2 parsers/sagroupparser.cpp M +2 -2 quanta.kdevelop M +66 -5 src/document.cpp --- branches/KDE/3.5/kdewebdev/quanta/ChangeLog #634152:634153 @@ -3,6 +3,9 @@ Version 3.5.7 (Release date: xx-xx-2006; Started 06-02-2006) - bugfixes: - fix directory creation when certain ftp servers are used [#141232] + - improvements: + - autocompletion for member variables. Patch by Andrew Lowe + . Version 3.5.6 (Release date: 26-01-2006; Started 12-10-2006): - bugfixes: --- branches/KDE/3.5/kdewebdev/quanta/data/dtep/php/description.rc #634152:634153 @@ -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 --- branches/KDE/3.5/kdewebdev/quanta/parsers/parser.cpp #634152:634153 @@ -1717,7 +1717,7 @@ void Parser::synchParseInDetail() { - m_saParser->parseInDetail(false); + m_saParser->parseInDetail(true); } void Parser::setSAParserEnabled(bool enabled) --- branches/KDE/3.5/kdewebdev/quanta/parsers/sagroupparser.cpp #634152:634153 @@ -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); } --- branches/KDE/3.5/kdewebdev/quanta/quanta.kdevelop #634152:634153 @@ -259,10 +259,10 @@ - + Quanta speicfic header - + A new empty C++ file. --- branches/KDE/3.5/kdewebdev/quanta/src/document.cpp #634152:634153 @@ -1199,11 +1199,11 @@ { case Xml: completion.type = "tag"; break; - case Script: completion.type = "script"; - break; + case Script: + completion.type = "script"; + break; } Node *node = parser->nodeAt(line, col); - Node *n = node; if (node && node->tag->type != Tag::XmlTag) node = node->parent; if (node && node->tag->type != Tag::XmlTag) @@ -1231,6 +1231,8 @@ { QString parentGroupStr = ""; bool classFound = false; + parser->synchParseInDetail(); + Node *n = parser->nodeAt(line, col); while (n && !classFound) { //Need to parser for groups, as the node tree is rebuilt before @@ -1285,6 +1287,8 @@ completion.userdata = word + "|"; QStringList tagNameList; QMap comments; + //A QMap to hold the completion type (function/string/class/etc) + QMap type; QString tagName; QDictIterator it(*(completionDTD->tagsList)); int i = 0; @@ -1318,11 +1322,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::Iterator otherIt=completions->begin(); + QValueList::Iterator variableIt=completions->begin(); for (uint i = 0; i < tagNameList.count(); i++) { if (completionDTD->family == Xml) @@ -1331,10 +1360,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; }