work save
This commit is contained in:
parent
f10bc14f3b
commit
e8644dfd0b
|
@ -403,6 +403,7 @@ PEvalStatement CppParser::evalExpression(
|
||||||
QMutexLocker locker(&mMutex);
|
QMutexLocker locker(&mMutex);
|
||||||
if (mParsing)
|
if (mParsing)
|
||||||
return PEvalStatement();
|
return PEvalStatement();
|
||||||
|
qDebug()<<phraseExpression;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
return doEvalExpression(fileName,
|
return doEvalExpression(fileName,
|
||||||
phraseExpression,
|
phraseExpression,
|
||||||
|
@ -3385,7 +3386,7 @@ PEvalStatement CppParser::doEvalPointerToMembers(
|
||||||
scope,
|
scope,
|
||||||
previousResult,
|
previousResult,
|
||||||
freeScoped);
|
freeScoped);
|
||||||
while (pos < phraseExpression.length() ) {
|
while (pos < phraseExpression.length()) {
|
||||||
if (!currentResult)
|
if (!currentResult)
|
||||||
break;
|
break;
|
||||||
if (currentResult &&
|
if (currentResult &&
|
||||||
|
@ -3405,8 +3406,9 @@ PEvalStatement CppParser::doEvalPointerToMembers(
|
||||||
currentResult->pointerLevel++;
|
currentResult->pointerLevel++;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
currentResult=PEvalStatement();
|
break;
|
||||||
}
|
}
|
||||||
|
// qDebug()<<pos<<"pointer member end";
|
||||||
return currentResult;
|
return currentResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3459,6 +3461,7 @@ PEvalStatement CppParser::doEvalCCast(const QString &fileName,
|
||||||
//parse
|
//parse
|
||||||
int startPos = pos;
|
int startPos = pos;
|
||||||
pos++;
|
pos++;
|
||||||
|
qDebug()<<"parse type cast ()";
|
||||||
PEvalStatement evalType = doEvalExpression(
|
PEvalStatement evalType = doEvalExpression(
|
||||||
fileName,
|
fileName,
|
||||||
phraseExpression,
|
phraseExpression,
|
||||||
|
@ -3466,10 +3469,13 @@ PEvalStatement CppParser::doEvalCCast(const QString &fileName,
|
||||||
scope,
|
scope,
|
||||||
PEvalStatement(),
|
PEvalStatement(),
|
||||||
true);
|
true);
|
||||||
|
qDebug()<<pos;
|
||||||
if (pos >= phraseExpression.length() || phraseExpression[pos]!=")") {
|
if (pos >= phraseExpression.length() || phraseExpression[pos]!=")") {
|
||||||
return PEvalStatement();
|
return PEvalStatement();
|
||||||
} else if (evalType &&
|
} else if (evalType &&
|
||||||
(evalType->kind == EvalStatementKind::Type)) {
|
(evalType->kind == EvalStatementKind::Type)) {
|
||||||
|
pos++; // skip ")"
|
||||||
|
qDebug()<<"parse type cast exp";
|
||||||
//it's a type cast
|
//it's a type cast
|
||||||
result = doEvalCCast(fileName,
|
result = doEvalCCast(fileName,
|
||||||
phraseExpression,
|
phraseExpression,
|
||||||
|
@ -3477,8 +3483,10 @@ PEvalStatement CppParser::doEvalCCast(const QString &fileName,
|
||||||
scope,
|
scope,
|
||||||
previousResult,
|
previousResult,
|
||||||
freeScoped);
|
freeScoped);
|
||||||
if (result)
|
if (result) {
|
||||||
|
qDebug()<<"type cast";
|
||||||
result->assignType(evalType);
|
result->assignType(evalType);
|
||||||
|
}
|
||||||
} else //it's not a type cast
|
} else //it's not a type cast
|
||||||
result = doEvalMemberAccess(
|
result = doEvalMemberAccess(
|
||||||
fileName,
|
fileName,
|
||||||
|
@ -3495,6 +3503,11 @@ PEvalStatement CppParser::doEvalCCast(const QString &fileName,
|
||||||
scope,
|
scope,
|
||||||
previousResult,
|
previousResult,
|
||||||
freeScoped);
|
freeScoped);
|
||||||
|
if (result) {
|
||||||
|
qDebug()<<pos<<(int)result->kind<<result->baseType;
|
||||||
|
} else {
|
||||||
|
qDebug()<<"!!!!!!!!!!!not found";
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3506,6 +3519,7 @@ PEvalStatement CppParser::doEvalMemberAccess(const QString &fileName,
|
||||||
bool freeScoped)
|
bool freeScoped)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// qDebug()<<"eval member access "<<pos<<phraseExpression;
|
||||||
PEvalStatement result;
|
PEvalStatement result;
|
||||||
if (pos>=phraseExpression.length())
|
if (pos>=phraseExpression.length())
|
||||||
return result;
|
return result;
|
||||||
|
@ -3516,10 +3530,8 @@ PEvalStatement CppParser::doEvalMemberAccess(const QString &fileName,
|
||||||
scope,
|
scope,
|
||||||
previousResult,
|
previousResult,
|
||||||
freeScoped);
|
freeScoped);
|
||||||
bool isFreeScoped = freeScoped;
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return PEvalStatement();
|
return PEvalStatement();
|
||||||
pos++;
|
|
||||||
while (pos<phraseExpression.length()) {
|
while (pos<phraseExpression.length()) {
|
||||||
if (!result)
|
if (!result)
|
||||||
break;
|
break;
|
||||||
|
@ -3540,17 +3552,16 @@ PEvalStatement CppParser::doEvalMemberAccess(const QString &fileName,
|
||||||
pos++; // skip ")"
|
pos++; // skip ")"
|
||||||
result = newResult;
|
result = newResult;
|
||||||
} else if (result->kind == EvalStatementKind::Function) {
|
} else if (result->kind == EvalStatementKind::Function) {
|
||||||
doSkipInExpression("(",")");
|
doSkipInExpression(phraseExpression,pos,"(",")");
|
||||||
//function call
|
//function call
|
||||||
result->kind = EvalStatementKind::Variable;
|
result->kind = EvalStatementKind::Variable;
|
||||||
} else
|
} else
|
||||||
result = PEvalStatement();
|
result = PEvalStatement();
|
||||||
} else if (phraseExpression[pos] == "[") {
|
} else if (phraseExpression[pos] == "[") {
|
||||||
//skip to "]"
|
//skip to "]"
|
||||||
doSkipInExpression("[","]");
|
doSkipInExpression(phraseExpression,pos,"[","]");
|
||||||
//todo: STL container;
|
//todo: STL container;
|
||||||
result->pointerLevel--;
|
result->pointerLevel--;
|
||||||
return
|
|
||||||
} else if (phraseExpression[pos] == ".") {
|
} else if (phraseExpression[pos] == ".") {
|
||||||
pos++;
|
pos++;
|
||||||
result = doEvalScopeResolution(
|
result = doEvalScopeResolution(
|
||||||
|
@ -3560,6 +3571,7 @@ PEvalStatement CppParser::doEvalMemberAccess(const QString &fileName,
|
||||||
scope,
|
scope,
|
||||||
result,
|
result,
|
||||||
false);
|
false);
|
||||||
|
qDebug()<<(result!=nullptr)<<pos<<"after .";
|
||||||
} else if (phraseExpression[pos] == "->") {
|
} else if (phraseExpression[pos] == "->") {
|
||||||
pos++;
|
pos++;
|
||||||
//todo: STL container
|
//todo: STL container
|
||||||
|
@ -3574,7 +3586,7 @@ PEvalStatement CppParser::doEvalMemberAccess(const QString &fileName,
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PEvalStatement CppParser::doEvalScopeResolution(const QString &fileName,
|
PEvalStatement CppParser::doEvalScopeResolution(const QString &fileName,
|
||||||
|
@ -3584,6 +3596,7 @@ PEvalStatement CppParser::doEvalScopeResolution(const QString &fileName,
|
||||||
const PEvalStatement& previousResult,
|
const PEvalStatement& previousResult,
|
||||||
bool freeScoped)
|
bool freeScoped)
|
||||||
{
|
{
|
||||||
|
// qDebug()<<"eval scope res "<<pos<<phraseExpression;
|
||||||
PEvalStatement result;
|
PEvalStatement result;
|
||||||
if (pos>=phraseExpression.length())
|
if (pos>=phraseExpression.length())
|
||||||
return result;
|
return result;
|
||||||
|
@ -3594,7 +3607,6 @@ PEvalStatement CppParser::doEvalScopeResolution(const QString &fileName,
|
||||||
scope,
|
scope,
|
||||||
previousResult,
|
previousResult,
|
||||||
freeScoped);
|
freeScoped);
|
||||||
pos++;
|
|
||||||
while (pos<phraseExpression.length()) {
|
while (pos<phraseExpression.length()) {
|
||||||
if (phraseExpression[pos]=="::" ) {
|
if (phraseExpression[pos]=="::" ) {
|
||||||
pos++;
|
pos++;
|
||||||
|
@ -3609,6 +3621,7 @@ PEvalStatement CppParser::doEvalScopeResolution(const QString &fileName,
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// qDebug()<<pos<<"scope end";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3619,6 +3632,11 @@ PEvalStatement CppParser::doEvalTerm(const QString &fileName,
|
||||||
const PEvalStatement& previousResult,
|
const PEvalStatement& previousResult,
|
||||||
bool freeScoped)
|
bool freeScoped)
|
||||||
{
|
{
|
||||||
|
if (previousResult) {
|
||||||
|
qDebug()<<"eval term "<<pos<<phraseExpression<<previousResult->baseType<<freeScoped;
|
||||||
|
} else {
|
||||||
|
qDebug()<<"eval term "<<pos<<phraseExpression<<"no type"<<freeScoped;
|
||||||
|
}
|
||||||
PEvalStatement result;
|
PEvalStatement result;
|
||||||
if (pos>=phraseExpression.length())
|
if (pos>=phraseExpression.length())
|
||||||
return result;
|
return result;
|
||||||
|
@ -3631,58 +3649,112 @@ PEvalStatement CppParser::doEvalTerm(const QString &fileName,
|
||||||
pos++; // skip ")";
|
pos++; // skip ")";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} else if (isIdentifier(phraseExpression[pos])) {
|
} else {
|
||||||
PStatement statement;
|
int pointerLevel = 0;
|
||||||
if (freeScoped) {
|
//skip "struct", "const", "static", etc
|
||||||
if (previousResult) {
|
while(pos < phraseExpression.length()) {
|
||||||
statement = findStatementStartingFrom(
|
QString token = phraseExpression[pos];
|
||||||
fileName,
|
if (token=="*") // for expression like (const * char)?
|
||||||
phraseExpression[pos],
|
pointerLevel++;
|
||||||
previousResult->baseStatement);
|
else if (mCppTypeKeywords.contains(token)
|
||||||
} else {
|
|| !mCppKeywords.contains(token))
|
||||||
statement = findStatementStartingFrom(
|
break;
|
||||||
fileName,
|
pos++;
|
||||||
phraseExpression[pos],
|
|
||||||
scope);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!previousResult) {
|
|
||||||
statement = findStatementInScope(phraseExpression[pos],PStatement());
|
|
||||||
} else {
|
|
||||||
statement = findStatementInScope(phraseExpression[pos],previousResult->baseStatement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pos++;
|
|
||||||
if (statement) {
|
if (pos>=phraseExpression.length() || phraseExpression[pos]==")")
|
||||||
switch (statement->kind) {
|
return result;
|
||||||
case StatementKind::skNamespace:
|
if (mCppKeywords.contains(phraseExpression[pos])) {
|
||||||
result = doCreateEvalNamespace(statement);
|
result = doCreateEvalType(phraseExpression[pos]);
|
||||||
break;
|
pos++;
|
||||||
case StatementKind::skVariable:
|
} else if (isIdentifier(phraseExpression[pos])) {
|
||||||
result = doCreateEvalVariable(fileName,statement);
|
PStatement statement;
|
||||||
break;
|
if (freeScoped) {
|
||||||
case StatementKind::skEnumType:
|
if (!previousResult) {
|
||||||
case StatementKind::skClass:
|
statement = findStatementStartingFrom(
|
||||||
case StatementKind::skEnumClassType:
|
fileName,
|
||||||
case StatementKind::skTypedef:
|
phraseExpression[pos],
|
||||||
result = doCreateEvalType(fileName,statement);
|
scope);
|
||||||
break;
|
} else {
|
||||||
case StatementKind::skFunction:
|
statement = findStatementStartingFrom(
|
||||||
result = ;
|
fileName,
|
||||||
break;
|
phraseExpression[pos],
|
||||||
|
previousResult->effectiveTypeStatement);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!previousResult) {
|
||||||
|
statement = findStatementInScope(phraseExpression[pos],PStatement());
|
||||||
|
} else {
|
||||||
|
if (previousResult->effectiveTypeStatement) {
|
||||||
|
qDebug()<<phraseExpression[pos]<<previousResult->effectiveTypeStatement->fullName;
|
||||||
|
} else {
|
||||||
|
qDebug()<<phraseExpression[pos]<<"no type";
|
||||||
|
}
|
||||||
|
statement = findStatementInScope(phraseExpression[pos],previousResult->effectiveTypeStatement);
|
||||||
|
// if (!statement) {
|
||||||
|
// qDebug()<<"not found!";
|
||||||
|
// } else {
|
||||||
|
// qDebug()<<statement->fullName;
|
||||||
|
// qDebug()<<statement->kind;
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
pos++;
|
||||||
if (isTypeStatement())
|
if (statement) {
|
||||||
|
switch (statement->kind) {
|
||||||
|
case StatementKind::skNamespace:
|
||||||
|
result = doCreateEvalNamespace(statement);
|
||||||
|
break;
|
||||||
|
case StatementKind::skVariable:
|
||||||
|
case StatementKind::skParameter:
|
||||||
|
result = doCreateEvalVariable(fileName,statement);
|
||||||
|
break;
|
||||||
|
case StatementKind::skEnumType:
|
||||||
|
case StatementKind::skClass:
|
||||||
|
case StatementKind::skEnumClassType:
|
||||||
|
case StatementKind::skTypedef:
|
||||||
|
result = doCreateEvalType(fileName,statement);
|
||||||
|
break;
|
||||||
|
case StatementKind::skFunction:
|
||||||
|
result = doCreateEvalFunction(fileName,statement);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = PEvalStatement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isIntegerLiteral(phraseExpression[pos])) {
|
||||||
|
result = doCreateEvalLiteral("int");
|
||||||
|
} else if (isFloatLiteral(phraseExpression[pos])) {
|
||||||
|
result = doCreateEvalLiteral("double");
|
||||||
|
} else if (isStringLiteral(phraseExpression[pos])) {
|
||||||
|
result = doCreateEvalLiteral("char");
|
||||||
|
result->pointerLevel = 1;
|
||||||
|
} else if (isCharLiteral(phraseExpression[pos])) {
|
||||||
|
result = doCreateEvalLiteral("char");
|
||||||
|
} else
|
||||||
result = PEvalStatement();
|
result = PEvalStatement();
|
||||||
|
if (result) {
|
||||||
|
qDebug()<<"term kind:"<<(int)result->kind;
|
||||||
}
|
}
|
||||||
} else if (isIntegerLiteral(phraseExpression[pos])) {
|
if (result && result->kind == EvalStatementKind::Type) {
|
||||||
} else if (isIntegerLiteral(phraseExpression[pos])) {
|
//skip "struct", "const", "static", etc
|
||||||
} else if (isFloatLiteral(phraseExpression[pos])) {
|
while(pos < phraseExpression.length()) {
|
||||||
} else if (isStringLiteral(phraseExpression[pos])) {
|
QString token = phraseExpression[pos];
|
||||||
|
if (token=="*") // for expression like (const * char)?
|
||||||
} else
|
pointerLevel++;
|
||||||
return PStatement();
|
else if (mCppTypeKeywords.contains(token)
|
||||||
|
|| !mCppKeywords.contains(token))
|
||||||
|
break;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
result->pointerLevel = pointerLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// qDebug()<<pos<<" term end";
|
||||||
|
// if (!result) {
|
||||||
|
// qDebug()<<"not found !!!!";
|
||||||
|
// }
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PEvalStatement CppParser::doCreateEvalNamespace(const PStatement &namespaceStatement)
|
PEvalStatement CppParser::doCreateEvalNamespace(const PStatement &namespaceStatement)
|
||||||
|
@ -3692,8 +3764,8 @@ PEvalStatement CppParser::doCreateEvalNamespace(const PStatement &namespaceState
|
||||||
return std::make_shared<EvalStatement>(
|
return std::make_shared<EvalStatement>(
|
||||||
namespaceStatement->fullName,
|
namespaceStatement->fullName,
|
||||||
EvalStatementKind::Namespace,
|
EvalStatementKind::Namespace,
|
||||||
namespaceStatement,
|
PStatement(),
|
||||||
PStatement());
|
namespaceStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
PEvalStatement CppParser::doCreateEvalType(const QString& fileName,const PStatement &typeStatement)
|
PEvalStatement CppParser::doCreateEvalType(const QString& fileName,const PStatement &typeStatement)
|
||||||
|
@ -3712,19 +3784,28 @@ PEvalStatement CppParser::doCreateEvalType(const QString& fileName,const PStatem
|
||||||
return std::make_shared<EvalStatement>(
|
return std::make_shared<EvalStatement>(
|
||||||
baseType,
|
baseType,
|
||||||
EvalStatementKind::Type,
|
EvalStatementKind::Type,
|
||||||
typeStatement,
|
|
||||||
PStatement(),
|
PStatement(),
|
||||||
|
typeStatement,
|
||||||
pointerLevel
|
pointerLevel
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return std::make_shared<EvalStatement>(
|
return std::make_shared<EvalStatement>(
|
||||||
typeStatement->fullName,
|
typeStatement->fullName,
|
||||||
EvalStatementKind::Type,
|
EvalStatementKind::Type,
|
||||||
typeStatement,
|
PStatement(),
|
||||||
PStatement());
|
typeStatement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PEvalStatement CppParser::doCreateEvalType(const QString &primitiveType)
|
||||||
|
{
|
||||||
|
return std::make_shared<EvalStatement>(
|
||||||
|
primitiveType,
|
||||||
|
EvalStatementKind::Type,
|
||||||
|
PStatement(),
|
||||||
|
PStatement());
|
||||||
|
}
|
||||||
|
|
||||||
PEvalStatement CppParser::doCreateEvalVariable(const QString &fileName, PStatement varStatement)
|
PEvalStatement CppParser::doCreateEvalVariable(const QString &fileName, PStatement varStatement)
|
||||||
{
|
{
|
||||||
if (!varStatement)
|
if (!varStatement)
|
||||||
|
@ -3767,6 +3848,67 @@ PEvalStatement CppParser::doCreateEvalFunction(const QString &fileName, PStateme
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PEvalStatement CppParser::doCreateEvalLiteral(const QString &type)
|
||||||
|
{
|
||||||
|
return std::make_shared<EvalStatement>(
|
||||||
|
type,
|
||||||
|
EvalStatementKind::Literal,
|
||||||
|
PStatement(),
|
||||||
|
PStatement());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppParser::doSkipInExpression(const QStringList &expression, int &pos, const QString &startSymbol, const QString &endSymbol)
|
||||||
|
{
|
||||||
|
int level = 0;
|
||||||
|
while (pos<expression.length()) {
|
||||||
|
QString token = expression[pos];
|
||||||
|
if (token == startSymbol) {
|
||||||
|
level++;
|
||||||
|
} else if (token == endSymbol) {
|
||||||
|
level--;
|
||||||
|
if (level==0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppParser::isIdentifier(const QString &token) const
|
||||||
|
{
|
||||||
|
return (!token.isEmpty() && isLetterChar(token.front())
|
||||||
|
&& !token.contains('\"'));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppParser::isIntegerLiteral(const QString &token) const
|
||||||
|
{
|
||||||
|
if (token.isEmpty())
|
||||||
|
return false;
|
||||||
|
QChar ch = token.front();
|
||||||
|
return (ch>='0' && ch<='9' && !token.contains(".") && !token.contains("e"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppParser::isFloatLiteral(const QString &token) const
|
||||||
|
{
|
||||||
|
if (token.isEmpty())
|
||||||
|
return false;
|
||||||
|
QChar ch = token.front();
|
||||||
|
return (ch>='0' && ch<='9' && (token.contains(".") || token.contains("e")));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppParser::isStringLiteral(const QString &token) const
|
||||||
|
{
|
||||||
|
if (token.isEmpty())
|
||||||
|
return false;
|
||||||
|
return (!token.startsWith('\'') && token.contains('"'));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppParser::isCharLiteral(const QString &token) const
|
||||||
|
{
|
||||||
|
if (token.isEmpty())
|
||||||
|
return false;
|
||||||
|
return (token.startsWith('\''));
|
||||||
|
}
|
||||||
|
|
||||||
PStatement CppParser::doParseEvalTypeInfo(
|
PStatement CppParser::doParseEvalTypeInfo(
|
||||||
const QString &fileName,
|
const QString &fileName,
|
||||||
const PStatement &scope,
|
const PStatement &scope,
|
||||||
|
@ -3820,9 +3962,8 @@ PStatement CppParser::doParseEvalTypeInfo(
|
||||||
}
|
}
|
||||||
position--;
|
position--;
|
||||||
}
|
}
|
||||||
|
PStatement statement = findStatementOf(fileName,baseType,scope);
|
||||||
PStatement statement = findStatementOf(fileName,s,scope);
|
return getTypeDef(statement,fileName,baseType);
|
||||||
return getTypeDef(statement,fileName,type);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4147,12 +4288,12 @@ QString CppParser::removeArgNames(const QString &args)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isSpaceChar(const QChar &ch)
|
bool CppParser::isSpaceChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
return ch==' ' || ch =='\t';
|
return ch==' ' || ch =='\t';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isWordChar(const QChar &ch)
|
bool CppParser::isWordChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
// return (ch>= 'A' && ch<='Z')
|
// return (ch>= 'A' && ch<='Z')
|
||||||
// || (ch>='a' && ch<='z')
|
// || (ch>='a' && ch<='z')
|
||||||
|
@ -4162,7 +4303,7 @@ bool CppParser::isWordChar(const QChar &ch)
|
||||||
|| ch == '&';
|
|| ch == '&';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isLetterChar(const QChar &ch)
|
bool CppParser::isLetterChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
// return (ch>= 'A' && ch<='Z')
|
// return (ch>= 'A' && ch<='Z')
|
||||||
// || (ch>='a' && ch<='z')
|
// || (ch>='a' && ch<='z')
|
||||||
|
@ -4170,12 +4311,12 @@ bool CppParser::isLetterChar(const QChar &ch)
|
||||||
|| ch == '_';
|
|| ch == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isDigitChar(const QChar &ch)
|
bool CppParser::isDigitChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
return (ch>='0' && ch<='9');
|
return (ch>='0' && ch<='9');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isSeperator(const QChar &ch) {
|
bool CppParser::isSeperator(const QChar &ch) const {
|
||||||
switch(ch.unicode()){
|
switch(ch.unicode()){
|
||||||
case '(':
|
case '(':
|
||||||
case ';':
|
case ';':
|
||||||
|
@ -4189,7 +4330,7 @@ bool CppParser::isSeperator(const QChar &ch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isblockChar(const QChar &ch)
|
bool CppParser::isblockChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
switch(ch.unicode()){
|
switch(ch.unicode()){
|
||||||
case ';':
|
case ';':
|
||||||
|
@ -4201,7 +4342,7 @@ bool CppParser::isblockChar(const QChar &ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isInvalidVarPrefixChar(const QChar &ch)
|
bool CppParser::isInvalidVarPrefixChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
switch (ch.unicode()) {
|
switch (ch.unicode()) {
|
||||||
case '#':
|
case '#':
|
||||||
|
@ -4222,12 +4363,12 @@ bool CppParser::isInvalidVarPrefixChar(const QChar &ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isBraceChar(const QChar &ch)
|
bool CppParser::isBraceChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
return ch == '{' || ch =='}';
|
return ch == '{' || ch =='}';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isLineChar(const QChar &ch)
|
bool CppParser::isLineChar(const QChar &ch) const
|
||||||
{
|
{
|
||||||
return ch=='\n' || ch=='\r';
|
return ch=='\n' || ch=='\r';
|
||||||
}
|
}
|
||||||
|
@ -4279,7 +4420,7 @@ bool CppParser::isNotFuncArgs(const QString &args)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isNamedScope(StatementKind kind)
|
bool CppParser::isNamedScope(StatementKind kind) const
|
||||||
{
|
{
|
||||||
switch(kind) {
|
switch(kind) {
|
||||||
case StatementKind::skClass:
|
case StatementKind::skClass:
|
||||||
|
@ -4291,7 +4432,7 @@ bool CppParser::isNamedScope(StatementKind kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isTypeStatement(StatementKind kind)
|
bool CppParser::isTypeStatement(StatementKind kind) const
|
||||||
{
|
{
|
||||||
switch(kind) {
|
switch(kind) {
|
||||||
case StatementKind::skClass:
|
case StatementKind::skClass:
|
||||||
|
@ -4309,7 +4450,7 @@ void CppParser::updateSerialId()
|
||||||
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
|
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppParser::isMemberOperator(QString token)
|
bool CppParser::isMemberOperator(QString token) const
|
||||||
{
|
{
|
||||||
return mMemberOperators.contains(token);
|
return mMemberOperators.contains(token);
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public:
|
||||||
* @param token
|
* @param token
|
||||||
* @return true if it is, false if not
|
* @return true if it is, false if not
|
||||||
*/
|
*/
|
||||||
bool isMemberOperator(QString token);
|
bool isMemberOperator(QString token) const;
|
||||||
|
|
||||||
bool enabled() const;
|
bool enabled() const;
|
||||||
void setEnabled(bool newEnabled);
|
void setEnabled(bool newEnabled);
|
||||||
|
@ -266,10 +266,17 @@ private:
|
||||||
PEvalStatement doCreateEvalNamespace(const PStatement& namespaceStatement);
|
PEvalStatement doCreateEvalNamespace(const PStatement& namespaceStatement);
|
||||||
|
|
||||||
PEvalStatement doCreateEvalType(const QString& fileName,const PStatement& typeStatement);
|
PEvalStatement doCreateEvalType(const QString& fileName,const PStatement& typeStatement);
|
||||||
|
PEvalStatement doCreateEvalType(const QString& primitiveType);
|
||||||
|
|
||||||
PEvalStatement doCreateEvalVariable(const QString& fileName, PStatement varStatement);
|
PEvalStatement doCreateEvalVariable(const QString& fileName, PStatement varStatement);
|
||||||
PEvalStatement doCreateEvalFunction(const QString& fileName, PStatement funcStatement);
|
PEvalStatement doCreateEvalFunction(const QString& fileName, PStatement funcStatement);
|
||||||
|
PEvalStatement doCreateEvalLiteral(const QString& type);
|
||||||
|
void doSkipInExpression(const QStringList& expression, int&pos, const QString& startSymbol, const QString& endSymbol);
|
||||||
|
bool isIdentifier(const QString& token) const;
|
||||||
|
bool isIntegerLiteral(const QString& token) const;
|
||||||
|
bool isFloatLiteral(const QString& token) const;
|
||||||
|
bool isStringLiteral(const QString& token) const;
|
||||||
|
bool isCharLiteral(const QString& token) const;
|
||||||
PStatement doParseEvalTypeInfo(
|
PStatement doParseEvalTypeInfo(
|
||||||
const QString& fileName,
|
const QString& fileName,
|
||||||
const PStatement& scope,
|
const PStatement& scope,
|
||||||
|
@ -351,27 +358,27 @@ private:
|
||||||
|
|
||||||
QString removeArgNames(const QString& args);
|
QString removeArgNames(const QString& args);
|
||||||
|
|
||||||
bool isSpaceChar(const QChar& ch);
|
bool isSpaceChar(const QChar& ch) const;
|
||||||
|
|
||||||
bool isWordChar(const QChar& ch);
|
bool isWordChar(const QChar& ch) const;
|
||||||
|
|
||||||
bool isLetterChar(const QChar& ch);
|
bool isLetterChar(const QChar& ch) const;
|
||||||
|
|
||||||
bool isDigitChar(const QChar& ch);
|
bool isDigitChar(const QChar& ch) const;
|
||||||
|
|
||||||
/*'(', ';', ':', '{', '}', '#' */
|
/*'(', ';', ':', '{', '}', '#' */
|
||||||
bool isSeperator(const QChar& ch);
|
bool isSeperator(const QChar& ch) const;
|
||||||
|
|
||||||
/*';', '{', '}'*/
|
/*';', '{', '}'*/
|
||||||
bool isblockChar(const QChar& ch);
|
bool isblockChar(const QChar& ch) const;
|
||||||
|
|
||||||
/* '#', ',', ';', ':', '{', '}', '!', '/', '+', '-', '<', '>' */
|
/* '#', ',', ';', ':', '{', '}', '!', '/', '+', '-', '<', '>' */
|
||||||
bool isInvalidVarPrefixChar(const QChar& ch);
|
bool isInvalidVarPrefixChar(const QChar& ch) const;
|
||||||
|
|
||||||
/*'{', '}' */
|
/*'{', '}' */
|
||||||
bool isBraceChar(const QChar& ch);
|
bool isBraceChar(const QChar& ch) const;
|
||||||
|
|
||||||
bool isLineChar(const QChar& ch);
|
bool isLineChar(const QChar& ch) const;
|
||||||
|
|
||||||
bool isNotFuncArgs(const QString& args);
|
bool isNotFuncArgs(const QString& args);
|
||||||
|
|
||||||
|
@ -380,14 +387,14 @@ private:
|
||||||
* @param kind
|
* @param kind
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
bool isNamedScope(StatementKind kind);
|
bool isNamedScope(StatementKind kind) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Test if a statement is a class/struct/union/enum/enum class/typedef
|
* @brief Test if a statement is a class/struct/union/enum/enum class/typedef
|
||||||
* @param kind
|
* @param kind
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
bool isTypeStatement(StatementKind kind);
|
bool isTypeStatement(StatementKind kind) const;
|
||||||
|
|
||||||
void updateSerialId();
|
void updateSerialId();
|
||||||
|
|
||||||
|
|
|
@ -518,5 +518,5 @@ void EvalStatement::assignType(const PEvalStatement &typeStatement)
|
||||||
Q_ASSERT(typeStatement && typeStatement->kind==EvalStatementKind::Type);
|
Q_ASSERT(typeStatement && typeStatement->kind==EvalStatementKind::Type);
|
||||||
baseType = typeStatement->baseType;
|
baseType = typeStatement->baseType;
|
||||||
pointerLevel = typeStatement->pointerLevel;
|
pointerLevel = typeStatement->pointerLevel;
|
||||||
effectiveTypeStatement = typeStatement->baseStatement;
|
effectiveTypeStatement = typeStatement->effectiveTypeStatement;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,8 +103,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>683</width>
|
<width>679</width>
|
||||||
<height>533</height>
|
<height>516</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -165,9 +165,9 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnCancle">
|
<widget class="QPushButton" name="btnCancel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Cancle</string>
|
<string>Cancel</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -543,27 +543,31 @@ void CodeCompletionPopup::getCompletionFor(
|
||||||
return;
|
return;
|
||||||
if (memberExpression.length()>2)
|
if (memberExpression.length()>2)
|
||||||
return;
|
return;
|
||||||
QString scopeName = ownerExpression.join("");
|
|
||||||
PStatement scope = mCurrentStatement;//the scope the expression in
|
PStatement scope = mCurrentStatement;//the scope the expression in
|
||||||
PStatement parentTypeStatement;
|
PStatement parentTypeStatement;
|
||||||
PStatement ownerStatement = mParser->findStatementOf(
|
// QString scopeName = ownerExpression.join("");
|
||||||
fileName,
|
// PStatement ownerStatement = mParser->findStatementOf(
|
||||||
scopeName,
|
// fileName,
|
||||||
mCurrentStatement,
|
// scopeName,
|
||||||
parentTypeStatement);
|
// mCurrentStatement,
|
||||||
|
// parentTypeStatement);
|
||||||
|
PEvalStatement ownerStatement = mParser->evalExpression(fileName,
|
||||||
|
ownerExpression,
|
||||||
|
scope);
|
||||||
// qDebug()<<scopeName;
|
// qDebug()<<scopeName;
|
||||||
// qDebug()<<memberOperator;
|
// qDebug()<<memberOperator;
|
||||||
// qDebug()<<memberExpression;
|
// qDebug()<<memberExpression;
|
||||||
if(!ownerStatement ) {
|
if(!ownerStatement || !ownerStatement->effectiveTypeStatement) {
|
||||||
// qDebug()<<"not found!";
|
qDebug()<<"statement not found!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// qDebug()<<"found: "<<ownerStatement->fullName;
|
// qDebug()<<"found: "<<ownerStatement->fullName;
|
||||||
if (memberOperator == "::") {
|
if (memberOperator == "::") {
|
||||||
if (ownerStatement->kind==StatementKind::skNamespace) {
|
if (ownerStatement->kind==EvalStatementKind::Namespace) {
|
||||||
//there might be many statements corresponding to one namespace;
|
//there might be many statements corresponding to one namespace;
|
||||||
PStatementList namespaceStatementsList =
|
PStatementList namespaceStatementsList =
|
||||||
mParser->findNamespace(ownerStatement->fullName);
|
mParser->findNamespace(ownerStatement->baseType);
|
||||||
if (namespaceStatementsList) {
|
if (namespaceStatementsList) {
|
||||||
foreach (const PStatement& namespaceStatement, *namespaceStatementsList) {
|
foreach (const PStatement& namespaceStatement, *namespaceStatementsList) {
|
||||||
addChildren(namespaceStatement, fileName, line);
|
addChildren(namespaceStatement, fileName, line);
|
||||||
|
@ -581,41 +585,10 @@ void CodeCompletionPopup::getCompletionFor(
|
||||||
if (
|
if (
|
||||||
(memberOperator != "::")
|
(memberOperator != "::")
|
||||||
&& (
|
&& (
|
||||||
ownerStatement->kind == StatementKind::skVariable
|
ownerStatement->kind == EvalStatementKind::Variable)
|
||||||
|| ownerStatement->kind == StatementKind::skParameter
|
|
||||||
|| ownerStatement->kind == StatementKind::skFunction)
|
|
||||||
) {
|
) {
|
||||||
// Get type statement of current (scope) statement
|
// Get type statement of current (scope) statement
|
||||||
PStatement classTypeStatement;
|
PStatement classTypeStatement = ownerStatement->effectiveTypeStatement;
|
||||||
PStatement parentScope = ownerStatement->parentScope.lock();
|
|
||||||
if ((ownerStatement->kind == StatementKind::skFunction)
|
|
||||||
&& parentScope
|
|
||||||
&& STLContainers.contains(parentScope->fullName)
|
|
||||||
&& STLElementMethods.contains(ownerStatement->command)){
|
|
||||||
// it's an element method of STL container
|
|
||||||
// we must find the type in the template parameter
|
|
||||||
|
|
||||||
// get the function's owner variable's definition
|
|
||||||
int lastI = mParser->findLastOperator(scopeName);
|
|
||||||
QString lastScopeName = scopeName.mid(0,lastI);
|
|
||||||
PStatement lastScopeStatement =
|
|
||||||
mParser->findStatementOf(
|
|
||||||
fileName, lastScopeName,
|
|
||||||
mCurrentStatement,parentTypeStatement);
|
|
||||||
if (!lastScopeStatement)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
QString typeName =
|
|
||||||
mParser->findFirstTemplateParamOf(
|
|
||||||
fileName,lastScopeStatement->type,
|
|
||||||
lastScopeStatement->parentScope.lock());
|
|
||||||
classTypeStatement = mParser->findTypeDefinitionOf(
|
|
||||||
fileName, typeName,
|
|
||||||
lastScopeStatement->parentScope.lock());
|
|
||||||
} else
|
|
||||||
classTypeStatement=mParser->findTypeDefinitionOf(
|
|
||||||
fileName, ownerStatement->type,parentTypeStatement);
|
|
||||||
|
|
||||||
if (!classTypeStatement)
|
if (!classTypeStatement)
|
||||||
return;
|
return;
|
||||||
|
@ -625,33 +598,19 @@ void CodeCompletionPopup::getCompletionFor(
|
||||||
|| memberOperator == "->*")) {
|
|| memberOperator == "->*")) {
|
||||||
QString typeName= mParser->findFirstTemplateParamOf(
|
QString typeName= mParser->findFirstTemplateParamOf(
|
||||||
fileName,
|
fileName,
|
||||||
ownerStatement->type,
|
ownerStatement->baseType,
|
||||||
parentScope);
|
scope);
|
||||||
classTypeStatement = mParser->findTypeDefinitionOf(
|
classTypeStatement = mParser->findTypeDefinitionOf(
|
||||||
fileName,
|
fileName,
|
||||||
typeName,
|
typeName,
|
||||||
parentScope);
|
scope);
|
||||||
if (!classTypeStatement)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//is a stl container operator[]
|
|
||||||
if (STLContainers.contains(classTypeStatement->fullName)
|
|
||||||
&& scopeName.endsWith(']')) {
|
|
||||||
QString typeName= mParser->findFirstTemplateParamOf(
|
|
||||||
fileName,
|
|
||||||
ownerStatement->type,
|
|
||||||
parentScope);
|
|
||||||
classTypeStatement = mParser->findTypeDefinitionOf(
|
|
||||||
fileName,
|
|
||||||
typeName,
|
|
||||||
parentScope);
|
|
||||||
if (!classTypeStatement)
|
if (!classTypeStatement)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isIncluded(classTypeStatement->fileName) &&
|
if (!isIncluded(classTypeStatement->fileName) &&
|
||||||
!isIncluded(classTypeStatement->definitionFileName))
|
!isIncluded(classTypeStatement->definitionFileName))
|
||||||
return;
|
return;
|
||||||
if ((classTypeStatement == scopeTypeStatement) || (ownerStatement->command == "this")) {
|
if ((classTypeStatement == scopeTypeStatement) || (ownerStatement->effectiveTypeStatement->command == "this")) {
|
||||||
//we can use all members
|
//we can use all members
|
||||||
addChildren(classTypeStatement,fileName,-1);
|
addChildren(classTypeStatement,fileName,-1);
|
||||||
} else { // we can only use public members
|
} else { // we can only use public members
|
||||||
|
@ -670,59 +629,58 @@ void CodeCompletionPopup::getCompletionFor(
|
||||||
}
|
}
|
||||||
//todo friend
|
//todo friend
|
||||||
} else if ((memberOperator == "::")
|
} else if ((memberOperator == "::")
|
||||||
&& ((ownerStatement->kind == StatementKind::skEnumType)
|
&& (ownerStatement->kind == EvalStatementKind::Type)) {
|
||||||
|| (ownerStatement->kind == StatementKind::skEnumClassType))) {
|
|
||||||
//we can add all child enum definess
|
//we can add all child enum definess
|
||||||
PStatement classTypeStatement = ownerStatement;
|
PStatement classTypeStatement = ownerStatement->effectiveTypeStatement;
|
||||||
|
if (!classTypeStatement)
|
||||||
|
return;
|
||||||
if (!isIncluded(classTypeStatement->fileName) &&
|
if (!isIncluded(classTypeStatement->fileName) &&
|
||||||
!isIncluded(classTypeStatement->definitionFileName))
|
!isIncluded(classTypeStatement->definitionFileName))
|
||||||
return;
|
return;
|
||||||
const StatementMap& children =
|
if (classTypeStatement->kind == StatementKind::skEnumType
|
||||||
mParser->statementList().childrenStatements(classTypeStatement);
|
|| classTypeStatement->kind == StatementKind::skEnumClassType) {
|
||||||
foreach (const PStatement& child,children) {
|
|
||||||
addStatement(child,fileName,line);
|
|
||||||
}
|
|
||||||
} else if ((memberOperator == "::")
|
|
||||||
&& (ownerStatement->kind == StatementKind::skClass)) {
|
|
||||||
PStatement classTypeStatement = ownerStatement;
|
|
||||||
if (!isIncluded(classTypeStatement->fileName) &&
|
|
||||||
!isIncluded(classTypeStatement->definitionFileName))
|
|
||||||
return;
|
|
||||||
if (classTypeStatement == scopeTypeStatement) {
|
|
||||||
//we can use all static members
|
|
||||||
const StatementMap& children =
|
const StatementMap& children =
|
||||||
mParser->statementList().childrenStatements(classTypeStatement);
|
mParser->statementList().childrenStatements(classTypeStatement);
|
||||||
foreach (const PStatement& childStatement, children) {
|
foreach (const PStatement& child,children) {
|
||||||
if (
|
addStatement(child,fileName,line);
|
||||||
(childStatement->isStatic)
|
|
||||||
|| (childStatement->kind == StatementKind::skTypedef
|
|
||||||
|| childStatement->kind == StatementKind::skClass
|
|
||||||
|| childStatement->kind == StatementKind::skEnum
|
|
||||||
|| childStatement->kind == StatementKind::skEnumClassType
|
|
||||||
|| childStatement->kind == StatementKind::skEnumType
|
|
||||||
)) {
|
|
||||||
addStatement(childStatement,fileName,-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we can only use public static members
|
//class
|
||||||
const StatementMap& children =
|
if (classTypeStatement == scopeTypeStatement) {
|
||||||
mParser->statementList().childrenStatements(classTypeStatement);
|
//we can use all static members
|
||||||
foreach (const PStatement& childStatement,children) {
|
const StatementMap& children =
|
||||||
if (
|
mParser->statementList().childrenStatements(classTypeStatement);
|
||||||
(childStatement->isStatic)
|
foreach (const PStatement& childStatement, children) {
|
||||||
|| (childStatement->kind == StatementKind::skTypedef
|
if (
|
||||||
|| childStatement->kind == StatementKind::skClass
|
(childStatement->isStatic)
|
||||||
|| childStatement->kind == StatementKind::skEnum
|
|| (childStatement->kind == StatementKind::skTypedef
|
||||||
|| childStatement->kind == StatementKind::skEnumClassType
|
|| childStatement->kind == StatementKind::skClass
|
||||||
|| childStatement->kind == StatementKind::skEnumType
|
|| childStatement->kind == StatementKind::skEnum
|
||||||
)) {
|
|| childStatement->kind == StatementKind::skEnumClassType
|
||||||
if (childStatement->classScope == StatementClassScope::scsPublic)
|
|| childStatement->kind == StatementKind::skEnumType
|
||||||
|
)) {
|
||||||
addStatement(childStatement,fileName,-1);
|
addStatement(childStatement,fileName,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we can only use public static members
|
||||||
|
const StatementMap& children =
|
||||||
|
mParser->statementList().childrenStatements(classTypeStatement);
|
||||||
|
foreach (const PStatement& childStatement,children) {
|
||||||
|
if (
|
||||||
|
(childStatement->isStatic)
|
||||||
|
|| (childStatement->kind == StatementKind::skTypedef
|
||||||
|
|| childStatement->kind == StatementKind::skClass
|
||||||
|
|| childStatement->kind == StatementKind::skEnum
|
||||||
|
|| childStatement->kind == StatementKind::skEnumClassType
|
||||||
|
|| childStatement->kind == StatementKind::skEnumType
|
||||||
|
)) {
|
||||||
|
if (childStatement->classScope == StatementClassScope::scsPublic)
|
||||||
|
addStatement(childStatement,fileName,-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//todo friend
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue