Index: clang-tools-extra/clang-tidy/objc/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/objc/CMakeLists.txt +++ clang-tools-extra/clang-tidy/objc/CMakeLists.txt @@ -10,6 +10,7 @@ ForbiddenSubclassingCheck.cpp MissingHashCheck.cpp NSInvocationArgumentLifetimeCheck.cpp + NsdateformatterCheck.cpp ObjCTidyModule.cpp PropertyDeclarationCheck.cpp SuperSelfCheck.cpp Index: clang-tools-extra/clang-tidy/objc/NsdateformatterCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/objc/NsdateformatterCheck.h @@ -0,0 +1,35 @@ +//===--- NsdateformatterCheck.h - clang-tidy --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_NSDATEFORMATTERCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_NSDATEFORMATTERCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace objc { + +/// Checks the string pattern used as a date format specifier and reports warnings if +/// it contains any incorrect sub-pattern. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/objc-NSDateFormatter.html +class NsdateformatterCheck : public ClangTidyCheck { +public: + NsdateformatterCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace objc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_NSDATEFORMATTERCHECK_H Index: clang-tools-extra/clang-tidy/objc/NsdateformatterCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/objc/NsdateformatterCheck.cpp @@ -0,0 +1,96 @@ +//===--- NsdateformatterCheck.cpp - clang-tidy ----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NsdateformatterCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +# include + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace objc { + +void NsdateformatterCheck::registerMatchers(MatchFinder *Finder) { + // Adding matchers. + Finder->addMatcher(objcMessageExpr(hasSelector("setDateFormat:"), hasArgument(0, hasDescendant( stringLiteral().bind("str_lit")))), this); +} + +// Checks if the string pattern used as a date format specifier is valid. +// A string pattern is valid if all the letters(a-z, A-Z) in it belong to the set of reserved characters. +// See: https://www.unicode.org/reports/tr35/tr35.html#Invalid_Patterns +bool isValidDatePattern(StringRef Pattern) { + char ValidDatePatternChars[] = {'G', 'y', 'Y', 'u', 'U', 'r', 'Q', 'q', 'M', 'L', 'I', 'w', 'W', 'd', 'D', 'F', 'g', 'E', 'e', 'c', 'a', 'b', 'B', 'h', 'H', 'K', 'k', 'j', 'J', 'C', 'm', 's', 'S', 'A', 'z', 'Z', 'O', 'v', 'V', 'X', 'x'}; + for (auto it = Pattern.begin(); it != Pattern.end(); it++) { + char PatternChar = *it; + if (isalpha(PatternChar)) { + if (std::find(std::begin(ValidDatePatternChars), std::end(ValidDatePatternChars), PatternChar) == std::end(ValidDatePatternChars)) + { + return false; + } + } + } + return true; +} + +// Checks if the string pattern used as a date format specifier contains +// any incorrect pattern and reports it as a warning. +// See: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns +void NsdateformatterCheck::check(const MatchFinder::MatchResult &Result) { + // Callback implementation. + const auto *StrExpr = Result.Nodes.getNodeAs("str_lit"); + StringRef SR = cast(StrExpr)->getString(); + + if (!isValidDatePattern(SR)) { + diag(StrExpr->getExprLoc(), "invalid date format specifier"); + } + + if (SR.contains('y') && SR.contains('w') && !SR.contains('Y')) { + diag(StrExpr->getExprLoc(), "use of calendar year(y) with week of the year(w); " + "did you mean to use week-year(Y) instead?"); + } + if (SR.contains('F')) { + if (!(SR.contains('e') || SR.contains('E'))) { + diag(StrExpr->getExprLoc(), "day of week in month(F) used without day of the week(e or E); " + "did you forget e (or E) in the format string?"); + } + if (!SR.contains('M')) { + diag(StrExpr->getExprLoc(), "day of week in month(F) used without the month(M); " + "did you forget M in the format string?"); + } + } + if (SR.contains('W') && !SR.contains('M')) { + diag(StrExpr->getExprLoc(), "Week of Month(W) used without the month(M); " + "did you forget M in the format string?"); + } + if (SR.contains('Y') && SR.contains('Q') && !SR.contains('y')) { + diag(StrExpr->getExprLoc(), "use of week year(Y) with quarter number(Q); " + "did you mean to use calendar year(y) instead?"); + } + if (SR.contains('Y') && SR.contains('M') && !SR.contains('y')) { + diag(StrExpr->getExprLoc(), "use of week year(Y) with month(M); " + "did you mean to use calendar year(y) instead?"); + } + if (SR.contains('Y') && SR.contains('D') && !SR.contains('y')) { + diag(StrExpr->getExprLoc(), "use of week year(Y) with day of the year(D); " + "did you mean to use calendar year(y) instead?"); + } + if (SR.contains('Y') && SR.contains('W') && !SR.contains('y')) { + diag(StrExpr->getExprLoc(), "use of week year(Y) with week of the month(W); " + "did you mean to use calendar year(y) instead?"); + } + if (SR.contains('Y') && SR.contains('F') && !SR.contains('y')) { + diag(StrExpr->getExprLoc(), "use of week year(Y) with day of the week in month(F); " + "did you mean to use calendar year(y) instead?"); + } +} + +} // namespace objc +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp +++ clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp @@ -15,6 +15,7 @@ #include "ForbiddenSubclassingCheck.h" #include "MissingHashCheck.h" #include "NSInvocationArgumentLifetimeCheck.h" +#include "NsdateformatterCheck.h" #include "PropertyDeclarationCheck.h" #include "SuperSelfCheck.h" @@ -27,6 +28,8 @@ class ObjCModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "objc-NSDateFormatter"); CheckFactories.registerCheck( "objc-avoid-nserror-init"); CheckFactories.registerCheck("objc-assert-equals"); Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -124,6 +124,11 @@ Replaces groups of adjacent macros with an unscoped anonymous enum. +- New :doc:`objc-NSDateFormatter + ` check. + + Report incorrect string patterns in the date format specifier. + - New :doc:`portability-std-allocator-const ` check. Report use of ``std::vector`` (and similar containers of const Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -84,7 +84,7 @@ `bugprone-posix-return `_, "Yes" `bugprone-redundant-branch-condition `_, "Yes" `bugprone-reserved-identifier `_, "Yes" - `bugprone-shared-ptr-array-mismatch `_, "Yes" + `bugprone-shared-ptr-array-mismatch `_, `bugprone-signal-handler `_, `bugprone-signed-char-misuse `_, `bugprone-sizeof-container `_, @@ -105,7 +105,7 @@ `bugprone-terminating-continue `_, "Yes" `bugprone-throw-keyword-missing `_, `bugprone-too-small-loop-variable `_, - `bugprone-unchecked-optional-access `_, "Yes" + `bugprone-unchecked-optional-access `_, `bugprone-undefined-memory-manipulation `_, `bugprone-undelegated-constructor `_, `bugprone-unhandled-exception-at-new `_, @@ -114,7 +114,7 @@ `bugprone-unused-return-value `_, `bugprone-use-after-move `_, `bugprone-virtual-near-miss `_, "Yes" - `cert-dcl21-cpp `_, "Yes" + `cert-dcl21-cpp `_, `cert-dcl50-cpp `_, `cert-dcl58-cpp `_, `cert-env33-c `_, @@ -263,6 +263,7 @@ `modernize-use-using `_, "Yes" `mpi-buffer-deref `_, "Yes" `mpi-type-mismatch `_, "Yes" + `objc-NSDateFormatter `_, "Yes" `objc-assert-equals `_, "Yes" `objc-avoid-nserror-init `_, `objc-dealloc-in-category `_, Index: clang-tools-extra/docs/clang-tidy/checks/objc-NSDateFormatter.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/objc-NSDateFormatter.rst @@ -0,0 +1,78 @@ +.. title:: clang-tidy - objc-NSDateFormatter + +objc-NSDateFormatter +==================== +When ``NSDateFormatter`` is used to convert an ``NSDate`` type to a ``String`` type, the user +can specify a custom format string. Certain format specifiers are undesirable +despite being legal. See http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns for all legal date patterns. + +This checker reports as warnings the following string patterns in a date format specifier: +1. yyyy + ww : Calendar year specified with week of a week year (unless YYYY is also specified). + Example 1: + Input Date: 29 December 2014 ; Format String: “yyyy-ww” + Output string: 2014-01 (Wrong because it’s not the first week of 2014) + + Example 2: + Input Date: 29 December 2014 ; Format String: “dd-MM-yyyy (ww-YYYY)” + Output string: 29-12-2014 (01-2015) (This is correct) + +2. F without ee/EE : Numeric day of week in a month without actual day. + Example: + Input Date: 29 December 2014 ; Format String: “F-MM” + Output string: 5-12 (Wrong because it reads as *5th ___ of Dec* in English) + +3. F without MM : Numeric day of week in a month without month. + Example: + Input Date: 29 December 2014 ; Format String: “F-EE” + Output string: 5-Mon (Wrong because it reads as *5th Mon of ___* in English) + +4. WW without MM : Week of the month without the month. + Example: + Input Date: 29 December 2014 ; Format String: “WW-yyyy” + Output string: 05-2014 (Wrong because it reads as *5th Week of ___* in English) + +5. YYYY + QQ : Week year specified with quarter of normal year (unless yyyy is also specified). + Example 1: + Input Date: 29 December 2014 ; Format String: “YYYY-QQ” + Output string: 2015-04 (Wrong because it’s not the 4th quarter of 2015) + + Example 2: + Input Date: 29 December 2014 ; Format String: “ww-YYYY (QQ-yyyy)” + Output string: 01-2015 (04-2014) (This is correct) + +6. YYYY + MM : Week year specified with Month of a calendar year (unless yyyy is also specified). + Example 1: + Input Date: 29 December 2014 ; Format String: “YYYY-MM” + Output string: 2015-12 (Wrong because it’s not the 12th month of 2015) + + Example 2: + Input Date: 29 December 2014 ; Format String: “ww-YYYY (MM-yyyy)” + Output string: 01-2015 (12-2014) (This is correct) + +7. YYYY + DD : Week year with day of a calendar year (unless yyyy is also specified). + Example 1: + Input Date: 29 December 2014 ; Format String: “YYYY-DD” + Output string: 2015-363 (Wrong because it’s not the 363rd day of 2015) + + Example 2: + Input Date: 29 December 2014 ; Format String: “ww-YYYY (DD-yyyy)” + Output string: 01-2015 (363-2014) (This is correct) + +8. YYYY + WW : Week year with week of a calendar year (unless yyyy is also specified). + Example 1: + Input Date: 29 December 2014 ; Format String: “YYYY-WW” + Output string: 2015-05 (Wrong because it’s not the 5th week of 2015) + + Example 2: + Input Date: 29 December 2014 ; Format String: “ww-YYYY (WW-MM-yyyy)” + Output string: 01-2015 (05-12-2014) (This is correct) + +9. YYYY + F : Week year with day of week in a calendar month (unless yyyy is also specified). + Example 1: + Input Date: 29 December 2014 ; Format String: “YYYY-ww-F-EE” + Output string: 2015-01-5-Mon (Wrong because it’s not the 5th Monday of January in 2015) + + Example 2: + Input Date: 29 December 2014 ; Format String: “ww-YYYY (F-EE-MM-yyyy)” + Output string: 01-2015 (5-Mon-12-2014) (This is correct) + Index: clang-tools-extra/test/clang-tidy/checkers/objc-NSDateFormatter.m =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/objc-NSDateFormatter.m @@ -0,0 +1,280 @@ +// RUN: %check_clang_tidy %s objc-NSDateFormatter %t + +#import + +@interface TestClass : NSObject{ +} ++(void)testMethod1; ++(void)testMethod2; ++(void)testMethod3; +@end + +@implementation TestClass + ++(void)testMethod1{ + // Reproducing incorrect behavior from Radar + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"YYYY_MM_dd_HH_mm_ss_SSS_ZZZ"]; + // CHECK-MESSAGES: :[[@LINE-1]]:17:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSDateComponents *comps = [[NSDateComponents alloc] init]; + [comps setDay:29]; + [comps setMonth:12]; + [comps setYear:2014]; + NSDate *date_radar = [[NSCalendar currentCalendar] dateFromComponents:comps]; + NSLog(@"YYYY_MM_dd_HH_mm_ss_SSS_ZZZ %@",[formatter stringFromDate:date_radar]); + + // Radar correct behavior + [formatter setDateFormat:@"yyyy_MM_dd_HH_mm_ss_SSS_ZZZ"]; + NSLog(@"yyyy_MM_dd_HH_mm_ss_SSS_ZZZ %@",[formatter stringFromDate:date_radar]); + + // Radar correct behavior - week year + [formatter setDateFormat:@"YYYY_ww_dd_HH_mm_ss_SSS_ZZZ"]; + NSLog(@"YYYY_ww_dd_HH_mm_ss_SSS_ZZZ %@",[formatter stringFromDate:date_radar]); + + // Radar incorrect behavior + [formatter setDateFormat:@"yyyy_ww_dd_HH_mm_ss_SSS_ZZZ"]; + // CHECK-MESSAGES: :[[@LINE-1]]:35:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_ww_dd_HH_mm_ss_SSS_ZZZ %@",[formatter stringFromDate:date_radar]); + + NSLog(@"=========================================="); + // Correct + [formatter setDateFormat:@"yyyy_MM"]; + NSLog(@"yyyy_MM %@",[formatter stringFromDate:date_radar]); + + // Correct + [formatter setDateFormat:@"yyyy_dd"]; + NSLog(@"yyyy_dd %@",[formatter stringFromDate:date_radar]); + + // Correct + [formatter setDateFormat:@"yyyy_DD"]; + NSLog(@"yyyy_DD %@",[formatter stringFromDate:date_radar]); + + // Incorrect + [formatter setDateFormat:@"yyyy_ww"]; + // CHECK-MESSAGES: :[[@LINE-1]]:53:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_ww %@",[formatter stringFromDate:date_radar]); + + // Incorrect + [formatter setDateFormat:@"yyyy_WW"]; + // CHECK-MESSAGES: :[[@LINE-1]]:58:31: warning: Week of Month(W) used without the month(M); did you forget M in the format string? [objc-NSDateFormatter] + NSLog(@"yyyy_WW %@",[formatter stringFromDate:date_radar]); + + NSLog(@"=========================================="); + // Correct + [formatter setDateFormat:@"yyyy_MM_dd"]; + NSLog(@"yyyy_MM_dd %@",[formatter stringFromDate:date_radar]); + + // Potentially Incorrect + [formatter setDateFormat:@"yyyy_MM_DD"]; + NSLog(@"yyyy_MM_DD %@",[formatter stringFromDate:date_radar]); + + // Incorrect + [formatter setDateFormat:@"yyyy_MM_ww"]; + // CHECK-MESSAGES: :[[@LINE-1]]:72:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_MM_ww %@",[formatter stringFromDate:date_radar]); + + NSLog(@"=======WEEK YEAR=========="); + // Incorrect + [formatter setDateFormat:@"YYYY_MM"]; + // CHECK-MESSAGES: :[[@LINE-1]]:78:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_MM %@",[formatter stringFromDate:date_radar]); + + // Correct + [formatter setDateFormat:@"YYYY_ww"]; + NSLog(@"YYYY_ww %@",[formatter stringFromDate:date_radar]); + + // Incorrect + [formatter setDateFormat:@"YYYY_WW"]; + // CHECK-MESSAGES: :[[@LINE-1]]:87:31: warning: Week of Month(W) used without the month(M); did you forget M in the format string? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:87:31: warning: use of week year(Y) with week of the month(W); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_WW %@",[formatter stringFromDate:date_radar]); + + // Correct + [formatter setDateFormat:@"YYYY_dd"]; + NSLog(@"YYYY_dd %@",[formatter stringFromDate:date_radar]); + + // Incorrect + [formatter setDateFormat:@"YYYY_DD"]; + // CHECK-MESSAGES: :[[@LINE-1]]:97:31: warning: use of week year(Y) with day of the year(D); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_DD %@",[formatter stringFromDate:date_radar]); + + NSLog(@"=========================================="); + // Potentially Incorrect + [formatter setDateFormat:@"YYYY_ww_dd"]; + NSLog(@"YYYY ww dd %@",[formatter stringFromDate:date_radar]); + + // Incorrect + [formatter setDateFormat:@"YYYY_ww_DD"]; + // CHECK-MESSAGES: :[[@LINE-1]]:107:31: warning: use of week year(Y) with day of the year(D); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_ww_DD %@",[formatter stringFromDate:date_radar]); + + // Generating 2015-W01-1 : How? +} + ++(void)testMethod2{ + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + NSDateComponents *comps = [[NSDateComponents alloc] init]; + [comps setDay:29]; + [comps setMonth:12]; + [comps setYear:2014]; + NSDate *date_radar = [[NSCalendar currentCalendar] dateFromComponents:comps]; + + // Test 1 : incorrect + [formatter setDateFormat:@"yyyy_QQ_MM_ww_dd_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:123:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_QQ_MM_ww_dd_EE %@",[formatter stringFromDate:date_radar]); + + // Test 2 : incorrect + [formatter setDateFormat:@"yyyy_QQ_MM_ww_dd_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:128:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_QQ_MM_ww_dd_ee %@",[formatter stringFromDate:date_radar]); + + // Test 3 : incorrect + [formatter setDateFormat:@"yyyy_QQ_MM_ww_DD_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:133:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_QQ_MM_ww_DD_EE %@",[formatter stringFromDate:date_radar]); + + // Test 4 : incorrect + [formatter setDateFormat:@"yyyy_QQ_MM_ww_DD_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:138:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_QQ_MM_ww_DD_ee %@",[formatter stringFromDate:date_radar]); + + // Test 5 : incorrect + [formatter setDateFormat:@"yyyy_QQ_MM_ww_F_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:143:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_QQ_MM_ww_F_EE %@",[formatter stringFromDate:date_radar]); + + // Test 6 : incorrect + [formatter setDateFormat:@"yyyy_QQ_MM_ww_F_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:148:31: warning: use of calendar year(y) with week of the year(w); did you mean to use week-year(Y) instead? [objc-NSDateFormatter] + NSLog(@"yyyy_QQ_MM_ww_F_ee %@",[formatter stringFromDate:date_radar]); + + // Test 7 : correct + [formatter setDateFormat:@"yyyy_QQ_MM_WW_dd_EE"]; + NSLog(@"yyyy_QQ_MM_WW_dd_EE %@",[formatter stringFromDate:date_radar]); + + // Test 8 : correct + [formatter setDateFormat:@"yyyy_QQ_MM_WW_dd_ee"]; + NSLog(@"yyyy_QQ_MM_WW_dd_ee %@",[formatter stringFromDate:date_radar]); + + // Test 9 : correct + [formatter setDateFormat:@"yyyy_QQ_MM_WW_DD_EE"]; + NSLog(@"yyyy_QQ_MM_WW_DD_EE %@",[formatter stringFromDate:date_radar]); + + // Test 10 : correct + [formatter setDateFormat:@"yyyy_QQ_MM_WW_DD_ee"]; + NSLog(@"yyyy_QQ_MM_WW_DD_ee %@",[formatter stringFromDate:date_radar]); + + // Test 11 : correct + [formatter setDateFormat:@"yyyy_QQ_MM_WW_F_EE"]; + NSLog(@"yyyy_QQ_MM_WW_F_EE %@",[formatter stringFromDate:date_radar]); + + // Test 12 : correct + [formatter setDateFormat:@"yyyy_QQ_MM_WW_F_ee"]; + NSLog(@"yyyy_QQ_MM_WW_F_ee %@",[formatter stringFromDate:date_radar]); + + // Test 13 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_ww_dd_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:177:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:177:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_ww_dd_EE %@",[formatter stringFromDate:date_radar]); + + // Test 14 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_ww_dd_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:183:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:183:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_ww_dd_ee %@",[formatter stringFromDate:date_radar]); + + // Test 15 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_ww_DD_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:189:31: warning: use of week year(Y) with day of the year(D); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:189:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:189:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_ww_DD_EE %@",[formatter stringFromDate:date_radar]); + + // Test 16 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_ww_DD_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:196:31: warning: use of week year(Y) with day of the year(D); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:196:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:196:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_ww_DD_ee %@",[formatter stringFromDate:date_radar]); + + // Test 17 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_ww_F_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:203:31: warning: use of week year(Y) with day of the week in month(F); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:203:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:203:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_ww_F_EE %@",[formatter stringFromDate:date_radar]); + + // Test 18 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_ww_F_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:210:31: warning: use of week year(Y) with day of the week in month(F); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:210:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:210:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_ww_F_ee %@",[formatter stringFromDate:date_radar]); + + // Test 19 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_WW_dd_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:217:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:217:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:217:31: warning: use of week year(Y) with week of the month(W); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_WW_dd_EE %@",[formatter stringFromDate:date_radar]); + + // Test 20 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_WW_dd_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:224:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:224:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:224:31: warning: use of week year(Y) with week of the month(W); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_WW_dd_ee %@",[formatter stringFromDate:date_radar]); + + // Test 21 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_WW_DD_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:231:31: warning: use of week year(Y) with day of the year(D); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:231:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:231:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-4]]:231:31: warning: use of week year(Y) with week of the month(W); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_WW_DD_EE %@",[formatter stringFromDate:date_radar]); + + // Test 22 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_WW_DD_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:239:31: warning: use of week year(Y) with day of the year(D); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:239:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:239:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-4]]:239:31: warning: use of week year(Y) with week of the month(W); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_WW_DD_ee %@",[formatter stringFromDate:date_radar]); + + // Test 23 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_WW_F_EE"]; + // CHECK-MESSAGES: :[[@LINE-1]]:247:31: warning: use of week year(Y) with day of the week in month(F); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:247:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:247:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-4]]:247:31: warning: use of week year(Y) with week of the month(W); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_WW_F_EE %@",[formatter stringFromDate:date_radar]); + + // Test 24 : incorrect + [formatter setDateFormat:@"YYYY_QQ_MM_WW_F_ee"]; + // CHECK-MESSAGES: :[[@LINE-1]]:255:31: warning: use of week year(Y) with day of the week in month(F); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-2]]:255:31: warning: use of week year(Y) with month(M); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-3]]:255:31: warning: use of week year(Y) with quarter number(Q); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + // CHECK-MESSAGES: :[[@LINE-4]]:255:31: warning: use of week year(Y) with week of the month(W); did you mean to use calendar year(y) instead? [objc-NSDateFormatter] + NSLog(@"YYYY_QQ_MM_WW_F_ee %@",[formatter stringFromDate:date_radar]); +} + ++(void)testMethod3{ + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + NSDateComponents *comps = [[NSDateComponents alloc] init]; + [comps setDay:29]; + [comps setMonth:12]; + [comps setYear:2014]; + NSDate *date_radar = [[NSCalendar currentCalendar] dateFromComponents:comps]; + + // Incorrect : has reserved and invalid chars + [formatter setDateFormat:@"Rashmi"]; + // CHECK-MESSAGES: :[[@LINE-1]]:272:31: warning: invalid date format specifier [objc-NSDateFormatter] + NSLog(@"Rashmi %@",[formatter stringFromDate:date_radar]); + + // Correct + [formatter setDateFormat:@"AMy"]; + NSLog(@"AMy %@",[formatter stringFromDate:date_radar]); +} +@end