1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
33 #include "qmljsstaticanalysismessage.h"
35 #include <utils/qtcassert.h>
37 #include <QtCore/QCoreApplication>
39 using namespace QmlJS;
40 using namespace QmlJS::StaticAnalysis;
44 class StaticAnalysisMessages
46 Q_DECLARE_TR_FUNCTIONS(StaticAnalysisMessages)
49 class PrototypeMessageData {
57 void newMsg(Type type, Severity severity, const QString &message, int placeholders = 0)
59 PrototypeMessageData prototype;
60 prototype.type = type;
61 prototype.severity = severity;
62 prototype.message = message;
63 prototype.placeholders = placeholders;
64 QTC_CHECK(placeholders <= 2);
65 QTC_ASSERT(!messages.contains(type), return);
66 messages[type] = prototype;
69 StaticAnalysisMessages();
70 QHash<Type, PrototypeMessageData> messages;
73 StaticAnalysisMessages::StaticAnalysisMessages()
75 newMsg(ErrInvalidEnumValue, Error,
76 tr("invalid value for enum"));
77 newMsg(ErrEnumValueMustBeStringOrNumber, Error,
78 tr("enum value must be a string or a number"));
79 newMsg(ErrNumberValueExpected, Error,
80 tr("number value expected"));
81 newMsg(ErrBooleanValueExpected, Error,
82 tr("boolean value expected"));
83 newMsg(ErrStringValueExpected, Error,
84 tr("string value expected"));
85 newMsg(ErrInvalidUrl, Error,
87 newMsg(WarnFileOrDirectoryDoesNotExist, Warning,
88 tr("file or directory does not exist"));
89 newMsg(ErrInvalidColor, Error,
91 newMsg(ErrAnchorLineExpected, Error,
92 tr("anchor line expected"));
93 newMsg(ErrPropertiesCanOnlyHaveOneBinding, Error,
94 tr("duplicate property binding"));
95 newMsg(ErrIdExpected, Error,
97 newMsg(ErrInvalidId, Error,
99 newMsg(ErrDuplicateId, Error,
101 newMsg(ErrInvalidPropertyName, Error,
102 tr("invalid property name '%1'"), 1);
103 newMsg(ErrDoesNotHaveMembers, Error,
104 tr("'%1' does not have members"), 1);
105 newMsg(ErrInvalidMember, Error,
106 tr("'%1' is not a member of '%2'"), 2);
107 newMsg(WarnAssignmentInCondition, Warning,
108 tr("assignment in condition"));
109 newMsg(WarnCaseWithoutFlowControl, Warning,
110 tr("unterminated non-empty case block"));
111 newMsg(WarnEval, Warning,
112 tr("do not use 'eval'"));
113 newMsg(WarnUnreachable, Warning,
115 newMsg(WarnWith, Warning,
116 tr("do not use 'with'"));
117 newMsg(WarnComma, Warning,
118 tr("do not use comma expressions"));
119 newMsg(WarnAlreadyFormalParameter, Warning,
120 tr("'%1' is already a formal parameter"), 1);
121 newMsg(WarnAlreadyFunction, Warning,
122 tr("'%1' is already a function"), 1);
123 newMsg(WarnVarUsedBeforeDeclaration, Warning,
124 tr("var '%1' is used before its declaration"), 1);
125 newMsg(WarnAlreadyVar, Warning,
126 tr("'%1' is already a var"), 1);
127 newMsg(WarnDuplicateDeclaration, Warning,
128 tr("'%1' is declared more than once"), 1);
129 newMsg(WarnFunctionUsedBeforeDeclaration, Warning,
130 tr("function '%1' is used before its declaration"), 1);
131 newMsg(WarnBooleanConstructor, Warning,
132 tr("do not use 'Boolean' as a constructor"));
133 newMsg(WarnStringConstructor, Warning,
134 tr("do not use 'String' as a constructor"));
135 newMsg(WarnObjectConstructor, Warning,
136 tr("do not use 'Object' as a constructor"));
137 newMsg(WarnArrayConstructor, Warning,
138 tr("do not use 'Array' as a constructor"));
139 newMsg(WarnFunctionConstructor, Warning,
140 tr("do not use 'Function' as a constructor"));
141 newMsg(HintAnonymousFunctionSpacing, Hint,
142 tr("the 'function' keyword and the opening parenthesis should be separated by a single space"));
143 newMsg(WarnBlock, Warning,
144 tr("do not use stand-alone blocks"));
145 newMsg(WarnVoid, Warning,
146 tr("do not use void expressions"));
147 newMsg(WarnConfusingPluses, Warning,
148 tr("confusing pluses"));
149 newMsg(WarnConfusingPreincrement, Warning,
150 tr("confusing preincrement"));
151 newMsg(WarnConfusingMinuses, Warning,
152 tr("confusing minuses"));
153 newMsg(WarnConfusingPredecrement, Warning,
154 tr("confusing predecrement"));
155 newMsg(HintDeclareVarsInOneLine, Hint,
156 tr("declare all function vars on a single line"));
158 // newMsg(HintExtraParentheses, Hint,
160 newMsg(MaybeWarnEqualityTypeCoercion, MaybeWarning,
161 tr("== and != may perform type coercion, use === or !== to avoid"));
162 newMsg(WarnConfusingExpressionStatement, Warning,
163 tr("expression statements should be assignments, calls or delete expressions only"));
164 newMsg(HintDeclarationsShouldBeAtStartOfFunction, Error,
165 tr("var declarations should be at the start of a function"));
166 newMsg(HintOneStatementPerLine, Error,
167 tr("only use one statement per line"));
168 newMsg(ErrUnknownComponent, Error,
169 tr("unknown component"));
170 newMsg(ErrCouldNotResolvePrototypeOf, Error,
171 tr("could not resolve the prototype '%1'' of '%2'"), 2);
172 newMsg(ErrCouldNotResolvePrototype, Error,
173 tr("could not resolve the prototype '%1'"), 1);
174 newMsg(ErrPrototypeCycle, Error,
175 tr("prototype cycle, the last non-repeated component is '%1'"), 1);
176 newMsg(ErrInvalidPropertyType, Error,
177 tr("invalid property type '%1'"), 1);
178 newMsg(WarnEqualityTypeCoercion, Warning,
179 tr("== and != perform type coercion, use === or !== to avoid"));
180 newMsg(WarnExpectedNewWithUppercaseFunction, Warning,
181 tr("calls of functions that start with an uppercase letter should use 'new'"));
182 newMsg(WarnNewWithLowercaseFunction, Warning,
183 tr("'new' should only be used with functions that start with an uppercase letter"));
184 newMsg(WarnNumberConstructor, Warning,
185 tr("do not use 'Number' as a constructor"));
186 newMsg(HintBinaryOperatorSpacing, Hint,
187 tr("use spaces around binary operators"));
188 newMsg(WarnUnintentinalEmptyBlock, Warning,
189 tr("unintentional empty block, use ({}) for empty object literal"));
192 } // anonymous namespace
194 Q_GLOBAL_STATIC(StaticAnalysisMessages, messages)
196 QList<Type> Message::allMessageTypes()
198 return messages()->messages.keys();
202 : type(UnknownType), severity(Hint)
205 Message::Message(Type type, AST::SourceLocation location, const QString &arg1, const QString &arg2)
206 : location(location), type(type)
208 QTC_ASSERT(messages()->messages.contains(type), return);
209 const StaticAnalysisMessages::PrototypeMessageData &prototype = messages()->messages.value(type);
210 severity = prototype.severity;
211 message = prototype.message;
212 if (prototype.placeholders == 0) {
213 if (!arg1.isEmpty() || !arg2.isEmpty())
214 qWarning() << "StaticAnalysis message" << type << "expects no arguments";
215 } else if (prototype.placeholders == 1) {
216 if (arg1.isEmpty() || !arg2.isEmpty())
217 qWarning() << "StaticAnalysis message" << type << "expects exactly one argument";
218 message = message.arg(arg1);
219 } else if (prototype.placeholders == 2) {
220 if (arg1.isEmpty() || arg2.isEmpty())
221 qWarning() << "StaticAnalysis message" << type << "expects exactly two arguments";
222 message = message.arg(arg1, arg2);
226 bool Message::isValid() const
228 return type != UnknownType && location.isValid() && !message.isEmpty();
231 DiagnosticMessage Message::toDiagnosticMessage() const
233 DiagnosticMessage diagnostic;
238 diagnostic.kind = DiagnosticMessage::Warning;
241 diagnostic.kind = DiagnosticMessage::Error;
244 diagnostic.loc = location;
245 diagnostic.message = message;