OSDN Git Service

QmlJS checks: Hint about extra parentheses.
[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(WarnConfusingMinuses, Warning,
150            tr("confusing minuses"));
151     newMsg(HintDeclareVarsInOneLine, Hint,
152            tr("declare all function vars on a single line"));
153     newMsg(HintExtraParentheses, Hint,
154            tr("unnecessary parentheses"));
155     newMsg(MaybeWarnEqualityTypeCoercion, MaybeWarning,
156            tr("== and != may perform type coercion, use === or !== to avoid"));
157     newMsg(WarnConfusingExpressionStatement, Warning,
158            tr("expression statements should be assignments, calls or delete expressions only"));
159     newMsg(HintDeclarationsShouldBeAtStartOfFunction, Error,
160            tr("var declarations should be at the start of a function"));
161     newMsg(HintOneStatementPerLine, Error,
162            tr("only use one statement per line"));
163     newMsg(ErrUnknownComponent, Error,
164            tr("unknown component"));
165     newMsg(ErrCouldNotResolvePrototypeOf, Error,
166            tr("could not resolve the prototype '%1'' of '%2'"), 2);
167     newMsg(ErrCouldNotResolvePrototype, Error,
168            tr("could not resolve the prototype '%1'"), 1);
169     newMsg(ErrPrototypeCycle, Error,
170            tr("prototype cycle, the last non-repeated component is '%1'"), 1);
171     newMsg(ErrInvalidPropertyType, Error,
172            tr("invalid property type '%1'"), 1);
173     newMsg(WarnEqualityTypeCoercion, Warning,
174            tr("== and != perform type coercion, use === or !== to avoid"));
175     newMsg(WarnExpectedNewWithUppercaseFunction, Warning,
176            tr("calls of functions that start with an uppercase letter should use 'new'"));
177     newMsg(WarnNewWithLowercaseFunction, Warning,
178            tr("'new' should only be used with functions that start with an uppercase letter"));
179     newMsg(WarnNumberConstructor, Warning,
180            tr("do not use 'Number' as a constructor"));
181     newMsg(HintBinaryOperatorSpacing, Hint,
182            tr("use spaces around binary operators"));
183     newMsg(WarnUnintentinalEmptyBlock, Warning,
184            tr("unintentional empty block, use ({}) for empty object literal"));
185 }
186
187 } // anonymous namespace
188
189 Q_GLOBAL_STATIC(StaticAnalysisMessages, messages)
190
191 QList<Type> Message::allMessageTypes()
192 {
193     return messages()->messages.keys();
194 }
195
196 Message::Message()
197     : type(UnknownType), severity(Hint)
198 {}
199
200 Message::Message(Type type, AST::SourceLocation location, const QString &arg1, const QString &arg2)
201     : location(location), type(type)
202 {
203     QTC_ASSERT(messages()->messages.contains(type), return);
204     const StaticAnalysisMessages::PrototypeMessageData &prototype = messages()->messages.value(type);
205     severity = prototype.severity;
206     message = prototype.message;
207     if (prototype.placeholders == 0) {
208         if (!arg1.isEmpty() || !arg2.isEmpty())
209             qWarning() << "StaticAnalysis message" << type << "expects no arguments";
210     } else if (prototype.placeholders == 1) {
211         if (arg1.isEmpty() || !arg2.isEmpty())
212             qWarning() << "StaticAnalysis message" << type << "expects exactly one argument";
213         message = message.arg(arg1);
214     } else if (prototype.placeholders == 2) {
215         if (arg1.isEmpty() || arg2.isEmpty())
216             qWarning() << "StaticAnalysis message" << type << "expects exactly two arguments";
217         message = message.arg(arg1, arg2);
218     }
219 }
220
221 bool Message::isValid() const
222 {
223     return type != UnknownType && location.isValid() && !message.isEmpty();
224 }
225
226 DiagnosticMessage Message::toDiagnosticMessage() const
227 {
228     DiagnosticMessage diagnostic;
229     switch (severity) {
230     case Hint:
231     case MaybeWarning:
232     case Warning:
233         diagnostic.kind = DiagnosticMessage::Warning;
234         break;
235     default:
236         diagnostic.kind = DiagnosticMessage::Error;
237         break;
238     }
239     diagnostic.loc = location;
240     diagnostic.message = message;
241     return diagnostic;
242 }