/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the tools applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*
qscodemarker.cpp
*/
#include "node.h"
#include "qscodemarker.h"
QT_BEGIN_NAMESPACE
QsCodeMarker::QsCodeMarker()
{
}
QsCodeMarker::~QsCodeMarker()
{
}
bool QsCodeMarker::recognizeCode( const QString& /* code */ )
{
return true;
}
bool QsCodeMarker::recognizeExtension( const QString& ext )
{
return ext == "js" || ext == "qs";
}
bool QsCodeMarker::recognizeLanguage( const QString& lang )
{
return lang == "JavaScript" || lang == "Qt Script";
}
QString QsCodeMarker::plainName( const Node *node )
{
QString name = node->name();
if ( node->type() == Node::Function )
name += "()";
return name;
}
QString QsCodeMarker::plainFullName( const Node *node, const Node * /* relative */ )
{
QString fullName;
for ( ;; ) {
fullName.prepend( plainName(node) );
if ( node->parent()->name().isEmpty() )
break;
node = node->parent();
fullName.prepend(".");
}
return fullName;
}
QString QsCodeMarker::markedUpCode( const QString& code,
const Node * /* relative */,
const QString& /* dirPath */ )
{
return protect( code );
}
QString QsCodeMarker::markedUpSynopsis( const Node *node,
const Node * /* relative */,
SynopsisStyle style )
{
QString synopsis;
QStringList extras;
QString name;
name = taggedNode( node );
if ( style != Detailed )
name = linkTag( node, name );
name = "<@name>" + name + "</@name>";
if ( style == Detailed && !node->parent()->name().isEmpty() &&
node->type() != Node::Enum )
name.prepend( taggedNode(node->parent()) + "." );
switch ( node->type() ) {
case Node::Class:
synopsis = "class " + name;
break;
case Node::Function:
{
const FunctionNode *func = (const FunctionNode *) node;
synopsis = name;
if ( style == SeparateList ) {
synopsis += "()";
} else {
synopsis += " (";
if ( !func->parameters().isEmpty() ) {
synopsis += " ";
int numOptional = 0;
QList<Parameter>::ConstIterator p = func->parameters().begin();
while ( p != func->parameters().end() ) {
if ( !(*p).defaultValue().isEmpty() ) {
if ( p == func->parameters().begin() ) {
synopsis += "[ ";
} else {
synopsis += " [ , ";
}
numOptional++;
} else {
if ( p != func->parameters().begin() )
synopsis += ", ";
}
if ( !(*p).name().isEmpty() )
synopsis += "<@param>" + protect( (*p).name() ) +
"</@param> : ";
synopsis += protect( (*p).leftType() );
++p;
}
for ( int i = 0; i < numOptional; i++ )
synopsis += " ]";
synopsis += " ";
}
synopsis += ")";
}
if ( style != SeparateList && !func->returnType().isEmpty() )
synopsis += " : " + protect( func->returnType() );
if ( style == Detailed && func->metaness() == FunctionNode::Signal )
extras << "[signal]";
}
break;
case Node::Property:
{
const PropertyNode *property = (const PropertyNode *) node;
synopsis = name;
if ( style != SeparateList )
synopsis += " : " + property->dataType();
if ( style == Detailed && property->setters().isEmpty() )
extras << "[read only]";
}
break;
case Node::Enum:
{
/*
The letters A to F and X (upper- and lower-case) can
appear in a hexadecimal constant (e.g. 0x3F).
*/
QRegExp letterRegExp( "[G-WYZg-wyz_]" );
const EnumNode *enume = (const EnumNode *) node;
synopsis = name;
if ( style == Summary && !enume->items().isEmpty() ) {
synopsis += " : ";
QString comma;
QList<EnumItem>::ConstIterator it = enume->items().begin();
while ( it != enume->items().end() ) {
if ( enume->itemAccess((*it).name()) == Node::Public ) {
synopsis += comma;
synopsis += (*it).name();
if ( (*it).value().indexOf(letterRegExp) != -1 )
synopsis += " = " + (*it).value();
comma = ", ";
}
++it;
}
}
}
break;
case Node::Namespace:
case Node::Typedef:
default:
synopsis = name;
}
if ( style == Summary ) {
if ( node->status() == Node::Preliminary ) {
extras << "(preliminary)";
} else if ( node->status() == Node::Deprecated ) {
extras << "(deprecated)";
} else if ( node->status() == Node::Obsolete ) {
extras << "(obsolete)";
}
}
QString extra;
if ( !extras.isEmpty() )
extra = "<@extra>" + extras.join(" ") + "</@extra>";
return synopsis + extra;
}
QString QsCodeMarker::markedUpName( const Node *node )
{
QString name = linkTag( node, taggedNode(node) );
if ( node->type() == Node::Function )
name += "()";
return name;
}
QString QsCodeMarker::markedUpFullName( const Node *node,
const Node * /* relative */ )
{
QString fullName;
for ( ;; ) {
fullName.prepend( markedUpName(node) );
if ( node->parent()->name().isEmpty() )
break;
node = node->parent();
fullName.prepend( "<@op>.</@op>" );
}
return fullName;
}
QString QsCodeMarker::markedUpEnumValue(const QString & /* enumValue */,
const Node * /* relative */)
{
return QString();
}
QString QsCodeMarker::markedUpIncludes( const QStringList& /* includes */ )
{
return QString();
}
QString QsCodeMarker::functionBeginRegExp( const QString& funcName )
{
return "^function[ \t].*\\b" + QRegExp::escape( funcName );
}
QString QsCodeMarker::functionEndRegExp( const QString& /* funcName */ )
{
return "^}";
}
QList<Section> QsCodeMarker::sections( const InnerNode *inner, SynopsisStyle style, Status status )
{
QList<Section> sections;
if (inner->type() != Node::Class)
return sections;
const ClassNode *classe = static_cast<const ClassNode *>(inner);
if ( style == Summary ) {
FastSection enums(classe, "Enums", "enum", "enums");
FastSection functions(classe, "Functions", "function", "functions");
FastSection readOnlyProperties(classe, "Read-Only Properties", "property", "properties");
FastSection signalz(classe, "Signals", "signal", "signals");
FastSection writableProperties(classe, "Writable Properties", "property", "properties");
QStack<const ClassNode *> stack;
stack.push( classe );
while ( !stack.isEmpty() ) {
const ClassNode *ancestorClass = stack.pop();
NodeList::ConstIterator c = ancestorClass->childNodes().begin();
while ( c != ancestorClass->childNodes().end() ) {
if ( (*c)->access() == Node::Public ) {
if ( (*c)->type() == Node::Enum ) {
insert( enums, *c, style, status );
} else if ( (*c)->type() == Node::Function ) {
const FunctionNode *func = (const FunctionNode *) *c;
if ( func->metaness() == FunctionNode::Signal ) {
insert( signalz, *c, style, status );
} else {
insert( functions, *c, style, status );
}
} else if ( (*c)->type() == Node::Property ) {
const PropertyNode *property =
(const PropertyNode *) *c;
if ( property->setters().isEmpty() ) {
insert( readOnlyProperties, *c, style, status );
} else {
insert( writableProperties, *c, style, status );
}
}
}
++c;
}
QList<RelatedClass>::ConstIterator r = ancestorClass->baseClasses().begin();
while ( r != ancestorClass->baseClasses().end() ) {
stack.prepend( (*r).node );
++r;
}
}
append( sections, enums );
append( sections, writableProperties );
append( sections, readOnlyProperties );
append( sections, functions );
append( sections, signalz );
} else if ( style == Detailed ) {
FastSection enums( classe, "Enum Documentation" );
FastSection functionsAndSignals( classe, "Function and Signal Documentation" );
FastSection properties( classe, "Property Documentation" );
NodeList::ConstIterator c = classe->childNodes().begin();
while ( c != classe->childNodes().end() ) {
if ( (*c)->access() == Node::Public ) {
if ( (*c)->type() == Node::Enum ) {
insert( enums, *c, style, status );
} else if ( (*c)->type() == Node::Function ) {
insert( functionsAndSignals, *c, style, status );
} else if ( (*c)->type() == Node::Property ) {
insert( properties, *c, style, status );
}
}
++c;
}
append( sections, enums );
append( sections, properties );
append( sections, functionsAndSignals );
} else { // ( style == SeparateList )
FastSection all( classe );
QStack<const ClassNode *> stack;
stack.push( classe );
while ( !stack.isEmpty() ) {
const ClassNode *ancestorClass = stack.pop();
NodeList::ConstIterator c = ancestorClass->childNodes().begin();
while ( c != ancestorClass->childNodes().end() ) {
if ( (*c)->access() == Node::Public )
insert( all, *c, style, status );
++c;
}
QList<RelatedClass>::ConstIterator r = ancestorClass->baseClasses().begin();
while ( r != ancestorClass->baseClasses().end() ) {
stack.prepend( (*r).node );
++r;
}
}
append( sections, all );
}
return sections;
}
const Node *QsCodeMarker::resolveTarget( const QString& /* target */,
const Tree * /* tree */,
const Node * /* relative */ )
{
return 0;
}
QT_END_NAMESPACE