summaryrefslogtreecommitdiff
path: root/src/libs/qmljs/qmljsstaticanalysismessage.cpp
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-09-28 15:16:00 +0200
committerChristian Kamm <christian.d.kamm@nokia.com>2011-10-10 14:39:20 +0200
commit55713a1514adab455ba99d27bd0d2656d221947a (patch)
treeecbd86251d571f4fbd83c49de0aa3a06f7b12207 /src/libs/qmljs/qmljsstaticanalysismessage.cpp
parentf25f1858f090062adab50ed92f15ba90cae4c0d2 (diff)
downloadqt-creator-55713a1514adab455ba99d27bd0d2656d221947a.tar.gz
QmlJS checks: Add severity and unique id to messages.
Change-Id: I2cded26524c3f64152107e65d740658e3003ffac Reviewed-on: http://codereview.qt-project.org/5790 Sanity-Review: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
Diffstat (limited to 'src/libs/qmljs/qmljsstaticanalysismessage.cpp')
-rw-r--r--src/libs/qmljs/qmljsstaticanalysismessage.cpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/libs/qmljs/qmljsstaticanalysismessage.cpp b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
new file mode 100644
index 0000000000..7b27c235a9
--- /dev/null
+++ b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
@@ -0,0 +1,247 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#include "qmljsstaticanalysismessage.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QCoreApplication>
+
+using namespace QmlJS;
+using namespace QmlJS::StaticAnalysis;
+
+namespace {
+
+class StaticAnalysisMessages
+{
+ Q_DECLARE_TR_FUNCTIONS(StaticAnalysisMessages)
+
+public:
+ class PrototypeMessageData {
+ public:
+ Type type;
+ Severity severity;
+ QString message;
+ int placeholders;
+ };
+
+ void newMsg(Type type, Severity severity, const QString &message, int placeholders = 0)
+ {
+ PrototypeMessageData prototype;
+ prototype.type = type;
+ prototype.severity = severity;
+ prototype.message = message;
+ prototype.placeholders = placeholders;
+ QTC_CHECK(placeholders <= 2);
+ QTC_ASSERT(!messages.contains(type), return);
+ messages[type] = prototype;
+ }
+
+ StaticAnalysisMessages();
+ QHash<Type, PrototypeMessageData> messages;
+};
+
+StaticAnalysisMessages::StaticAnalysisMessages()
+{
+ newMsg(ErrInvalidEnumValue, Error,
+ tr("invalid value for enum"));
+ newMsg(ErrEnumValueMustBeStringOrNumber, Error,
+ tr("enum value must be a string or a number"));
+ newMsg(ErrNumberValueExpected, Error,
+ tr("number value expected"));
+ newMsg(ErrBooleanValueExpected, Error,
+ tr("boolean value expected"));
+ newMsg(ErrStringValueExpected, Error,
+ tr("string value expected"));
+ newMsg(ErrInvalidUrl, Error,
+ tr("invalid URL"));
+ newMsg(WarnFileOrDirectoryDoesNotExist, Warning,
+ tr("file or directory does not exist"));
+ newMsg(ErrInvalidColor, Error,
+ tr("invalid color"));
+ newMsg(ErrAnchorLineExpected, Error,
+ tr("anchor line expected"));
+ newMsg(ErrPropertiesCanOnlyHaveOneBinding, Error,
+ tr("duplicate property binding"));
+ newMsg(ErrIdExpected, Error,
+ tr("id expected"));
+ newMsg(ErrInvalidId, Error,
+ tr("invalid id"));
+ newMsg(ErrDuplicateId, Error,
+ tr("duplicate id"));
+ newMsg(ErrInvalidPropertyName, Error,
+ tr("invalid property name '%1'"), 1);
+ newMsg(ErrDoesNotHaveMembers, Error,
+ tr("'%1' does not have members"), 1);
+ newMsg(ErrInvalidMember, Error,
+ tr("'%1' is not a member of '%2'"), 2);
+ newMsg(WarnAssignmentInCondition, Warning,
+ tr("assignment in condition"));
+ newMsg(WarnCaseWithoutFlowControl, Warning,
+ tr("unterminated non-empty case block"));
+ newMsg(WarnEval, Warning,
+ tr("do not use 'eval'"));
+ newMsg(WarnUnreachable, Warning,
+ tr("unreachable"));
+ newMsg(WarnWith, Warning,
+ tr("do not use 'with'"));
+ newMsg(WarnComma, Warning,
+ tr("do not use comma expressions"));
+ newMsg(WarnAlreadyFormalParameter, Warning,
+ tr("'%1' is already a formal parameter"), 1);
+ newMsg(WarnAlreadyFunction, Warning,
+ tr("'%1' is already a function"), 1);
+ newMsg(WarnVarUsedBeforeDeclaration, Warning,
+ tr("var '%1' is used before its declaration"), 1);
+ newMsg(WarnAlreadyVar, Warning,
+ tr("'%1' is already a var"), 1);
+ newMsg(WarnDuplicateDeclaration, Warning,
+ tr("'%1' is declared more than once"), 1);
+ newMsg(WarnFunctionUsedBeforeDeclaration, Warning,
+ tr("function '%1' is used before its declaration"), 1);
+ newMsg(WarnBooleanConstructor, Warning,
+ tr("do not use 'Boolean' as a constructor"));
+ newMsg(WarnStringConstructor, Warning,
+ tr("do not use 'String' as a constructor"));
+ newMsg(WarnObjectConstructor, Warning,
+ tr("do not use 'Object' as a constructor"));
+ newMsg(WarnArrayConstructor, Warning,
+ tr("do not use 'Array' as a constructor"));
+ newMsg(WarnFunctionConstructor, Warning,
+ tr("do not use 'Function' as a constructor"));
+ newMsg(HintAnonymousFunctionSpacing, Hint,
+ tr("the 'function' keyword and the opening parenthesis should be separated by a single space"));
+ newMsg(WarnBlock, Warning,
+ tr("do not use stand-alone blocks"));
+ newMsg(WarnVoid, Warning,
+ tr("do not use void expressions"));
+ newMsg(WarnConfusingPluses, Warning,
+ tr("confusing pluses"));
+ newMsg(WarnConfusingPreincrement, Warning,
+ tr("confusing preincrement"));
+ newMsg(WarnConfusingMinuses, Warning,
+ tr("confusing minuses"));
+ newMsg(WarnConfusingPredecrement, Warning,
+ tr("confusing predecrement"));
+ newMsg(HintDeclareVarsInOneLine, Hint,
+ tr("declare all function vars on a single line"));
+ // unused
+// newMsg(HintExtraParentheses, Hint,
+// tr(""));
+ newMsg(MaybeWarnEqualityTypeCoercion, MaybeWarning,
+ tr("== and != may perform type coercion, use === or !== to avoid"));
+ newMsg(WarnConfusingExpressionStatement, Warning,
+ tr("expression statements should be assignments, calls or delete expressions only"));
+ newMsg(HintDeclarationsShouldBeAtStartOfFunction, Error,
+ tr("var declarations should be at the start of a function"));
+ newMsg(HintOneStatementPerLine, Error,
+ tr("only use one statement per line"));
+ newMsg(ErrUnknownComponent, Error,
+ tr("unknown component"));
+ newMsg(ErrCouldNotResolvePrototypeOf, Error,
+ tr("could not resolve the prototype '%1'' of '%2'"), 2);
+ newMsg(ErrCouldNotResolvePrototype, Error,
+ tr("could not resolve the prototype '%1'"), 1);
+ newMsg(ErrPrototypeCycle, Error,
+ tr("prototype cycle, the last non-repeated component is '%1'"), 1);
+ newMsg(ErrInvalidPropertyType, Error,
+ tr("invalid property type '%1'"), 1);
+ newMsg(WarnEqualityTypeCoercion, Warning,
+ tr("== and != perform type coercion, use === or !== to avoid"));
+ newMsg(WarnExpectedNewWithUppercaseFunction, Warning,
+ tr("calls of functions that start with an uppercase letter should use 'new'"));
+ newMsg(WarnNewWithLowercaseFunction, Warning,
+ tr("'new' should only be used with functions that start with an uppercase letter"));
+ newMsg(WarnNumberConstructor, Warning,
+ tr("do not use 'Number' as a constructor"));
+ newMsg(HintBinaryOperatorSpacing, Hint,
+ tr("use spaces around binary operators"));
+ newMsg(WarnUnintentinalEmptyBlock, Warning,
+ tr("unintentional empty block, use ({}) for empty object literal"));
+}
+
+} // anonymous namespace
+
+Q_GLOBAL_STATIC(StaticAnalysisMessages, messages)
+
+QList<Type> Message::allMessageTypes()
+{
+ return messages()->messages.keys();
+}
+
+Message::Message()
+ : type(UnknownType), severity(Hint)
+{}
+
+Message::Message(Type type, AST::SourceLocation location, const QString &arg1, const QString &arg2)
+ : location(location), type(type)
+{
+ QTC_ASSERT(messages()->messages.contains(type), return);
+ const StaticAnalysisMessages::PrototypeMessageData &prototype = messages()->messages.value(type);
+ severity = prototype.severity;
+ message = prototype.message;
+ if (prototype.placeholders == 0) {
+ if (!arg1.isEmpty() || !arg2.isEmpty())
+ qWarning() << "StaticAnalysis message" << type << "expects no arguments";
+ } else if (prototype.placeholders == 1) {
+ if (arg1.isEmpty() || !arg2.isEmpty())
+ qWarning() << "StaticAnalysis message" << type << "expects exactly one argument";
+ message = message.arg(arg1);
+ } else if (prototype.placeholders == 2) {
+ if (arg1.isEmpty() || arg2.isEmpty())
+ qWarning() << "StaticAnalysis message" << type << "expects exactly two arguments";
+ message = message.arg(arg1, arg2);
+ }
+}
+
+bool Message::isValid() const
+{
+ return type != UnknownType && location.isValid() && !message.isEmpty();
+}
+
+DiagnosticMessage Message::toDiagnosticMessage() const
+{
+ DiagnosticMessage diagnostic;
+ switch (severity) {
+ case Hint:
+ case MaybeWarning:
+ case Warning:
+ diagnostic.kind = DiagnosticMessage::Warning;
+ break;
+ default:
+ diagnostic.kind = DiagnosticMessage::Error;
+ break;
+ }
+ diagnostic.loc = location;
+ diagnostic.message = message;
+ return diagnostic;
+}