From dd53a9ebc4c1f6e15d54dd679efd35da6ec1312d Mon Sep 17 00:00:00 2001 From: AlexHaxe Date: Mon, 10 Jun 2024 21:44:12 +0200 Subject: [PATCH] added FileNameCase check (#527) * added FileNameCase check * removed escaping of `/` from XMLReporter --- .github/workflows/checkstyle-linux.yml | 13 +- CHANGELOG.md | 5 + checkstyle.json | 3 + haxelib.json | 4 +- package-lock.json | 4 +- package.json | 2 +- resources/checkstyle-excludes-schema.json | 116 +++++++------- resources/checkstyle-schema.json | 151 +++++++++++------- resources/default-config.json | 4 + src/checkstyle/checks/import.hx | 3 + .../checks/naming/FileNameCaseCheck.hx | 86 ++++++++++ src/checkstyle/import.hx | 7 +- src/checkstyle/reporter/XMLReporter.hx | 13 +- .../checks/naming/FileNameCaseCheckTest.hx | 73 +++++++++ test/checkstyle/config/ConfigParserTest.hx | 2 +- .../detect/DetectCodingStyleTest.hx | 14 +- testAndResources.hxml | 1 + 17 files changed, 363 insertions(+), 138 deletions(-) create mode 100644 src/checkstyle/checks/import.hx create mode 100644 src/checkstyle/checks/naming/FileNameCaseCheck.hx create mode 100644 test/checkstyle/checks/naming/FileNameCaseCheckTest.hx diff --git a/.github/workflows/checkstyle-linux.yml b/.github/workflows/checkstyle-linux.yml index f98b053c..649bef90 100644 --- a/.github/workflows/checkstyle-linux.yml +++ b/.github/workflows/checkstyle-linux.yml @@ -20,11 +20,11 @@ jobs: CC_TEST_REPORTER_ID: c4eda639526d39fbcab7ab9fc68c4046d4e597df56dbcb552b42d27b3580b758 CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} steps: - - uses: actions/checkout@v1 - - name: Use Node.js 12 - uses: actions/setup-node@v1 + - uses: actions/checkout@v4 + - name: Use Node.js 18 + uses: actions/setup-node@v4 with: - node-version: 12 + node-version: 18 - name: Installing codeclimate client if: matrix.haxe-version == 'nightly' run: | @@ -76,6 +76,11 @@ jobs: ../cc-test-reporter format-coverage -t lcov ../lcov.info; \ ../cc-test-reporter upload-coverage; \ ) + # - name: Checkstyle report annotations + # if: success() + # uses: jwgmeligmeyling/checkstyle-github-action@master + # with: + # path: '**/check-style-report.xml' - name: Upload results to codecov if: success() && (matrix.haxe-version == 'nightly') run: bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports" diff --git a/CHANGELOG.md b/CHANGELOG.md index d0faca63..d892fd8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## dev branch / next version (2.x.x) +## version 2.9.0 (2024-06-10) + +- New check `FileNameCase` to check file names match module names +- Fixed XMLReporter to no longer escape `/` to `/` + ## version 2.8.5 (2023-02-15) - Fixed inner assignement check to allow assignment in arrow functions, fixes [#259](https://github.com/HaxeCheckstyle/haxe-checkstyle/issues/259) diff --git a/checkstyle.json b/checkstyle.json index 3821a96c..f854447b 100644 --- a/checkstyle.json +++ b/checkstyle.json @@ -142,6 +142,9 @@ { "type": "FileLength" }, + { + "type": "FileNameCase" + }, { "props": { "option": "upperCase" diff --git a/haxelib.json b/haxelib.json index 97df673e..a951386e 100644 --- a/haxelib.json +++ b/haxelib.json @@ -18,8 +18,8 @@ "adireddy", "Gama11" ], - "releasenote": "updated tokentree lib - see CHANGELOG", - "version": "2.8.5", + "releasenote": "added FileNameCase check - see CHANGELOG", + "version": "2.9.0", "url": "https://github.com/HaxeCheckstyle/haxe-checkstyle", "dependencies": {} } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 32ee812b..e3ac7b4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@haxecheckstyle/haxe-checkstyle", - "version": "2.8.5", + "version": "2.9.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@haxecheckstyle/haxe-checkstyle", - "version": "2.8.5", + "version": "2.9.0", "license": "MIT", "bin": { "haxe-checkstyle": "bin/checkstyle.js" diff --git a/package.json b/package.json index acad5c81..5d151d31 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@haxecheckstyle/haxe-checkstyle", - "version": "2.8.5", + "version": "2.9.0", "description": "Automated code analysis ideal for projects that want to enforce a coding standard.", "repository": { "type": "git", diff --git a/resources/checkstyle-excludes-schema.json b/resources/checkstyle-excludes-schema.json index 1e79f7b8..4a1e2d8c 100644 --- a/resources/checkstyle-excludes-schema.json +++ b/resources/checkstyle-excludes-schema.json @@ -18,7 +18,7 @@ }, "UnusedImport": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 78 + "propertyOrder": 79 }, "Dynamic": { "$ref": "#/definitions/ExcludeFilterList", @@ -26,30 +26,30 @@ }, "Final": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 28 + "propertyOrder": 29 }, "MultipleStringLiterals": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 45 + "propertyOrder": 46 }, "NeedBraces": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 47 + "propertyOrder": 48 }, "SeparatorWhitespace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 64 + "propertyOrder": 65 }, "all": { "$ref": "#/definitions/ExcludeFilterList" }, "LocalVariableName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 38 + "propertyOrder": 39 }, "NestedForDepth": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 49 + "propertyOrder": 50 }, "Anonymous": { "$ref": "#/definitions/ExcludeFilterList", @@ -57,11 +57,11 @@ }, "MultipleVariableDeclarations": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 46 + "propertyOrder": 47 }, "NestedTryDepth": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 51 + "propertyOrder": 52 }, "BlockBreakingConditional": { "$ref": "#/definitions/ExcludeFilterList", @@ -81,7 +81,7 @@ }, "ReturnCount": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 62 + "propertyOrder": 63 }, "DefaultComesLast": { "$ref": "#/definitions/ExcludeFilterList", @@ -89,11 +89,11 @@ }, "HexadecimalLiteral": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 29 + "propertyOrder": 30 }, "WhitespaceAfter": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 82 + "propertyOrder": 83 }, "ConstantName": { "$ref": "#/definitions/ExcludeFilterList", @@ -105,23 +105,23 @@ }, "Interface": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 34 + "propertyOrder": 35 }, "WhitespaceAround": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 83 + "propertyOrder": 84 }, "NestedIfDepth": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 50 + "propertyOrder": 51 }, "ParameterName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 55 + "propertyOrder": 56 }, "NullableParameter": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 52 + "propertyOrder": 53 }, "AvoidStarImport": { "$ref": "#/definitions/ExcludeFilterList", @@ -129,7 +129,7 @@ }, "SeparatorWrap": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 65 + "propertyOrder": 66 }, "AvoidIdentifier": { "$ref": "#/definitions/ExcludeFilterList", @@ -137,19 +137,19 @@ }, "RedundantAllowMeta": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 59 + "propertyOrder": 60 }, "HiddenField": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 30 + "propertyOrder": 31 }, "UnnecessaryConstructor": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 77 + "propertyOrder": 78 }, "SimplifyBooleanExpression": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 66 + "propertyOrder": 67 }, "path": { "description": "filters excludes relative to\n\t- RELATIVE_TO_PROJECT = use project root\n\t- RELATIVE_TO_SOURCE = use path(s) specified via \"-s \" command line switches", @@ -161,23 +161,23 @@ }, "MethodCount": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 41 + "propertyOrder": 42 }, "UnusedLocalVar": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 79 + "propertyOrder": 80 }, "TabForAligning": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 71 + "propertyOrder": 72 }, "MethodName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 43 + "propertyOrder": 44 }, "RightCurly": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 63 + "propertyOrder": 64 }, "AvoidTernaryOperator": { "$ref": "#/definitions/ExcludeFilterList", @@ -185,7 +185,7 @@ }, "ParameterNumber": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 56 + "propertyOrder": 57 }, "ArrowFunction": { "$ref": "#/definitions/ExcludeFilterList", @@ -193,7 +193,7 @@ }, "MethodLength": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 42 + "propertyOrder": 43 }, "ConditionalCompilation": { "$ref": "#/definitions/ExcludeFilterList", @@ -205,7 +205,7 @@ }, "MemberName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 40 + "propertyOrder": 41 }, "ERegLiteral": { "$ref": "#/definitions/ExcludeFilterList", @@ -213,19 +213,23 @@ }, "RedundantModifier": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 60 + "propertyOrder": 61 }, "Type": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 74 + "propertyOrder": 75 }, "TypeName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 76 + "propertyOrder": 77 }, "Indentation": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 31 + "propertyOrder": 32 + }, + "FileNameCase": { + "$ref": "#/definitions/ExcludeFilterList", + "propertyOrder": 28 }, "CommentedOutCode": { "$ref": "#/definitions/ExcludeFilterList", @@ -238,39 +242,39 @@ }, "Return": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 61 + "propertyOrder": 62 }, "SimplifyBooleanReturn": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 67 + "propertyOrder": 68 }, "TODOComment": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 70 + "propertyOrder": 71 }, "VarTypeHint": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 80 + "propertyOrder": 81 }, "NestedControlFlow": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 48 + "propertyOrder": 49 }, "OperatorWhitespace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 53 + "propertyOrder": 54 }, "Spacing": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 68 + "propertyOrder": 69 }, "IndentationCharacter": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 32 + "propertyOrder": 33 }, "MagicNumber": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 39 + "propertyOrder": 40 }, "ArrayLiteral": { "$ref": "#/definitions/ExcludeFilterList", @@ -278,19 +282,19 @@ }, "TrailingWhitespace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 73 + "propertyOrder": 74 }, "VariableInitialisation": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 81 + "propertyOrder": 82 }, "LineLength": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 36 + "propertyOrder": 37 }, "ListenerName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 37 + "propertyOrder": 38 }, "FileLength": { "$ref": "#/definitions/ExcludeFilterList", @@ -302,11 +306,11 @@ }, "StringLiteral": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 69 + "propertyOrder": 70 }, "Trace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 72 + "propertyOrder": 73 }, "ArrayAccess": { "$ref": "#/definitions/ExcludeFilterList", @@ -314,7 +318,7 @@ }, "PublicAccessor": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 57 + "propertyOrder": 58 }, "DocCommentStyle": { "$ref": "#/definitions/ExcludeFilterList", @@ -322,11 +326,11 @@ }, "InnerAssignment": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 33 + "propertyOrder": 34 }, "RedundantAccessMeta": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 58 + "propertyOrder": 59 }, "CodeSimilarity": { "$ref": "#/definitions/ExcludeFilterList", @@ -334,19 +338,19 @@ }, "OperatorWrap": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 54 + "propertyOrder": 55 }, "TypeDocComment": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 75 + "propertyOrder": 76 }, "LeftCurly": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 35 + "propertyOrder": 36 }, "ModifierOrder": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 44 + "propertyOrder": 45 }, "FieldDocComment": { "$ref": "#/definitions/ExcludeFilterList", diff --git a/resources/checkstyle-schema.json b/resources/checkstyle-schema.json index ae757662..0cfe233f 100644 --- a/resources/checkstyle-schema.json +++ b/resources/checkstyle-schema.json @@ -2124,6 +2124,38 @@ }, "type": "object" }, + "FileNameCaseCheck": { + "description": "Checks that file names match the case of their module name.", + "additionalProperties": false, + "properties": { + "type": { + "description": "Checks that file names match the case of their module name.", + "type": "string", + "enum": [ + "FileNameCase" + ] + }, + "props": { + "description": "Checks that file names match the case of their module name.", + "additionalProperties": false, + "properties": { + "severity": { + "description": "sets gravity of reported violations:\n\t- IGNORE = do not report violations, violations do not appear anywhere in output\n\t- INFO = all violations have info / lowest priority\n\t- WARNING = all violations have warning / medium priority\n\t- ERROR = all violations have error / highest priority", + "type": "string", + "enum": [ + "INFO", + "WARNING", + "ERROR", + "IGNORE" + ], + "propertyOrder": 0 + } + }, + "type": "object" + } + }, + "type": "object" + }, "ListenerNameCheck": { "description": "Checks the naming conventions of event listener functions specified using `listeners` property.", "additionalProperties": false, @@ -3018,7 +3050,7 @@ }, "UnusedImport": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 78 + "propertyOrder": 79 }, "Dynamic": { "$ref": "#/definitions/ExcludeFilterList", @@ -3026,30 +3058,30 @@ }, "Final": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 28 + "propertyOrder": 29 }, "MultipleStringLiterals": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 45 + "propertyOrder": 46 }, "NeedBraces": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 47 + "propertyOrder": 48 }, "SeparatorWhitespace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 64 + "propertyOrder": 65 }, "all": { "$ref": "#/definitions/ExcludeFilterList" }, "LocalVariableName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 38 + "propertyOrder": 39 }, "NestedForDepth": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 49 + "propertyOrder": 50 }, "Anonymous": { "$ref": "#/definitions/ExcludeFilterList", @@ -3057,11 +3089,11 @@ }, "MultipleVariableDeclarations": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 46 + "propertyOrder": 47 }, "NestedTryDepth": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 51 + "propertyOrder": 52 }, "BlockBreakingConditional": { "$ref": "#/definitions/ExcludeFilterList", @@ -3081,7 +3113,7 @@ }, "ReturnCount": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 62 + "propertyOrder": 63 }, "DefaultComesLast": { "$ref": "#/definitions/ExcludeFilterList", @@ -3089,11 +3121,11 @@ }, "HexadecimalLiteral": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 29 + "propertyOrder": 30 }, "WhitespaceAfter": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 82 + "propertyOrder": 83 }, "ConstantName": { "$ref": "#/definitions/ExcludeFilterList", @@ -3105,23 +3137,23 @@ }, "Interface": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 34 + "propertyOrder": 35 }, "WhitespaceAround": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 83 + "propertyOrder": 84 }, "NestedIfDepth": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 50 + "propertyOrder": 51 }, "ParameterName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 55 + "propertyOrder": 56 }, "NullableParameter": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 52 + "propertyOrder": 53 }, "AvoidStarImport": { "$ref": "#/definitions/ExcludeFilterList", @@ -3129,7 +3161,7 @@ }, "SeparatorWrap": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 65 + "propertyOrder": 66 }, "AvoidIdentifier": { "$ref": "#/definitions/ExcludeFilterList", @@ -3137,19 +3169,19 @@ }, "RedundantAllowMeta": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 59 + "propertyOrder": 60 }, "HiddenField": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 30 + "propertyOrder": 31 }, "UnnecessaryConstructor": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 77 + "propertyOrder": 78 }, "SimplifyBooleanExpression": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 66 + "propertyOrder": 67 }, "path": { "description": "filters excludes relative to\n\t- RELATIVE_TO_PROJECT = use project root\n\t- RELATIVE_TO_SOURCE = use path(s) specified via \"-s \" command line switches", @@ -3161,23 +3193,23 @@ }, "MethodCount": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 41 + "propertyOrder": 42 }, "UnusedLocalVar": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 79 + "propertyOrder": 80 }, "TabForAligning": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 71 + "propertyOrder": 72 }, "MethodName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 43 + "propertyOrder": 44 }, "RightCurly": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 63 + "propertyOrder": 64 }, "AvoidTernaryOperator": { "$ref": "#/definitions/ExcludeFilterList", @@ -3185,7 +3217,7 @@ }, "ParameterNumber": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 56 + "propertyOrder": 57 }, "ArrowFunction": { "$ref": "#/definitions/ExcludeFilterList", @@ -3193,7 +3225,7 @@ }, "MethodLength": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 42 + "propertyOrder": 43 }, "ConditionalCompilation": { "$ref": "#/definitions/ExcludeFilterList", @@ -3205,7 +3237,7 @@ }, "MemberName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 40 + "propertyOrder": 41 }, "ERegLiteral": { "$ref": "#/definitions/ExcludeFilterList", @@ -3213,19 +3245,23 @@ }, "RedundantModifier": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 60 + "propertyOrder": 61 }, "Type": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 74 + "propertyOrder": 75 }, "TypeName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 76 + "propertyOrder": 77 }, "Indentation": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 31 + "propertyOrder": 32 + }, + "FileNameCase": { + "$ref": "#/definitions/ExcludeFilterList", + "propertyOrder": 28 }, "CommentedOutCode": { "$ref": "#/definitions/ExcludeFilterList", @@ -3238,39 +3274,39 @@ }, "Return": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 61 + "propertyOrder": 62 }, "SimplifyBooleanReturn": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 67 + "propertyOrder": 68 }, "TODOComment": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 70 + "propertyOrder": 71 }, "VarTypeHint": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 80 + "propertyOrder": 81 }, "NestedControlFlow": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 48 + "propertyOrder": 49 }, "OperatorWhitespace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 53 + "propertyOrder": 54 }, "Spacing": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 68 + "propertyOrder": 69 }, "IndentationCharacter": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 32 + "propertyOrder": 33 }, "MagicNumber": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 39 + "propertyOrder": 40 }, "ArrayLiteral": { "$ref": "#/definitions/ExcludeFilterList", @@ -3278,19 +3314,19 @@ }, "TrailingWhitespace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 73 + "propertyOrder": 74 }, "VariableInitialisation": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 81 + "propertyOrder": 82 }, "LineLength": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 36 + "propertyOrder": 37 }, "ListenerName": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 37 + "propertyOrder": 38 }, "FileLength": { "$ref": "#/definitions/ExcludeFilterList", @@ -3302,11 +3338,11 @@ }, "StringLiteral": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 69 + "propertyOrder": 70 }, "Trace": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 72 + "propertyOrder": 73 }, "ArrayAccess": { "$ref": "#/definitions/ExcludeFilterList", @@ -3314,7 +3350,7 @@ }, "PublicAccessor": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 57 + "propertyOrder": 58 }, "DocCommentStyle": { "$ref": "#/definitions/ExcludeFilterList", @@ -3322,11 +3358,11 @@ }, "InnerAssignment": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 33 + "propertyOrder": 34 }, "RedundantAccessMeta": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 58 + "propertyOrder": 59 }, "CodeSimilarity": { "$ref": "#/definitions/ExcludeFilterList", @@ -3334,19 +3370,19 @@ }, "OperatorWrap": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 54 + "propertyOrder": 55 }, "TypeDocComment": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 75 + "propertyOrder": 76 }, "LeftCurly": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 35 + "propertyOrder": 36 }, "ModifierOrder": { "$ref": "#/definitions/ExcludeFilterList", - "propertyOrder": 44 + "propertyOrder": 45 }, "FieldDocComment": { "$ref": "#/definitions/ExcludeFilterList", @@ -4352,6 +4388,9 @@ { "$ref": "#/definitions/FileLengthCheck" }, + { + "$ref": "#/definitions/FileNameCaseCheck" + }, { "$ref": "#/definitions/FinalCheck" }, diff --git a/resources/default-config.json b/resources/default-config.json index 4e044d3b..2a18ca4f 100644 --- a/resources/default-config.json +++ b/resources/default-config.json @@ -194,6 +194,10 @@ "ignoreEmptyLines": true } }, + { + "type": "FileNameCase", + "props": {} + }, { "type": "Final", "props": {} diff --git a/src/checkstyle/checks/import.hx b/src/checkstyle/checks/import.hx new file mode 100644 index 00000000..30322b3a --- /dev/null +++ b/src/checkstyle/checks/import.hx @@ -0,0 +1,3 @@ +package checkstyle.checks; + +import checkstyle.SeverityLevel; \ No newline at end of file diff --git a/src/checkstyle/checks/naming/FileNameCaseCheck.hx b/src/checkstyle/checks/naming/FileNameCaseCheck.hx new file mode 100644 index 00000000..022b229b --- /dev/null +++ b/src/checkstyle/checks/naming/FileNameCaseCheck.hx @@ -0,0 +1,86 @@ +package checkstyle.checks.naming; + +import haxe.io.Path; + +/** + Checks that file names match the case of their module name. +**/ +@name("FileNameCase") +@desc("Checks that file names match the case of their module name.") +class FileNameCaseCheck extends Check { + public function new() { + super(TOKEN); + } + + override function actualRun() { + var fileName:String = Path.withoutDirectory(checker.file.name); + fileName = Path.withoutExtension(fileName); + checkFile(fileName, checker); + } + + function checkFile(fileName:String, checker:Checker) { + var types:Array = getTypes(checker.getTokenTree()); + var lowerFileName:String = fileName.toLowerCase(); + if (fileName == "import") { + if (types.length <= 0) { + return; + } + log('"import.hx" contains types', 0, 0, 0, 0); + return; + } + if ((lowerFileName == "import") && (types.length == 0)) { + // ImPort.hx with types + log('"$fileName.hx" contains no types - consider renaming to "import.hx"', 0, 0, 0, 0); + return; + } + if (!types.contains(fileName)) { + for (type in types) { + var lowerType:String = type.toLowerCase(); + if (lowerType == lowerFileName) { + log('"$fileName.hx" defines type "$type" using different case', 0, 0, 0, 0); + } + } + log('"$fileName.hx" defines no type with name "$fileName"', 0, 0, 0, 0); + return; + } + } + + function getTypes(token:TokenTree):Array { + var types:Array = checker.getTokenTree().filterCallback(function(token:TokenTree, depth:Int):FilterResult { + return switch (token.tok) { + case Kwd(KwdAbstract) | Kwd(KwdClass) | Kwd(KwdEnum) | Kwd(KwdInterface) | Kwd(KwdTypedef): + FoundSkipSubtree; + default: + GoDeeper; + } + }); + var typeNames:Array = []; + for (type in types) { + switch (type.tok) { + case Kwd(KwdAbstract) | Kwd(KwdClass) | Kwd(KwdEnum) | Kwd(KwdInterface) | Kwd(KwdTypedef): + var child:Null = type.getFirstChild(); + if (child == null) { + continue; + } + switch (child.tok) { + case Const(CIdent(s)): + typeNames.push(s); + default: + } + default: + } + } + + return typeNames; + } + + override public function detectableInstances():DetectableInstances { + return [{ + fixed: [], + properties: [{ + propertyName: "severity", + values: [SeverityLevel.WARNING] + }] + }]; + } +} \ No newline at end of file diff --git a/src/checkstyle/import.hx b/src/checkstyle/import.hx index 8ad5834c..60d18d4b 100644 --- a/src/checkstyle/import.hx +++ b/src/checkstyle/import.hx @@ -1,7 +1,6 @@ package checkstyle; import checkstyle.Checker.LinePos; -import checkstyle.SeverityLevel; import checkstyle.detect.DetectableInstances; import checkstyle.utils.ErrorUtils; import haxe.Exception; @@ -18,4 +17,8 @@ using checkstyle.utils.ArrayUtils; using checkstyle.utils.ExprUtils; using checkstyle.utils.FieldUtils; using checkstyle.utils.StringUtils; -using tokentree.TokenTreeAccessHelper; \ No newline at end of file +using tokentree.TokenTreeAccessHelper; + +#if !macro +import checkstyle.SeverityLevel; +#end \ No newline at end of file diff --git a/src/checkstyle/reporter/XMLReporter.hx b/src/checkstyle/reporter/XMLReporter.hx index fadc89f0..e86d301c 100644 --- a/src/checkstyle/reporter/XMLReporter.hx +++ b/src/checkstyle/reporter/XMLReporter.hx @@ -10,16 +10,9 @@ class XMLReporter extends BaseReporter { Solution from mustache.js https://github.com/janl/mustache.js/blob/master/mustache.js#L49 **/ - static var ENTITY_MAP:Map = [ - "&" => "&", - "<" => "<", - ">" => ">", - '"' => """, - "'" => "'", - "/" => "/" - ]; - - static var ENTITY_RE:EReg = ~/[&<>"'\/]/g; + static var ENTITY_MAP:Map = ["&" => "&", "<" => "<", ">" => ">", '"' => """, "'" => "'"]; + + static var ENTITY_RE:EReg = ~/[&<>"']/g; public function new(numFiles:Int, checkCount:Int, usedCheckCount:Int, path:String, s:String, ns:Bool) { super(numFiles, checkCount, usedCheckCount, path, ns); diff --git a/test/checkstyle/checks/naming/FileNameCaseCheckTest.hx b/test/checkstyle/checks/naming/FileNameCaseCheckTest.hx new file mode 100644 index 00000000..b113da3b --- /dev/null +++ b/test/checkstyle/checks/naming/FileNameCaseCheckTest.hx @@ -0,0 +1,73 @@ +package checkstyle.checks.naming; + +class FileNameCaseCheckTest extends CheckTestCase { + @Test + public function testCorrectNaming() { + var check = new FileNameCaseCheck(); + assertNoMsg(check, IMPORT, "import.hx"); + assertNoMsg(check, TYPES, "Test.hx"); + assertNoMsg(check, TYPES, "ITest.hx"); + assertNoMsg(check, TYPES, "Test2.hx"); + assertNoMsg(check, TYPES, "Test3.hx"); + } + + @Test + public function testIncorrectImport() { + var check = new FileNameCaseCheck(); + assertMsg(check, IMPORT, '"Import.hx" contains no types - consider renaming to "import.hx"', "Import.hx"); + assertMsg(check, TYPES, '"import.hx" contains types', "import.hx"); + } + + @Test + public function testModuleWithNoTypes() { + var check = new FileNameCaseCheck(); + assertMsg(check, IMPORT, '"Main.hx" defines no type with name "Main"', "Main.hx"); + } + + @Test + public function testIncorrectCase() { + var check = new FileNameCaseCheck(); + + assertMessages(check, TYPES, [ + '"TeSt.hx" defines type "Test" using different case', + '"TeSt.hx" defines no type with name "TeSt"' + ], "TeSt.hx"); + + assertMessages(check, TYPES, [ + '"Itest.hx" defines type "ITest" using different case', + '"Itest.hx" defines no type with name "Itest"' + ], "Itest.hx"); + } +} + +enum abstract FileNameCaseCheckTests(String) to String { + var IMPORT = " + import haxe.io.Path; + import checkstyle.checks.Check; + + using StringTools; + "; + + var TYPES = " + class Test { + public var a:Int; + private var b:Int; + static var COUNT:Int = 1; + static inline var COUNT2:Int = 1; + var count5:Int = 1; + } + + interface ITest { + + } + + enum Test2 { + count; + a; + } + + typedef Test3 = { + var count1:Int; + var count2:String; + }"; +} \ No newline at end of file diff --git a/test/checkstyle/config/ConfigParserTest.hx b/test/checkstyle/config/ConfigParserTest.hx index cc6dbcd2..c3a0c7ed 100644 --- a/test/checkstyle/config/ConfigParserTest.hx +++ b/test/checkstyle/config/ConfigParserTest.hx @@ -4,7 +4,7 @@ import checkstyle.utils.ConfigUtils; class ConfigParserTest { static inline var LOCAL_PATH:String = "./"; - static inline var TEST_COUNT:Int = 80; + static inline var TEST_COUNT:Int = 81; @Test public function testCheckstyleConfig() { diff --git a/test/checkstyle/detect/DetectCodingStyleTest.hx b/test/checkstyle/detect/DetectCodingStyleTest.hx index 828f0be4..3c9f0a9a 100644 --- a/test/checkstyle/detect/DetectCodingStyleTest.hx +++ b/test/checkstyle/detect/DetectCodingStyleTest.hx @@ -36,6 +36,7 @@ import checkstyle.checks.metrics.CyclomaticComplexityCheck; import checkstyle.checks.modifier.FinalCheck; import checkstyle.checks.modifier.RedundantModifierCheck; import checkstyle.checks.naming.ConstantNameCheck; +import checkstyle.checks.naming.FileNameCaseCheck; import checkstyle.checks.size.FileLengthCheck; import checkstyle.checks.size.LineLengthCheck; import checkstyle.checks.size.MethodCountCheck; @@ -72,8 +73,7 @@ class DetectCodingStyleTest { @Test public function testDetectConditionalCompilation() { - var detectedChecks:Array = DetectCodingStyle.detectCodingStyle([new ConditionalCompilationCheck()], - [buildCheckFile(SAMPLE_CODING_STYLE)]); + var detectedChecks:Array = DetectCodingStyle.detectCodingStyle([new ConditionalCompilationCheck()], [buildCheckFile(SAMPLE_CODING_STYLE)]); Assert.areEqual(1, detectedChecks.length); Assert.areEqual("ConditionalCompilation", detectedChecks[0].type); var props = cast detectedChecks[0].props; @@ -288,8 +288,7 @@ class DetectCodingStyleTest { @Test public function testDetectUnnecessaryConstructor() { - var detectedChecks:Array = DetectCodingStyle.detectCodingStyle([new UnnecessaryConstructorCheck()], - [buildCheckFile(SAMPLE_CODING_STYLE)]); + var detectedChecks:Array = DetectCodingStyle.detectCodingStyle([new UnnecessaryConstructorCheck()], [buildCheckFile(SAMPLE_CODING_STYLE)]); Assert.areEqual(1, detectedChecks.length); Assert.areEqual("UnnecessaryConstructor", detectedChecks[0].type); } @@ -381,6 +380,13 @@ class DetectCodingStyleTest { Assert.areEqual("^[A-Z][A-Z0-9]*(_[A-Z0-9_]+)*$", props.format); } + @Test + public function testDetectFileNameCase() { + var detectedChecks:Array = DetectCodingStyle.detectCodingStyle([new FileNameCaseCheck()], [buildCheckFile(SAMPLE_CODING_STYLE)]); + Assert.areEqual(1, detectedChecks.length); + Assert.areEqual("FileNameCase", detectedChecks[0].type); + } + // checkstyle.checks.size @Test public function testDetectFileLength() { diff --git a/testAndResources.hxml b/testAndResources.hxml index 4b12abe4..fda7ae18 100644 --- a/testAndResources.hxml +++ b/testAndResources.hxml @@ -2,5 +2,6 @@ build/commonTest.hxml -x TestMain -cmd neko run -s src -s test -s schema -s build -p resources/static-analysis.txt +-cmd neko run -s src -s test -s schema -s build -r xml -cmd neko run --default-config resources/default-config.json -cmd neko run -c resources/default-config.json