From 2c02d317e51058692042406a550ffb24cee937db Mon Sep 17 00:00:00 2001 From: Kevin Eady <8634912+KevinEady@users.noreply.github.com> Date: Mon, 9 Nov 2020 17:58:32 +0100 Subject: [PATCH] build: add pre-commit package for linting (#823) * build: add incremental clang-format checks * build: add pre-commit package for linting --- .clang-format | 111 ++++++++++++++++++++++++++++++++++++++++ .travis.yml | 1 + package.json | 9 +++- scripts/clang-format.js | 42 +++++++++++++++ 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 .clang-format create mode 100644 scripts/clang-format.js diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..4aad29c32 --- /dev/null +++ b/.clang-format @@ -0,0 +1,111 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^' + Priority: 2 + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 8 +UseTab: Never diff --git a/.travis.yml b/.travis.yml index 56f9c903c..642470330 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,7 @@ script: # Travis CI sets NVM_NODEJS_ORG_MIRROR, but it makes node-gyp fail to download headers for nightly builds. - unset NVM_NODEJS_ORG_MIRROR + - npm run lint - npm test after_success: - cpp-coveralls --gcov-options '\-lp' --build-root test/build --exclude test diff --git a/package.json b/package.json index 93f3fd81c..2d25d0aaa 100644 --- a/package.json +++ b/package.json @@ -264,8 +264,10 @@ "description": "Node.js API (N-API)", "devDependencies": { "benchmark": "^2.1.4", - "fs-extra": "^9.0.1", "bindings": "^1.5.0", + "clang-format": "^1.4.0", + "fs-extra": "^9.0.1", + "pre-commit": "^1.2.2", "safe-buffer": "^5.1.1" }, "directories": {}, @@ -300,7 +302,10 @@ "dev": "node test", "predev:incremental": "node-gyp configure build -C test --debug", "dev:incremental": "node test", - "doc": "doxygen doc/Doxyfile" + "doc": "doxygen doc/Doxyfile", + "lint": "node scripts/clang-format.js", + "lint:fix": "git-clang-format" }, + "pre-commit": "lint", "version": "3.0.2" } diff --git a/scripts/clang-format.js b/scripts/clang-format.js new file mode 100644 index 000000000..b44d47674 --- /dev/null +++ b/scripts/clang-format.js @@ -0,0 +1,42 @@ +#!/usr/bin/env node + +const spawn = require('child_process').spawnSync; +const path = require('path'); + +const filesToCheck = ['*.h', '*.cc']; +const CLANG_FORMAT_START = process.env.CLANG_FORMAT_START || 'master'; + +function main(args) { + let clangFormatPath = path.dirname(require.resolve('clang-format')); + const options = ['--binary=node_modules/.bin/clang-format', '--style=file']; + + const gitClangFormatPath = path.join(clangFormatPath, + 'bin/git-clang-format'); + const result = spawn('python', [ + gitClangFormatPath, + ...options, + '--diff', + CLANG_FORMAT_START, + 'HEAD', + ...filesToCheck + ], { encoding: 'utf-8' }); + + if (result.error) { + console.error('Error running git-clang-format:', result.error); + return 2; + } + + const clangFormatOutput = result.stdout.trim(); + if (clangFormatOutput !== ('no modified files to format') && + clangFormatOutput !== ('clang-format did not modify any files')) { + console.error(clangFormatOutput); + const fixCmd = '"npm run lint:fix"'; + console.error(` + ERROR: please run ${fixCmd} to format changes in your commit`); + return 1; + } +} + +if (require.main === module) { + process.exitCode = main(process.argv.slice(2)); +}