OSDN Git Service

QmlJS checks: Add severity and unique id to messages.
[qt-creator-jp/qt-creator-jp.git] / src / libs / qmljs / qmljsstaticanalysismessage.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
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.
18 **
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.
22 **
23 ** Other Usage
24 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
30 **
31 **************************************************************************/
32
33 #include "qmljsstaticanalysismessage.h"
34
35 #include <utils/qtcassert.h>
36
37 #include <QtCore/QCoreApplication>
38
39 using namespace QmlJS;
40 using namespace QmlJS::StaticAnalysis;
41
42 namespace {
43
44 class StaticAnalysisMessages
45 {
46     Q_DECLARE_TR_FUNCTIONS(StaticAnalysisMessages)
47
48 public:
49     class PrototypeMessageData {
50     public:
51         Type type;
52         Severity severity;
53         QString message;
54         int placeholders;
55     };
56
57     void newMsg(Type type, Severity severity, const QString &message, int placeholders = 0)
58     {
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;
67     }
68
69     StaticAnalysisMessages();
70     QHash<Type, PrototypeMessageData> messages;
71 };
72
73 StaticAnalysisMessages::StaticAnalysisMessages()
74 {
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,
86            tr("invalid URL"));
87     newMsg(WarnFileOrDirectoryDoesNotExist, Warning,
88            tr("file or directory does not exist"));
89     newMsg(ErrInvalidColor, Error,
90            tr("invalid color"));
91     newMsg(ErrAnchorLineExpected, Error,
92            tr("anchor line expected"));
93     newMsg(ErrPropertiesCanOnlyHaveOneBinding, Error,
94            tr("duplicate property binding"));
95     newMsg(ErrIdExpected, Error,
96            tr("id expected"));
97     newMsg(ErrInvalidId, Error,
98            tr("invalid id"));
99     newMsg(ErrDuplicateId, Error,
100            tr("duplicate id"));
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,
114            tr("unreachable"));
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"));
157     // unused
158 //    newMsg(HintExtraParentheses, Hint,
159 //           tr(""));
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"));
190 }
191
192 } // anonymous namespace
193
194 Q_GLOBAL_STATIC(StaticAnalysisMessages, messages)
195
196 QList<Type> Message::allMessageTypes()
197 {
198     return messages()->messages.keys();
199 }
200
201 Message::Message()
202     : type(UnknownType), severity(Hint)
203 {}
204
205 Message::Message(Type type, AST::SourceLocation location, const QString &arg1, const QString &arg2)
206     : location(location), type(type)
207 {
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);
223     }
224 }
225
226 bool Message::isValid() const
227 {
228     return type != UnknownType && location.isValid() && !message.isEmpty();
229 }
230
231 DiagnosticMessage Message::toDiagnosticMessage() const
232 {
233     DiagnosticMessage diagnostic;
234     switch (severity) {
235     case Hint:
236     case MaybeWarning:
237     case Warning:
238         diagnostic.kind = DiagnosticMessage::Warning;
239         break;
240     default:
241         diagnostic.kind = DiagnosticMessage::Error;
242         break;
243     }
244     diagnostic.loc = location;
245     diagnostic.message = message;
246     return diagnostic;
247 }