Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
fefd72b2
Commit
fefd72b2
authored
Oct 27, 2009
by
Roberto Raggi
Browse files
Introduced CPlusPlus::FindUsages.
parent
83a7e0f5
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/libs/cplusplus/FindUsages.cpp
0 → 100644
View file @
fefd72b2
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "FindUsages.h"
#include "TypeOfExpression.h"
#include <Control.h>
#include <Literals.h>
#include <Names.h>
#include <Symbols.h>
#include <AST.h>
#include <QtCore/QDir>
using
namespace
CPlusPlus
;
FindUsages
::
FindUsages
(
Document
::
Ptr
doc
,
const
Snapshot
&
snapshot
,
QFutureInterface
<
Usage
>
*
future
)
:
ASTVisitor
(
doc
->
control
()),
_future
(
future
),
_doc
(
doc
),
_snapshot
(
snapshot
),
_source
(
_doc
->
source
()),
_sem
(
doc
->
control
()),
_inSimpleDeclaration
(
0
)
{
_snapshot
.
insert
(
_doc
);
}
void
FindUsages
::
setGlobalNamespaceBinding
(
NamespaceBindingPtr
globalNamespaceBinding
)
{
_globalNamespaceBinding
=
globalNamespaceBinding
;
}
QList
<
int
>
FindUsages
::
operator
()(
Symbol
*
symbol
,
Identifier
*
id
,
AST
*
ast
)
{
_references
.
clear
();
_declSymbol
=
symbol
;
_id
=
id
;
_exprDoc
=
Document
::
create
(
"<references>"
);
accept
(
ast
);
return
_references
;
}
QString
FindUsages
::
matchingLine
(
const
Token
&
tk
)
const
{
const
char
*
beg
=
_source
.
constData
();
const
char
*
cp
=
beg
+
tk
.
offset
;
for
(;
cp
!=
beg
-
1
;
--
cp
)
{
if
(
*
cp
==
'\n'
)
break
;
}
++
cp
;
const
char
*
lineEnd
=
cp
+
1
;
for
(;
*
lineEnd
;
++
lineEnd
)
{
if
(
*
lineEnd
==
'\n'
)
break
;
}
const
QString
matchingLine
=
QString
::
fromUtf8
(
cp
,
lineEnd
-
cp
);
return
matchingLine
;
}
void
FindUsages
::
reportResult
(
unsigned
tokenIndex
,
const
QList
<
Symbol
*>
&
candidates
)
{
const
bool
isStrongResult
=
checkCandidates
(
candidates
);
if
(
isStrongResult
)
reportResult
(
tokenIndex
);
}
void
FindUsages
::
reportResult
(
unsigned
tokenIndex
)
{
const
Token
&
tk
=
tokenAt
(
tokenIndex
);
const
QString
lineText
=
matchingLine
(
tk
);
unsigned
line
,
col
;
getTokenStartPosition
(
tokenIndex
,
&
line
,
&
col
);
if
(
col
)
--
col
;
// adjust the column position.
const
int
len
=
tk
.
f
.
length
;
if
(
_future
)
{
const
QString
path
=
QDir
::
toNativeSeparators
(
_doc
->
fileName
());
_future
->
reportResult
(
Usage
(
path
,
line
,
lineText
,
col
,
len
));
}
_references
.
append
(
tokenIndex
);
}
bool
FindUsages
::
checkCandidates
(
const
QList
<
Symbol
*>
&
candidates
)
const
{
if
(
Symbol
*
canonicalSymbol
=
LookupContext
::
canonicalSymbol
(
candidates
,
_globalNamespaceBinding
.
data
()))
{
#if 0
qDebug() << "*** canonical symbol:" << canonicalSymbol->fileName()
<< canonicalSymbol->line() << canonicalSymbol->column()
<< "candidates:" << candidates.size();
#endif
return
checkSymbol
(
canonicalSymbol
);
}
return
false
;
}
bool
FindUsages
::
checkScope
(
Symbol
*
symbol
,
Symbol
*
otherSymbol
)
const
{
if
(
!
(
symbol
&&
otherSymbol
))
return
false
;
else
if
(
symbol
->
scope
()
==
otherSymbol
->
scope
())
return
true
;
else
if
(
symbol
->
name
()
&&
otherSymbol
->
name
())
{
if
(
!
symbol
->
name
()
->
isEqualTo
(
otherSymbol
->
name
()))
return
false
;
}
else
if
(
symbol
->
name
()
!=
otherSymbol
->
name
())
{
return
false
;
}
return
checkScope
(
symbol
->
enclosingSymbol
(),
otherSymbol
->
enclosingSymbol
());
}
bool
FindUsages
::
checkSymbol
(
Symbol
*
symbol
)
const
{
if
(
!
symbol
)
{
return
false
;
}
else
if
(
symbol
==
_declSymbol
)
{
return
true
;
}
else
if
(
symbol
->
line
()
==
_declSymbol
->
line
()
&&
symbol
->
column
()
==
_declSymbol
->
column
())
{
if
(
!
qstrcmp
(
symbol
->
fileName
(),
_declSymbol
->
fileName
()))
return
true
;
}
else
if
(
symbol
->
isForwardClassDeclaration
()
&&
(
_declSymbol
->
isClass
()
||
_declSymbol
->
isForwardClassDeclaration
()))
{
return
checkScope
(
symbol
,
_declSymbol
);
}
else
if
(
_declSymbol
->
isForwardClassDeclaration
()
&&
(
symbol
->
isClass
()
||
symbol
->
isForwardClassDeclaration
()))
{
return
checkScope
(
symbol
,
_declSymbol
);
}
return
false
;
}
LookupContext
FindUsages
::
currentContext
(
AST
*
ast
)
{
unsigned
line
,
column
;
getTokenStartPosition
(
ast
->
firstToken
(),
&
line
,
&
column
);
Symbol
*
lastVisibleSymbol
=
_doc
->
findSymbolAt
(
line
,
column
);
if
(
lastVisibleSymbol
&&
lastVisibleSymbol
==
_previousContext
.
symbol
())
return
_previousContext
;
LookupContext
ctx
(
lastVisibleSymbol
,
_exprDoc
,
_doc
,
_snapshot
);
_previousContext
=
ctx
;
return
ctx
;
}
void
FindUsages
::
ensureNameIsValid
(
NameAST
*
ast
)
{
if
(
ast
&&
!
ast
->
name
)
ast
->
name
=
_sem
.
check
(
ast
,
/*scope = */
0
);
}
bool
FindUsages
::
visit
(
MemInitializerAST
*
ast
)
{
if
(
ast
->
name
&&
ast
->
name
->
asSimpleName
()
!=
0
)
{
ensureNameIsValid
(
ast
->
name
);
SimpleNameAST
*
simple
=
ast
->
name
->
asSimpleName
();
if
(
identifier
(
simple
->
identifier_token
)
==
_id
)
{
LookupContext
context
=
currentContext
(
ast
);
const
QList
<
Symbol
*>
candidates
=
context
.
resolve
(
simple
->
name
);
reportResult
(
simple
->
identifier_token
,
candidates
);
}
}
accept
(
ast
->
expression
);
return
false
;
}
bool
FindUsages
::
visit
(
PostfixExpressionAST
*
ast
)
{
_postfixExpressionStack
.
append
(
ast
);
return
true
;
}
void
FindUsages
::
endVisit
(
PostfixExpressionAST
*
)
{
_postfixExpressionStack
.
removeLast
();
}
bool
FindUsages
::
visit
(
MemberAccessAST
*
ast
)
{
if
(
ast
->
member_name
)
{
if
(
SimpleNameAST
*
simple
=
ast
->
member_name
->
asSimpleName
())
{
if
(
identifier
(
simple
->
identifier_token
)
==
_id
)
{
Q_ASSERT
(
!
_postfixExpressionStack
.
isEmpty
());
checkExpression
(
_postfixExpressionStack
.
last
()
->
firstToken
(),
simple
->
identifier_token
);
return
false
;
}
}
}
return
true
;
}
void
FindUsages
::
checkExpression
(
unsigned
startToken
,
unsigned
endToken
)
{
const
unsigned
begin
=
tokenAt
(
startToken
).
begin
();
const
unsigned
end
=
tokenAt
(
endToken
).
end
();
const
QString
expression
=
_source
.
mid
(
begin
,
end
-
begin
);
// qDebug() << "*** check expression:" << expression;
TypeOfExpression
typeofExpression
;
typeofExpression
.
setSnapshot
(
_snapshot
);
unsigned
line
,
column
;
getTokenStartPosition
(
startToken
,
&
line
,
&
column
);
Symbol
*
lastVisibleSymbol
=
_doc
->
findSymbolAt
(
line
,
column
);
const
QList
<
TypeOfExpression
::
Result
>
results
=
typeofExpression
(
expression
,
_doc
,
lastVisibleSymbol
,
TypeOfExpression
::
Preprocess
);
QList
<
Symbol
*>
candidates
;
foreach
(
TypeOfExpression
::
Result
r
,
results
)
{
FullySpecifiedType
ty
=
r
.
first
;
Symbol
*
lastVisibleSymbol
=
r
.
second
;
candidates
.
append
(
lastVisibleSymbol
);
}
reportResult
(
endToken
,
candidates
);
}
bool
FindUsages
::
visit
(
QualifiedNameAST
*
ast
)
{
for
(
NestedNameSpecifierAST
*
nested_name_specifier
=
ast
->
nested_name_specifier
;
nested_name_specifier
;
nested_name_specifier
=
nested_name_specifier
->
next
)
{
if
(
NameAST
*
class_or_namespace_name
=
nested_name_specifier
->
class_or_namespace_name
)
{
SimpleNameAST
*
simple_name
=
class_or_namespace_name
->
asSimpleName
();
TemplateIdAST
*
template_id
=
0
;
if
(
!
simple_name
)
{
template_id
=
class_or_namespace_name
->
asTemplateId
();
if
(
template_id
)
{
for
(
TemplateArgumentListAST
*
template_arguments
=
template_id
->
template_arguments
;
template_arguments
;
template_arguments
=
template_arguments
->
next
)
{
accept
(
template_arguments
->
template_argument
);
}
}
}
if
(
simple_name
||
template_id
)
{
const
unsigned
identifier_token
=
simple_name
?
simple_name
->
identifier_token
:
template_id
->
identifier_token
;
if
(
identifier
(
identifier_token
)
==
_id
)
checkExpression
(
ast
->
firstToken
(),
identifier_token
);
}
}
}
if
(
NameAST
*
unqualified_name
=
ast
->
unqualified_name
)
{
unsigned
identifier_token
=
0
;
if
(
SimpleNameAST
*
simple_name
=
unqualified_name
->
asSimpleName
())
identifier_token
=
simple_name
->
identifier_token
;
else
if
(
DestructorNameAST
*
dtor_name
=
unqualified_name
->
asDestructorName
())
identifier_token
=
dtor_name
->
identifier_token
;
TemplateIdAST
*
template_id
=
0
;
if
(
!
identifier_token
)
{
template_id
=
unqualified_name
->
asTemplateId
();
if
(
template_id
)
{
identifier_token
=
template_id
->
identifier_token
;
for
(
TemplateArgumentListAST
*
template_arguments
=
template_id
->
template_arguments
;
template_arguments
;
template_arguments
=
template_arguments
->
next
)
{
accept
(
template_arguments
->
template_argument
);
}
}
}
if
(
identifier_token
&&
identifier
(
identifier_token
)
==
_id
)
checkExpression
(
ast
->
firstToken
(),
identifier_token
);
}
return
false
;
}
bool
FindUsages
::
visit
(
EnumeratorAST
*
ast
)
{
Identifier
*
id
=
identifier
(
ast
->
identifier_token
);
if
(
id
==
_id
)
{
LookupContext
context
=
currentContext
(
ast
);
const
QList
<
Symbol
*>
candidates
=
context
.
resolve
(
control
()
->
nameId
(
id
));
reportResult
(
ast
->
identifier_token
,
candidates
);
}
accept
(
ast
->
expression
);
return
false
;
}
bool
FindUsages
::
visit
(
SimpleNameAST
*
ast
)
{
Identifier
*
id
=
identifier
(
ast
->
identifier_token
);
if
(
id
==
_id
)
{
LookupContext
context
=
currentContext
(
ast
);
const
QList
<
Symbol
*>
candidates
=
context
.
resolve
(
ast
->
name
);
reportResult
(
ast
->
identifier_token
,
candidates
);
}
return
false
;
}
bool
FindUsages
::
visit
(
DestructorNameAST
*
ast
)
{
Identifier
*
id
=
identifier
(
ast
->
identifier_token
);
if
(
id
==
_id
)
{
LookupContext
context
=
currentContext
(
ast
);
const
QList
<
Symbol
*>
candidates
=
context
.
resolve
(
ast
->
name
);
reportResult
(
ast
->
identifier_token
,
candidates
);
}
return
false
;
}
bool
FindUsages
::
visit
(
TemplateIdAST
*
ast
)
{
if
(
_id
==
identifier
(
ast
->
identifier_token
))
{
LookupContext
context
=
currentContext
(
ast
);
const
QList
<
Symbol
*>
candidates
=
context
.
resolve
(
ast
->
name
);
reportResult
(
ast
->
identifier_token
,
candidates
);
}
for
(
TemplateArgumentListAST
*
template_arguments
=
ast
->
template_arguments
;
template_arguments
;
template_arguments
=
template_arguments
->
next
)
{
accept
(
template_arguments
->
template_argument
);
}
return
false
;
}
bool
FindUsages
::
visit
(
ParameterDeclarationAST
*
ast
)
{
for
(
SpecifierAST
*
spec
=
ast
->
type_specifier
;
spec
;
spec
=
spec
->
next
)
accept
(
spec
);
if
(
DeclaratorAST
*
declarator
=
ast
->
declarator
)
{
for
(
SpecifierAST
*
attr
=
declarator
->
attributes
;
attr
;
attr
=
attr
->
next
)
accept
(
attr
);
for
(
PtrOperatorAST
*
ptr_op
=
declarator
->
ptr_operators
;
ptr_op
;
ptr_op
=
ptr_op
->
next
)
accept
(
ptr_op
);
if
(
!
_inSimpleDeclaration
)
// visit the core declarator only if we are not in simple-declaration.
accept
(
declarator
->
core_declarator
);
for
(
PostfixDeclaratorAST
*
fx_op
=
declarator
->
postfix_declarators
;
fx_op
;
fx_op
=
fx_op
->
next
)
accept
(
fx_op
);
for
(
SpecifierAST
*
spec
=
declarator
->
post_attributes
;
spec
;
spec
=
spec
->
next
)
accept
(
spec
);
accept
(
declarator
->
initializer
);
}
accept
(
ast
->
expression
);
return
false
;
}
bool
FindUsages
::
visit
(
ExpressionOrDeclarationStatementAST
*
ast
)
{
accept
(
ast
->
declaration
);
return
false
;
}
bool
FindUsages
::
visit
(
FunctionDeclaratorAST
*
ast
)
{
accept
(
ast
->
parameters
);
for
(
SpecifierAST
*
spec
=
ast
->
cv_qualifier_seq
;
spec
;
spec
=
spec
->
next
)
accept
(
spec
);
accept
(
ast
->
exception_specification
);
return
false
;
}
bool
FindUsages
::
visit
(
SimpleDeclarationAST
*
)
{
++
_inSimpleDeclaration
;
return
true
;
}
void
FindUsages
::
endVisit
(
SimpleDeclarationAST
*
)
{
--
_inSimpleDeclaration
;
}
src/libs/cplusplus/FindUsages.h
0 → 100644
View file @
fefd72b2
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef FINDUSAGES_H
#define FINDUSAGES_H
#include "LookupContext.h"
#include "CppDocument.h"
#include "CppBindings.h"
#include "Semantic.h"
#include <ASTVisitor.h>
#include <QtCore/QFutureInterface>
namespace
CPlusPlus
{
class
CPLUSPLUS_EXPORT
Usage
{
public:
Usage
()
:
line
(
0
),
col
(
0
),
len
(
0
)
{}
Usage
(
const
QString
&
path
,
int
line
,
const
QString
&
lineText
,
int
col
,
int
len
)
:
path
(
path
),
line
(
line
),
lineText
(
lineText
),
col
(
col
),
len
(
len
)
{}
public:
QString
path
;
int
line
;
QString
lineText
;
int
col
;
int
len
;
};
class
CPLUSPLUS_EXPORT
FindUsages
:
protected
ASTVisitor
{
public:
FindUsages
(
Document
::
Ptr
doc
,
const
Snapshot
&
snapshot
,
QFutureInterface
<
Usage
>
*
future
);
void
setGlobalNamespaceBinding
(
NamespaceBindingPtr
globalNamespaceBinding
);
QList
<
int
>
operator
()(
Symbol
*
symbol
,
Identifier
*
id
,
AST
*
ast
);
protected:
using
ASTVisitor
::
visit
;
using
ASTVisitor
::
endVisit
;
QString
matchingLine
(
const
Token
&
tk
)
const
;
void
reportResult
(
unsigned
tokenIndex
,
const
QList
<
Symbol
*>
&
candidates
);
void
reportResult
(
unsigned
tokenIndex
);
bool
checkSymbol
(
Symbol
*
symbol
)
const
;
bool
checkCandidates
(
const
QList
<
Symbol
*>
&
candidates
)
const
;
bool
checkScope
(
Symbol
*
symbol
,
Symbol
*
otherSymbol
)
const
;
void
checkExpression
(
unsigned
startToken
,
unsigned
endToken
);
LookupContext
currentContext
(
AST
*
ast
);
void
ensureNameIsValid
(
NameAST
*
ast
);
virtual
bool
visit
(
MemInitializerAST
*
ast
);
virtual
bool
visit
(
PostfixExpressionAST
*
ast
);
virtual
void
endVisit
(
PostfixExpressionAST
*
);
virtual
bool
visit
(
MemberAccessAST
*
ast
);
virtual
bool
visit
(
QualifiedNameAST
*
ast
);
virtual
bool
visit
(
EnumeratorAST
*
ast
);
virtual
bool
visit
(
SimpleNameAST
*
ast
);
virtual
bool
visit
(
DestructorNameAST
*
ast
);
virtual
bool
visit
(
TemplateIdAST
*
ast
);
virtual
bool
visit
(
ParameterDeclarationAST
*
ast
);
virtual
bool
visit
(
ExpressionOrDeclarationStatementAST
*
ast
);
virtual
bool
visit
(
FunctionDeclaratorAST
*
ast
);
virtual
bool
visit
(
SimpleDeclarationAST
*
);
virtual
void
endVisit
(
SimpleDeclarationAST
*
);
private:
QFutureInterface
<
Usage
>
*
_future
;
Identifier
*
_id
;
Symbol
*
_declSymbol
;
Document
::
Ptr
_doc
;
Snapshot
_snapshot
;
QByteArray
_source
;
Document
::
Ptr
_exprDoc
;
Semantic
_sem
;
NamespaceBindingPtr
_globalNamespaceBinding
;
QList
<
PostfixExpressionAST
*>
_postfixExpressionStack
;
QList
<
QualifiedNameAST
*>
_qualifiedNameStack
;
QList
<
int
>
_references
;
LookupContext
_previousContext
;
int
_inSimpleDeclaration
;
};
}
// end of namespace CPlusPlus
#endif // FINDUSAGES_H
src/libs/cplusplus/cplusplus-lib.pri
View file @
fefd72b2
...
...
@@ -38,6 +38,7 @@ HEADERS += \
$$PWD/CppBindings.h \
$$PWD/ASTParent.h \
$$PWD/GenTemplateInstance.h \
$$PWD/FindUsages.h \
$$PWD/CheckUndefinedSymbols.h \
$$PWD/PreprocessorClient.h \
$$PWD/PreprocessorEnvironment.h \
...
...
@@ -61,6 +62,7 @@ SOURCES += \
$$PWD/CppBindings.cpp \
$$PWD/ASTParent.cpp \
$$PWD/GenTemplateInstance.cpp \
$$PWD/FindUsages.cpp \
$$PWD/CheckUndefinedSymbols.cpp \
$$PWD/PreprocessorClient.cpp \
$$PWD/PreprocessorEnvironment.cpp \
...
...
src/plugins/cpptools/cppfindreferences.cpp
View file @
fefd72b2
...
...
@@ -50,11 +50,8 @@
#include <cplusplus/CppDocument.h>
#include <cplusplus/CppBindings.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/ResolveExpression.h>
#include <cplusplus/Overview.h>
#include <cplusplus/TypeOfExpression.h>
#include <cplusplus/FastPreprocessor.h>
#include <cplusplus/FindUsages.h>
#include <QtCore/QTime>
#include <QtCore/QtConcurrentRun>
...
...
@@ -65,438 +62,6 @@
using
namespace
CppTools
::
Internal
;
using
namespace
CPlusPlus
;
namespace
{
struct
Process
:
protected
ASTVisitor
{
public:
Process
(
Document
::
Ptr
doc
,
const
Snapshot
&
snapshot
,
QFutureInterface
<
Utils
::
FileSearchResult
>
*
future
)
:
ASTVisitor
(
doc
->
control
()),
_future
(
future
),
_doc
(
doc
),
_snapshot
(
snapshot
),