ui: fixed autocompletion issues
* click in autocompletions list causes search * right arrow for autocompletion * changed query operator has from '>' to '.' and operator sub from '.' to '+' * fixed autocompletions to fit to query and * fixed spectral layouting endless looping on unconnected node
This commit is contained in:
@@ -28,12 +28,6 @@ void QtQueryElement::onChecked(bool)
|
||||
}
|
||||
|
||||
|
||||
void QtSmartSearchBox::search()
|
||||
{
|
||||
editTextToElement();
|
||||
MessageSearch(utility::join(m_tokens, "") + text().toStdString()).dispatch();
|
||||
}
|
||||
|
||||
QtSmartSearchBox::QtSmartSearchBox(QWidget* parent)
|
||||
: QLineEdit(parent)
|
||||
, m_allowTextChange(false)
|
||||
@@ -45,7 +39,6 @@ QtSmartSearchBox::QtSmartSearchBox(QWidget* parent)
|
||||
m_highlightRect->setGeometry(0, 0, 0, 0);
|
||||
m_highlightRect->setObjectName("search_box_highlight");
|
||||
|
||||
connect(this, SIGNAL(returnPressed()), this, SLOT(search()), Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(textEdited(const QString&)), this, SLOT(onTextEdited(const QString&)));
|
||||
connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(onTextChanged(const QString&)));
|
||||
|
||||
@@ -66,6 +59,11 @@ void QtSmartSearchBox::setAutocompletionList(const std::vector<SearchMatch>& aut
|
||||
|
||||
connect(completer, SIGNAL(matchHighlighted(const SearchMatch&)), this, SLOT(onAutocompletionHighlighted(const SearchMatch&)), Qt::DirectConnection);
|
||||
connect(completer, SIGNAL(matchActivated(const SearchMatch&)), this, SLOT(onAutocompletionActivated(const SearchMatch&)), Qt::DirectConnection);
|
||||
|
||||
if (autocompletionList.size())
|
||||
{
|
||||
m_highlightedMatch = *completer->getSearchMatchAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::setQuery(const std::string& text)
|
||||
@@ -84,14 +82,27 @@ void QtSmartSearchBox::setFocus()
|
||||
layoutElements();
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::search()
|
||||
{
|
||||
editTextToElement();
|
||||
MessageSearch(utility::join(m_tokens, "") + text().toStdString()).dispatch();
|
||||
}
|
||||
|
||||
bool QtSmartSearchBox::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->key() == Qt::Key_Tab && completer()->popup()->isVisible())
|
||||
if (keyEvent->key() == Qt::Key_Tab)
|
||||
{
|
||||
onAutocompletionActivated(m_highlightedMatch);
|
||||
if (completer()->popup()->isVisible())
|
||||
{
|
||||
searchMatchToToken(m_highlightedMatch);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestAutoCompletions();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -109,7 +120,14 @@ void QtSmartSearchBox::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
m_shiftKeyDown = event->modifiers() & Qt::ShiftModifier;
|
||||
|
||||
if (event->key() == Qt::Key_Backspace)
|
||||
if (event->key() == Qt::Key_Return)
|
||||
{
|
||||
if (!completer()->popup()->isVisible())
|
||||
{
|
||||
search();
|
||||
}
|
||||
}
|
||||
else if (event->key() == Qt::Key_Backspace)
|
||||
{
|
||||
if (hasSelectedElements())
|
||||
{
|
||||
@@ -162,9 +180,13 @@ void QtSmartSearchBox::keyPressEvent(QKeyEvent* event)
|
||||
selectAllElementsWith(false);
|
||||
layoutElements();
|
||||
}
|
||||
else if (cursorPosition() == text().size() && (text().size() || m_cursorIndex < m_elements.size()))
|
||||
else if (cursorPosition() == text().size())
|
||||
{
|
||||
if (!editTextToElement())
|
||||
if (completer()->popup()->isVisible())
|
||||
{
|
||||
searchMatchToToken(m_highlightedMatch);
|
||||
}
|
||||
else if (!editTextToElement())
|
||||
{
|
||||
moveCursor(1);
|
||||
}
|
||||
@@ -375,14 +397,11 @@ void QtSmartSearchBox::onAutocompletionHighlighted(const SearchMatch& match)
|
||||
|
||||
void QtSmartSearchBox::onAutocompletionActivated(const SearchMatch& match)
|
||||
{
|
||||
searchMatchToToken(match);
|
||||
|
||||
if (match.fullName.size())
|
||||
{
|
||||
m_oldText.clear();
|
||||
clearLineEdit();
|
||||
|
||||
std::string name = match.encodeForQuery();
|
||||
textToToken(name);
|
||||
updateElements();
|
||||
search();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,6 +462,7 @@ void QtSmartSearchBox::moveCursorTo(int target)
|
||||
{
|
||||
m_cursorIndex = target;
|
||||
layoutElements();
|
||||
hideAutoCompletions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,6 +486,19 @@ void QtSmartSearchBox::textToToken(std::string text)
|
||||
m_cursorIndex++;
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::searchMatchToToken(const SearchMatch& match)
|
||||
{
|
||||
if (match.fullName.size())
|
||||
{
|
||||
m_oldText.clear();
|
||||
clearLineEdit();
|
||||
|
||||
std::string name = match.encodeForQuery();
|
||||
textToToken(name);
|
||||
updateElements();
|
||||
}
|
||||
}
|
||||
|
||||
void QtSmartSearchBox::setEditText(const QString& text)
|
||||
{
|
||||
m_allowTextChange = true;
|
||||
|
||||
@@ -31,9 +31,6 @@ class QtSmartSearchBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
void search();
|
||||
|
||||
public:
|
||||
QtSmartSearchBox(QWidget* parent);
|
||||
virtual ~QtSmartSearchBox();
|
||||
@@ -41,6 +38,7 @@ public:
|
||||
void setAutocompletionList(const std::vector<SearchMatch>& autocompletionList);
|
||||
void setQuery(const std::string& text);
|
||||
void setFocus();
|
||||
void search();
|
||||
|
||||
protected:
|
||||
virtual bool event(QEvent *event);
|
||||
@@ -66,6 +64,7 @@ private:
|
||||
void moveCursorTo(int goal);
|
||||
|
||||
void textToToken(std::string text);
|
||||
void searchMatchToToken(const SearchMatch& match);
|
||||
void setEditText(const QString& text);
|
||||
bool editTextToElement();
|
||||
void editElement(QtQueryElement* element);
|
||||
|
||||
@@ -76,6 +76,17 @@ void GraphLayouter::layoutSpectralPrototype(std::vector<DummyNode>& nodes, const
|
||||
|
||||
MatrixDynamicBase<int> laplacian = buildLaplacianMatrix(nodes, edges);
|
||||
|
||||
// If the laplacian matrix has a zero value in it's diagonal, that means there are unconnected nodes and the spectral
|
||||
// layouting fails for some reason. In this case we switch to raster layout.
|
||||
for (unsigned int i = 0; i < laplacian.getColumnsCount(); i++)
|
||||
{
|
||||
if (laplacian.getValue(i, i) == 0)
|
||||
{
|
||||
layoutSimpleRaster(nodes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Eigen::MatrixXd degreeMatrix = Eigen::MatrixXd::Zero(laplacian.getColumnsCount(), laplacian.getRowsCount());
|
||||
Eigen::MatrixXd eigenMatrix = Eigen::MatrixXd::Zero(laplacian.getColumnsCount(), laplacian.getRowsCount());
|
||||
|
||||
|
||||
+52
-43
@@ -590,18 +590,17 @@ std::string Storage::getNameForNodeWithId(Id id) const
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SearchMatch> Storage::getAutocompletionMatches(
|
||||
const std::string& query, const std::string& word) const
|
||||
std::vector<SearchMatch> Storage::getAutocompletionMatches(const std::string& query, const std::string& word) const
|
||||
{
|
||||
SearchResults tokenResults;
|
||||
|
||||
bool usedSubquery = false;
|
||||
bool hasQueryResults = false;
|
||||
if (query.size())
|
||||
{
|
||||
usedSubquery = getSubQuerySearchResults(query, word, &tokenResults);
|
||||
hasQueryResults = getQuerySearchResults(query, word, &tokenResults);
|
||||
}
|
||||
|
||||
if (!usedSubquery && word.size())
|
||||
if (!hasQueryResults && word.size())
|
||||
{
|
||||
tokenResults = m_tokenIndex.runFuzzySearch(word);
|
||||
}
|
||||
@@ -692,28 +691,28 @@ std::shared_ptr<Graph> Storage::getGraphForActiveTokenIds(const std::vector<Id>&
|
||||
Edge* edge = dynamic_cast<Edge*>(token);
|
||||
graph->addEdgeAndAllChildrenAsPlainCopy(edge);
|
||||
}
|
||||
}
|
||||
|
||||
for(const std::pair<Id, std::shared_ptr<Node>> nodePair : graph->getNodes())
|
||||
{
|
||||
Node* node = m_graph.getNodeById(nodePair.first);
|
||||
for (const std::pair<Id, std::shared_ptr<Node>> nodePair : graph->getNodes())
|
||||
{
|
||||
Node* node = m_graph.getNodeById(nodePair.first);
|
||||
|
||||
node->forEachEdge(
|
||||
[graph](Edge* edge)
|
||||
{
|
||||
if(edge->getType() != Edge::EdgeType::EDGE_MEMBER)
|
||||
node->forEachEdge(
|
||||
[graph](Edge* edge)
|
||||
{
|
||||
Node* from = edge->getFrom();
|
||||
Node* to = edge->getTo();
|
||||
|
||||
if(graph->findNode([from](Node* node){return from->getId() == node->getId();}) != NULL
|
||||
&& graph->findNode([to](Node* node){return to->getId() == node->getId();}) != NULL)
|
||||
if (edge->getType() != Edge::EdgeType::EDGE_MEMBER)
|
||||
{
|
||||
graph->addEdge(edge);
|
||||
Node* from = edge->getFrom();
|
||||
Node* to = edge->getTo();
|
||||
|
||||
if (graph->findNode([from](Node* node){ return from->getId() == node->getId(); }) != NULL &&
|
||||
graph->findNode([to](Node* node){ return to->getId() == node->getId(); }) != NULL)
|
||||
{
|
||||
graph->addEdge(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return graph;
|
||||
@@ -1050,24 +1049,34 @@ TokenLocation* Storage::addTokenLocation(Token* token, const ParseLocation& loc,
|
||||
return location;
|
||||
}
|
||||
|
||||
bool Storage::getSubQuerySearchResults(
|
||||
const std::string& query,
|
||||
const std::string& word,
|
||||
SearchResults* results
|
||||
) const {
|
||||
bool Storage::getQuerySearchResults(const std::string& query, const std::string& word, SearchResults* results) const
|
||||
{
|
||||
std::string q = query;
|
||||
bool isCommand = false;
|
||||
|
||||
if (QueryOperator::getOperatorType(q.back()) == QueryOperator::OPERATOR_SUB)
|
||||
switch (QueryOperator::getOperatorType(q.back()))
|
||||
{
|
||||
case QueryOperator::OPERATOR_AND:
|
||||
case QueryOperator::OPERATOR_NOT:
|
||||
q.pop_back();
|
||||
}
|
||||
else if (QueryOperator::getOperatorType(q.back()) == QueryOperator::OPERATOR_HAS)
|
||||
{
|
||||
q.pop_back();
|
||||
}
|
||||
else if (QueryOperator::getOperatorType(q.back()) != QueryOperator::OPERATOR_NONE)
|
||||
{
|
||||
return false;
|
||||
|
||||
case QueryOperator::OPERATOR_HAS:
|
||||
q.pop_back();
|
||||
q.append("'member'");
|
||||
break;
|
||||
|
||||
case QueryOperator::OPERATOR_SUB:
|
||||
q.pop_back();
|
||||
break;
|
||||
|
||||
case QueryOperator::OPERATOR_COMMAND:
|
||||
isCommand = true;
|
||||
case QueryOperator::OPERATOR_NONE:
|
||||
case QueryOperator::OPERATOR_TOKEN:
|
||||
case QueryOperator::OPERATOR_GROUP_OPEN:
|
||||
case QueryOperator::OPERATOR_GROUP_CLOSE:
|
||||
break;
|
||||
}
|
||||
|
||||
QueryTree tree(q);
|
||||
@@ -1096,27 +1105,27 @@ bool Storage::getSubQuerySearchResults(
|
||||
{
|
||||
if (word.size())
|
||||
{
|
||||
if (searchNodes.size() > 1)
|
||||
{
|
||||
SearchResults res = node->runFuzzySearchOnSelf(word);
|
||||
results->insert(res.begin(), res.end());
|
||||
}
|
||||
else
|
||||
if (searchNodes.size() == 1 && !isCommand)
|
||||
{
|
||||
SearchResults res = node->runFuzzySearch(word);
|
||||
results->insert(res.begin(), res.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
SearchResults res = node->runFuzzySearchOnSelf(word);
|
||||
results->insert(res.begin(), res.end());
|
||||
}
|
||||
}
|
||||
else if (searchNodes.size() == 1)
|
||||
else if (searchNodes.size() == 1 && !isCommand)
|
||||
{
|
||||
for (const std::shared_ptr<SearchNode>& child : node->getChildren())
|
||||
{
|
||||
child->addResultsRecursive(*results, 0, child.get());
|
||||
child->addResultsRecursive(results, 1, child.get());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
node->addResultsRecursive(*results, 0, node);
|
||||
node->addResults(results, 1, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,8 +140,7 @@ private:
|
||||
Edge* addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeUsage& typeUsage);
|
||||
TokenLocation* addTokenLocation(Token* token, const ParseLocation& location, bool isScope = false);
|
||||
|
||||
bool getSubQuerySearchResults(
|
||||
const std::string& query, const std::string& word, SearchResults* results) const;
|
||||
bool getQuerySearchResults(const std::string& query, const std::string& word, SearchResults* results) const;
|
||||
|
||||
void removeNodeIfUnreferenced(Node* node);
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ void GraphFilterConductor::filter(const QueryTree* tree, const FilterableGraph*
|
||||
|
||||
void GraphFilterConductor::filterRecursively(const QueryNode* node, const FilterableGraph* in, FilterableGraph* out) const
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->isOperator())
|
||||
{
|
||||
filterOperatorNode(dynamic_cast<const QueryOperator*>(node), in, out);
|
||||
|
||||
@@ -15,8 +15,8 @@ const std::map<char, QueryOperator::OperatorType>& QueryOperator::getOperatorTyp
|
||||
operatorMap.emplace(' ', OPERATOR_NONE);
|
||||
|
||||
operatorMap.emplace('!', OPERATOR_NOT);
|
||||
operatorMap.emplace('>', OPERATOR_HAS);
|
||||
operatorMap.emplace('.', OPERATOR_SUB);
|
||||
operatorMap.emplace('.', OPERATOR_HAS);
|
||||
operatorMap.emplace('+', OPERATOR_SUB);
|
||||
operatorMap.emplace('&', OPERATOR_AND);
|
||||
operatorMap.emplace('|', OPERATOR_OR);
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ SearchResults SearchNode::runFuzzySearch(const std::string& query) const
|
||||
FuzzyMap m = n->fuzzyMatchRecursive(query, 0, 0, 0);
|
||||
for (const std::pair<size_t, const SearchNode*>& p : m)
|
||||
{
|
||||
addResultsRecursive(result, p.first, p.second);
|
||||
addResultsRecursive(&result, p.first, p.second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ SearchResults SearchNode::runFuzzySearchOnSelf(const std::string& query) const
|
||||
FuzzyMap m = fuzzyMatchRecursive(query, 0, 0, 0);
|
||||
for (const std::pair<size_t, const SearchNode*>& p : m)
|
||||
{
|
||||
addResultsRecursive(result, p.first, p.second);
|
||||
addResultsRecursive(&result, p.first, p.second);
|
||||
}
|
||||
|
||||
// TODO: Currently all matches are added to the ordered set and get compared by their fullName for alphabetical
|
||||
@@ -184,13 +184,18 @@ SearchResults SearchNode::runFuzzySearchOnSelf(const std::string& query) const
|
||||
return result;
|
||||
}
|
||||
|
||||
void SearchNode::addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const
|
||||
void SearchNode::addResults(SearchResults* results, size_t weight, const SearchNode* node) const
|
||||
{
|
||||
result.insert(SearchResult(weight, node, this));
|
||||
results->insert(SearchResult(weight, node, this));
|
||||
}
|
||||
|
||||
void SearchNode::addResultsRecursive(SearchResults* results, size_t weight, const SearchNode* node) const
|
||||
{
|
||||
addResults(results, weight, node);
|
||||
|
||||
for (std::shared_ptr<SearchNode> n: node->m_nodes)
|
||||
{
|
||||
addResultsRecursive(result, weight, n.get());
|
||||
addResultsRecursive(results, weight, n.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,8 @@ public:
|
||||
SearchResults runFuzzySearch(const std::string& query) const;
|
||||
SearchResults runFuzzySearchOnSelf(const std::string& query) const;
|
||||
|
||||
void addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const;
|
||||
void addResults(SearchResults* results, size_t weight, const SearchNode* node) const;
|
||||
void addResultsRecursive(SearchResults* results, size_t weight, const SearchNode* node) const;
|
||||
|
||||
private:
|
||||
typedef std::multimap<size_t, const SearchNode*> FuzzyMap;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "data/search/SearchResult.h"
|
||||
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
#include "data/search/SearchNode.h"
|
||||
|
||||
SearchResult::SearchResult()
|
||||
@@ -20,5 +22,5 @@ bool SearchResult::operator()(const SearchResult& lhs, const SearchResult& rhs)
|
||||
return lhs.weight > rhs.weight;
|
||||
}
|
||||
|
||||
return lhs.node->getFullName() < rhs.node->getFullName();
|
||||
return utility::toLowerCase(lhs.node->getFullName()) < utility::toLowerCase(rhs.node->getFullName());
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
namespace utility
|
||||
@@ -117,6 +118,13 @@ namespace utility
|
||||
return res.first == prefix.end();
|
||||
}
|
||||
|
||||
std::string toLowerCase(const std::string& in)
|
||||
{
|
||||
std::string out;
|
||||
std::transform(in.begin(), in.end(), std::back_inserter(out), tolower);
|
||||
return out;
|
||||
}
|
||||
|
||||
bool equalsCaseInsensitive(const std::string& a, const std::string& b)
|
||||
{
|
||||
if (a.size() == b.size())
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace utility
|
||||
|
||||
bool isPrefix(const std::string& prefix, const std::string& text);
|
||||
|
||||
std::string toLowerCase(const std::string& in);
|
||||
bool equalsCaseInsensitive(const std::string& a, const std::string& b);
|
||||
|
||||
std::string replace(std::string str, const std::string& from, const std::string& to);
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
void test_operator_sub()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("'class'.'base'"),
|
||||
printedFilteredTestGraph("'class''base'"),
|
||||
|
||||
"1 nodes: class:A\n"
|
||||
"0 edges:\n"
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
void test_operator_has()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("\"A\">'field'"),
|
||||
printedFilteredTestGraph("\"A\".'field'"),
|
||||
|
||||
"1 nodes: field:A::count\n"
|
||||
"0 edges:\n"
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
void test_operator_group()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("('static'|'const').'public'"),
|
||||
printedFilteredTestGraph("('static'|'const')'public'"),
|
||||
|
||||
"1 nodes: method:A::getCount\n"
|
||||
"0 edges:\n"
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
|
||||
"A \" INVALID\n"
|
||||
" \"A\"\n"
|
||||
". IMPLICIT\n"
|
||||
"+ IMPLICIT\n"
|
||||
" \"\"\n"
|
||||
);
|
||||
}
|
||||
@@ -189,11 +189,11 @@ public:
|
||||
void test_operator_has_query()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedQueryTree("\"A\">\"B\""),
|
||||
printedQueryTree("\"A\".\"B\""),
|
||||
|
||||
"\"A\" > \"B\"\n"
|
||||
"\"A\" . \"B\"\n"
|
||||
" \"A\"\n"
|
||||
">\n"
|
||||
".\n"
|
||||
" \"B\"\n"
|
||||
);
|
||||
}
|
||||
@@ -276,7 +276,7 @@ public:
|
||||
|
||||
"\"A\" ( \"B\" )\n"
|
||||
" \"A\"\n"
|
||||
". IMPLICIT\n"
|
||||
"+ IMPLICIT\n"
|
||||
" (\"B\")\n"
|
||||
);
|
||||
}
|
||||
@@ -284,12 +284,12 @@ public:
|
||||
void test_operator_precedence_not_before_has()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedQueryTree("!'struct'.!'const'"),
|
||||
printedQueryTree("!'struct'+!'const'"),
|
||||
|
||||
"! 'struct' . ! 'const'\n"
|
||||
"! 'struct' + ! 'const'\n"
|
||||
" !\n"
|
||||
" 'struct'\n"
|
||||
".\n"
|
||||
"+\n"
|
||||
" !\n"
|
||||
" 'const'\n"
|
||||
);
|
||||
@@ -298,13 +298,13 @@ public:
|
||||
void test_operator_precedence_has_before_sub()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedQueryTree("'namespace'>'class'.'base'"),
|
||||
printedQueryTree("'namespace'.'class'+'base'"),
|
||||
|
||||
"'namespace' > 'class' . 'base'\n"
|
||||
"'namespace' . 'class' + 'base'\n"
|
||||
" 'namespace'\n"
|
||||
" >\n"
|
||||
" .\n"
|
||||
" 'class'\n"
|
||||
".\n"
|
||||
"+\n"
|
||||
" 'base'\n"
|
||||
);
|
||||
}
|
||||
@@ -312,11 +312,11 @@ public:
|
||||
void test_operator_precedence_has_before_or()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedQueryTree("'class'>'method'|'field'"),
|
||||
printedQueryTree("'class'.'method'|'field'"),
|
||||
|
||||
"'class' > 'method' | 'field'\n"
|
||||
"'class' . 'method' | 'field'\n"
|
||||
" 'class'\n"
|
||||
" >\n"
|
||||
" .\n"
|
||||
" 'method'\n"
|
||||
"|\n"
|
||||
" 'field'\n"
|
||||
@@ -326,22 +326,22 @@ public:
|
||||
void test_operator_precedence_respects_groups()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedQueryTree("'namespace'.('class'>'method')"),
|
||||
printedQueryTree("'namespace'+('class'.'method')"),
|
||||
|
||||
"'namespace' . ( 'class' > 'method' )\n"
|
||||
"'namespace' + ( 'class' . 'method' )\n"
|
||||
" 'namespace'\n"
|
||||
".\n"
|
||||
"+\n"
|
||||
" 'class'\n"
|
||||
" (>)\n"
|
||||
" (.)\n"
|
||||
" 'method'\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(
|
||||
printedQueryTree("'class'>('method'|'field')"),
|
||||
printedQueryTree("'class'.('method'|'field')"),
|
||||
|
||||
"'class' > ( 'method' | 'field' )\n"
|
||||
"'class' . ( 'method' | 'field' )\n"
|
||||
" 'class'\n"
|
||||
">\n"
|
||||
".\n"
|
||||
" 'method'\n"
|
||||
" (|)\n"
|
||||
" 'field'\n"
|
||||
@@ -351,15 +351,15 @@ public:
|
||||
void test_spaces_get_stripped_out_of_query()
|
||||
{
|
||||
TS_ASSERT_EQUALS(
|
||||
printedQueryTree(" \"Field \">('method' | 'field') .'const' | 'public' "),
|
||||
printedQueryTree(" \"Field \".('method' | 'field') +'const' | 'public' "),
|
||||
|
||||
"\"Field\" > ( 'method' | 'field' ) . 'const' | 'public'\n"
|
||||
"\"Field\" . ( 'method' | 'field' ) + 'const' | 'public'\n"
|
||||
" \"Field\"\n"
|
||||
" >\n"
|
||||
" .\n"
|
||||
" 'method'\n"
|
||||
" (|)\n"
|
||||
" 'field'\n"
|
||||
" .\n"
|
||||
" +\n"
|
||||
" 'const'\n"
|
||||
"|\n"
|
||||
" 'public'\n"
|
||||
|
||||
@@ -212,6 +212,13 @@ public:
|
||||
TS_ASSERT(!utility::isPrefix(bar, foo));
|
||||
}
|
||||
|
||||
void test_to_lower_case()
|
||||
{
|
||||
TS_ASSERT_EQUALS("foobar", utility::toLowerCase("FooBar"));
|
||||
TS_ASSERT_EQUALS("foobar", utility::toLowerCase("FOOBAR"));
|
||||
TS_ASSERT_EQUALS("foobar", utility::toLowerCase("foobar"));
|
||||
}
|
||||
|
||||
void test_equals_case_insensitive_with_different_cases()
|
||||
{
|
||||
const std::string foo = "FooBar";
|
||||
|
||||
Reference in New Issue
Block a user