diff options
Diffstat (limited to 'quanta/parsers/sagroupparser.cpp')
-rw-r--r-- | quanta/parsers/sagroupparser.cpp | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/quanta/parsers/sagroupparser.cpp b/quanta/parsers/sagroupparser.cpp new file mode 100644 index 00000000..77698a45 --- /dev/null +++ b/quanta/parsers/sagroupparser.cpp @@ -0,0 +1,311 @@ +/*************************************************************************** + sagroupparser.cpp - description + ------------------- + begin : Wed Feb 11 2004 + copyright : (C) 2004 Andras Mantia <amantia@kde.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +//qt includes +#include <qtimer.h> +#include <qvaluelist.h> + +//kde includes +#include <kdebug.h> +#include <kdirwatch.h> +#include <kurl.h> + +//own includes +#include "sagroupparser.h" +#include "saparser.h" +#include "document.h" +#include "node.h" +#include "parsercommon.h" +#include "qextfileinfo.h" +#include "quantacommon.h" +#include "resource.h" +#include "tag.h" + +extern GroupElementMapList globalGroupMap; + +SAGroupParser::SAGroupParser(SAParser *parent, Document *write, Node *startNode, Node *endNode, bool synchronous, bool parsingLastNode, bool paringLastGroup) +{ + g_node = startNode; + g_endNode = endNode; + m_synchronous = synchronous; + m_lastGroupParsed = paringLastGroup; + m_parsingLastNode = parsingLastNode; + m_parent = parent; + m_write = write; + m_count = 0; + m_parseForGroupTimer = new QTimer(this); + connect(m_parseForGroupTimer, SIGNAL(timeout()), this, SLOT(slotParseForScriptGroup())); +} + +void SAGroupParser::slotParseForScriptGroup() +{ +#ifdef DEBUG_PARSER + //kdDebug(24001) << "slotParseForScriptGroup. Synch: " << m_synchronous << endl; +#endif + if ((m_parent && !m_parent->parsingEnabled()) || (!baseNode && !m_synchronous)) + { +#ifdef DEBUG_PARSER + kdDebug(24001) << "slotParseForScriptGroup aborted. Synch: " << m_synchronous << endl; +#endif + return; + } + + if (g_node && g_node != g_endNode ) + { + if (g_node->tag && (g_node->tag->type == Tag::Text || g_node->tag->type == Tag::ScriptStructureBegin)) + parseForScriptGroup(g_node); + g_node = g_node->nextSibling(); + if (m_synchronous) + { + slotParseForScriptGroup(); + return; + } + else + { +#ifdef DEBUG_PARSER + //kdDebug(24001) << "Calling slotParseForScriptGroup from slotParseForScriptGroup." << endl; +#endif + m_parseForGroupTimer->start(0, true); + } + } else + { +#ifdef DEBUG_PARSER + kdDebug(24001) << "slotParseForScriptGroup done." << endl; +#endif + if (m_lastGroupParsed && m_parsingLastNode && !m_synchronous) + { + if (m_lastGroupParsed) + { +#ifdef DEBUG_PARSER +// kdDebug(24000) << "Calling cleanGroups from SAGroupParser::slotParseForScriptGroup" << endl; + kdDebug(24001) << m_count << " GroupElement created." << endl; +#endif + emit cleanGroups(); + m_lastGroupParsed = false; + } +#ifdef DEBUG_PARSER + kdDebug(24001) << "Emitting rebuildStructureTree from slotParseForScriptGroup." << endl; +#endif + emit rebuildStructureTree(true); + } + } +} + +void SAGroupParser::parseForScriptGroup(Node *node) +{ +#ifdef DEBUG_PARSER + QTime t; + t.start(); +#endif + + int bl, bc, el, ec; + int pos; + QString title; + QString tmpStr; + StructTreeGroup group; + GroupElement *groupElement; + GroupElementList* groupElementList; + KURL baseURL = QExtFileInfo::path(m_write->url()); + QString str = node->tag->cleanStr; + QString tagStr = node->tag->tagStr(); + const DTDStruct* dtd = node->tag->dtd(); + node->tag->beginPos(bl, bc); + QValueList<StructTreeGroup>::ConstIterator it; + for (it = dtd->structTreeGroups.begin(); it != dtd->structTreeGroups.end(); ++it) + { + group = *it; + if (!group.hasDefinitionRx || + node->tag->type == Tag::XmlTag || + node->tag->type == Tag::XmlTagEnd || + node->tag->type == Tag::Comment || + node->tag->type == Tag::Empty || + ( group.tagType != Tag::Text && node->tag->type != group.tagType) + ) + continue; + pos = 0; + group.definitionRx.setMinimal(group.isMinimalDefinitionRx); + while (pos != -1) + { + pos = group.definitionRx.search(str, pos); + if (pos != -1) //the Node is part of this group + { + title = tagStr.mid(pos, group.definitionRx.matchedLength()); + node->tag->beginPos(bl, bc); + tmpStr = tagStr.left(pos); + int newLines = tmpStr.contains('\n'); + bl += newLines; + int l = tmpStr.findRev('\n'); //the last EOL + bc = (l == -1) ? bc + pos : pos - l - 1; + newLines = title.contains('\n'); + l = title.length(); + el = bl + newLines; + ec = (newLines > 0) ? l - title.findRev('\n') : bc + l - 1; + pos += l; + AreaStruct area(bl, bc, el, ec); + //get the list of elements which are present in this group and + //have the same title. For example get the list of all group + //element which are variable and the matched string was "$i" + int cap1Pos = str.find(group.definitionRx.cap(1)); + QString s = tagStr.mid(cap1Pos, group.definitionRx.cap(1).length()); + groupElementList = & (globalGroupMap[group.name + "|" + s]); + //Create a new tag which point to the exact location of the matched string. + //For example when the group defined PHP variables it + //points to "$i" in a node which originally contained "print $i + 1" + Tag *newTag = new Tag(*node->tag); + newTag->setTagPosition(area); + newTag->setStr(title); + newTag->name = s; + + groupElement = new GroupElement; + groupElement->deleted = false; + groupElement->tag = newTag; + groupElement->node = node; + groupElement->group = const_cast<StructTreeGroup*>(&(*it)); + //Find out if the current node is inside a script structure or not. + //This is used to define local/global scope of the group elements. + Node *tmpNode = node; + while (tmpNode && tmpNode->tag->dtd() == dtd && tmpNode->tag->type != Tag::ScriptStructureBegin) + { + tmpNode = tmpNode->parent; + } + if (tmpNode && tmpNode->tag->type == Tag::ScriptStructureBegin) + { + groupElement->parentNode = tmpNode; + } else + { + groupElement->parentNode = 0L; + } + groupElement->global = true; + tmpNode = node->parent; + while (tmpNode && tmpNode->tag->dtd() == dtd) + { + if ( tmpNode->tag->type == Tag::ScriptStructureBegin && tmpNode->tag->dtd()->localScopeKeywordsRx.search(tmpNode->tag->cleanStr) != -1) + { + groupElement->global = false; + groupElement->parentNode = tmpNode; + break; + } + tmpNode = tmpNode->parent; + } + + if (group.appendToTags) + { + QTag *qTag = new QTag(); + // 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) + { + for (GroupElementList::ConstIterator it2 = groupElement->parentNode->m_groupElements.constBegin(); it2 != groupElement->parentNode->m_groupElements.constEnd(); ++it2) + { + if ((*it2)->group->name == group.parentGroup) + { + qTag->className = (*it2)->tag->name; + break; + } + } + } + // 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.replace(s.lower(), qTag); + } + + + if (!group.typeRx.pattern().isEmpty() && group.typeRx.search(title) != -1) + groupElement->type = group.typeRx.cap(1); +#ifdef DEBUG_PARSER + kdDebug(24001) << "GroupElement created: " <<groupElement << " "<< groupElement->tag->area().bLine << " " << groupElement->tag->area().bCol << " "<< groupElement->tag->area().eLine << " "<< groupElement->tag->area().eCol << " " << groupElement->tag->tagStr() << " " << groupElement->type << endl; +#endif + //store the pointer to the group element list where this node was put + //used to clear the corresponding entry from the group element lists + //when the node is deleted (eg. $i was deleted, so it should be deleted + //from the "variables | $i" group element list as well) + node->m_groupElements.append(groupElement); + groupElementList->append(groupElement); + m_count++; + //if a filename may be present in the title, extract it + if (group.hasFileName && group.parseFile) + { + s.remove(group.fileNameRx); + KURL url; + QuantaCommon::setUrl(url, s.stripWhiteSpace()); + url = QExtFileInfo::toAbsolute(url, baseURL); + ParserCommon::includedFiles += url.path(); + ParserCommon::includedFilesDTD.append(dtd); + ParserCommon::includeWatch->addFile(url.path()); + } + } + } + } +#ifdef DEBUG_PARSER + if (t.elapsed() > 10) + kdDebug(24001) << "Done: " << t.elapsed() << endl; +#endif +} + +#include "sagroupparser.moc" |