├── .gitignore ├── .travis.yml ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── feature.png ├── package.json ├── src ├── configuration.ts ├── extension.ts ├── lint.ts └── runner.ts ├── test ├── extension.test.ts └── index.ts ├── tsconfig.json └── vsc-extension-quickstart.md /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - "6" 6 | 7 | os: 8 | - osx 9 | - linux 10 | 11 | before_install: 12 | - if [ $TRAVIS_OS_NAME == "linux" ]; then 13 | export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0; 14 | sh -e /etc/init.d/xvfb start; 15 | sleep 3; 16 | sudo apt-get install python -y; 17 | sudo pip install cpplint; 18 | which cpplint; 19 | fi 20 | - if [ $TRAVIS_OS_NAME == "macos" ]; then 21 | brew install python virtualenv; 22 | pip install cpplint; 23 | which cpplint; 24 | fi 25 | 26 | install: 27 | - node --version 28 | - npm --version 29 | - npm install 30 | - npm run vscode:prepublish 31 | 32 | script: 33 | - npm test --silent -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.1.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], 11 | "stopOnEntry": false, 12 | "sourceMaps": true, 13 | "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], 14 | "preLaunchTask": "npm" 15 | }, 16 | { 17 | "name": "Launch Tests", 18 | "type": "extensionHost", 19 | "request": "launch", 20 | "runtimeExecutable": "${execPath}", 21 | "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], 22 | "stopOnEntry": false, 23 | "sourceMaps": true, 24 | "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ], 25 | "preLaunchTask": "npm" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | } 9 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // Available variables which can be used inside of strings. 2 | // ${workspaceRoot}: the root folder of the team 3 | // ${file}: the current opened file 4 | // ${fileBasename}: the current opened file's basename 5 | // ${fileDirname}: the current opened file's dirname 6 | // ${fileExtname}: the current opened file's extension 7 | // ${cwd}: the current working directory of the spawned process 8 | 9 | // A task runner that calls a custom npm script that compiles the extension. 10 | { 11 | "version": "0.1.0", 12 | 13 | // we want to run npm 14 | "command": "npm", 15 | 16 | // the command is a shell script 17 | "isShellCommand": true, 18 | 19 | // show the output window only if unrecognized errors occur. 20 | "showOutput": "silent", 21 | 22 | // we run the custom script "compile" as defined in package.json 23 | "args": ["run", "compile", "--loglevel", "silent"], 24 | 25 | // The tsc compiler is started in watching mode 26 | "isBackground": true, 27 | 28 | // use the standard tsc in watch mode problem matcher to find compile problems in the output. 29 | "problemMatcher": "$tsc-watch" 30 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | out/test/** 4 | test/** 5 | src/** 6 | **/*.map 7 | .gitignore 8 | tsconfig.json 9 | vsc-extension-quickstart.md 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to the "cpplint" extension will be documented in this file. 3 | 4 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 5 | 6 | ## [0.1.3] 7 | ### Change 8 | 9 | - for earlier versions of cpplint -- g-arjones 10 | 11 | ## [0.1.2] 12 | ### Change 13 | 14 | - fix cpplint in 500ms when setting and save happened to avoid large file freeze 15 | 16 | ## [0.1.0] 17 | ### Change 18 | 19 | - update vscode baseline to 1.21 20 | - when exclude is a relative path, multiroot will scaned 21 | 22 | ## [0.1.0] 23 | ### Change 24 | 25 | - configure to ConfigManager singletone 26 | - lint when file open 27 | 28 | ## [0.0.10] 29 | ### Add 30 | 31 | - add lint language settings 32 | 33 | ### fix 34 | 35 | - when no active editer exists, extension will crash 36 | 37 | ## [0.0.9] 38 | ### Add 39 | 40 | - add extensions and header setting arguments 41 | 42 | ## [0.0.8] 43 | ### Add 44 | 45 | - add root and repository setting arguments 46 | 47 | ## [0.0.6 - 0.0.7] 48 | ### Add 49 | 50 | - add multi root support 51 | 52 | ## [0.0.5] 53 | 54 | - add line length configuration 55 | - add travis ci status 56 | - add exclude configuration 57 | - add filters configuration 58 | - add verbose configuration 59 | 60 | ## [0.0.4] 61 | 62 | - fix readme image 63 | - add source link 64 | 65 | ## [0.0.3] 66 | 67 | - add lintMode, able to choose scan single file or the whole workspace 68 | 69 | ## [0.0.2] 70 | 71 | - add missing dependence of lodash 72 | 73 | ## [0.0.1] 74 | 75 | - Initial release -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 secularbird 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpplint README 2 | 3 | This extension utilizes the cpplint checker to provide C and C++ code style checker within Visual Studio Code. 4 | 5 | [](https://travis-ci.org/secularbird/cpplint-extension) 6 | 7 | ## Features 8 | 9 | * check coding style of cpp and c, when open and save source file 10 | 11 |  12 | 13 | ## Requirements 14 | 15 | ### Install cpplint 16 | 17 | #### Install from source 18 | 19 | https://github.com/cpplint/cpplint 20 | 21 | #### Mac & Linux 22 | 23 | ```bash 24 | sudo pip install cpplint 25 | ``` 26 | 27 | #### Windows 28 | 29 | * install anaconda 30 | download link: https://repo.continuum.io/archive/Anaconda2-5.0.0-Windows-x86_64.exe 31 | 32 | * install cpplint 33 | open the anaconda Prompt, run the following command 34 | ```batch 35 | pip install cpplint 36 | ``` 37 | 38 | #### Check the install result 39 | 40 | ##### Linux 41 | 42 | ```text 43 | ls -l /usr/local/bin/cpplint 44 | -rwxr-xr-x 1 root root 381 May 3 08:19 /usr/local/bin/cpplint 45 | ``` 46 | 47 | ##### Mac 48 | 49 | ```bash 50 | ls -l /opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/cpplint 51 | -rwxr-xr-x 1 root wheel 468 Apr 30 22:57 /opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/cpplint 52 | ``` 53 | 54 | or 55 | 56 | ```bash 57 | ls -l /opt/local/Library/Frameworks/Python.framework/Versions/3.5/bin/cpplint 58 | -rwxr-xr-x 1 root wheel 267 Apr 30 22:03 /opt/local/Library/Frameworks/Python.framework/Versions/3.5/bin/cpplint 59 | ``` 60 | 61 | ##### Windows 62 | 63 | ``` bath 64 | dir c:\ProgramData\Anaconda2\Scripts\cpplint.exe 65 | ``` 66 | 67 | ## Extension Settings 68 | 69 | * `cpplint.cpplintPath`: set cpplint executable path, path on windows should like `c:\\ProgramData\\Anaconda2\\Scripts\\cpplint.exe` 70 | * `cpplint.lintMode`: set cpplint mode, avialable value are single and workspace 71 | * `cpplint.lineLength`: set line length strict, default is 80 characters 72 | * `cpplint.excludes`: set exclude rules, which is related path and shell globbing is preforming, abosluted path is supported right now, 73 |
Examples: 74 | ["one.cc"] 75 | ["src/\*.cc"] 76 | ["src/\*.cc", "test/\*.cc"]77 | * `cpplint.filters`: set filters, only error messages whose category names pass the filters will be printed 78 | * `cpplint.root`: set the root directory used for deriving header guard CPP variables 79 | * `cpplint.repository`: set top level directory of the repository, used to derive the header guard CPP variable 80 | * `cpplint.extensions`: set the allowed file extensions that cpplint will check 81 | * `cpplint.languages`: set the allowed vscode language identifiers that cpplint will check *(Currently only on single file mode)* 82 | * `cpplint.headers`: set the allowed header extensions that cpplint will consider to be header files 83 | * `cpplint.verbose`: verbose level, errors with lower verbosity levels have lower confidence and are more likely to be false positives 84 | 85 | ## Known Issues 86 | 87 | Any issues please contact: [cpplint](https://github.com/secularbird/cpplint-extension/issues) 88 | -------------------------------------------------------------------------------- /feature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/secularbird/cpplint-extension/e9b3696b6ea780f5ba4d474d0c08c518b179abe6/feature.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cpplint", 3 | "displayName": "cpplint", 4 | "description": "code style check tool extension for cpplint", 5 | "version": "0.1.3", 6 | "publisher": "mine", 7 | "repository": { 8 | "type": "Git", 9 | "url": "https://github.com/secularbird/cpplint-extension" 10 | }, 11 | "engines": { 12 | "vscode": "^1.21.0" 13 | }, 14 | "categories": [ 15 | "Linters" 16 | ], 17 | "keywords": [ 18 | "multi-root ready" 19 | ], 20 | "activationEvents": [ 21 | "onLanguage:cpp", 22 | "onLanguage:c", 23 | "onCommand:cpplint.runAnalysis", 24 | "onCommand:cpplint.runWholeAnalysis" 25 | ], 26 | "main": "./out/src/extension", 27 | "contributes": { 28 | "commands": [ 29 | { 30 | "command": "cpplint.runAnalysis", 31 | "title": "Analyze current file", 32 | "category": "cpplinter" 33 | }, 34 | { 35 | "command": "cpplint.runWholeAnalysis", 36 | "title": "Analyze current workspace", 37 | "category": "cpplinter" 38 | } 39 | ], 40 | "configuration": { 41 | "type": "object", 42 | "title": "cpplint", 43 | "properties": { 44 | "cpplint.cpplintPath": { 45 | "type": "string", 46 | "default": "/usr/local/bin/cpplint", 47 | "description": "The path to the cpplint executable. If not set, the default location will be used." 48 | }, 49 | "cpplint.lintMode": { 50 | "type": "string", 51 | "default": "single", 52 | "enum": [ 53 | "single", 54 | "workspace" 55 | ], 56 | "description": "single is fast, only provides information of current active file, workspace is slow, provides informations of the whole workspace" 57 | }, 58 | "cpplint.lineLength": { 59 | "type": "number", 60 | "default": 80, 61 | "description": "This is the allowed line length for the project." 62 | }, 63 | "cpplint.excludes": { 64 | "type": "array", 65 | "default": [], 66 | "description": "Exclude the given path from the list of files to be linted.Relative paths are evaluated relative to the current directory and shell globbing is performed" 67 | }, 68 | "cpplint.filters": { 69 | "type": "array", 70 | "default": [], 71 | "description": "Specify a comma-separated list of category-filters to apply: only error messages whose category names pass the filters will be printed." 72 | }, 73 | "cpplint.verbose": { 74 | "type": "number", 75 | "default": 0, 76 | "enum": [ 77 | 0, 78 | 1, 79 | 2, 80 | 4, 81 | 5 82 | ], 83 | "description": "Specify a number 0-5 to restrict errors to certain verbosity levels. Errors with lower verbosity levels have lower confidence and are more likely to be false positives." 84 | }, 85 | "cpplint.repository": { 86 | "type": "string", 87 | "default": "${workspaceFolder}", 88 | "description": "The top level directory of the repository, used to derive the header guard CPP variable. By default, this is determined by searching for a path that contains .git, .hg, or .svn. When this flag is specified, the given path is used instead. This option allows the header guard CPP variable to remain consistent even if members of a team have different repository root directories (such as when checking out a subdirectory with SVN). In addition, users of non-mainstream version control systems can use this flag to ensure readable header guard CPP variables." 89 | }, 90 | "cpplint.root": { 91 | "type": "string", 92 | "default": "${workspaceFolder}/include", 93 | "description": "The root directory used for deriving header guard CPP variables. This directory is relative to the top level directory of the repository which by default is determined by searching for a directory that contains .git, .hg, or .svn but can also be controlled with the --repository flag. If the specified directory does not exist, this flag is ignored." 94 | }, 95 | "cpplint.extensions": { 96 | "type": "array", 97 | "default": [ 98 | "cpp", 99 | "h++", 100 | "cuh", 101 | "c", 102 | "c++", 103 | "cu", 104 | "hxx", 105 | "hpp", 106 | "cc", 107 | "cxx", 108 | "h" 109 | ], 110 | "description": "The allowed file extensions that cpplint will check." 111 | }, 112 | "cpplint.languages": { 113 | "type": "array", 114 | "default": [ 115 | "cpp", 116 | "c" 117 | ], 118 | "description": "The allowed vscode language identifiers that cpplint will check." 119 | }, 120 | "cpplint.headers": { 121 | "type": "array", 122 | "default": [ 123 | "h++", 124 | "cuh", 125 | "hxx", 126 | "hpp", 127 | "h" 128 | ], 129 | "description": "The allowed header extensions that cpplint will consider to be header files." 130 | } 131 | } 132 | } 133 | }, 134 | "scripts": { 135 | "vscode:prepublish": "tsc -p ./", 136 | "compile": "tsc -watch -p ./", 137 | "postinstall": "node ./node_modules/vscode/bin/install", 138 | "test": "node ./node_modules/vscode/bin/test" 139 | }, 140 | "devDependencies": { 141 | "typescript": "^2.0.3", 142 | "vscode": "^1.0.0", 143 | "mocha": "^2.3.3", 144 | "@types/node": "^6.0.40", 145 | "@types/mocha": "^2.2.32" 146 | }, 147 | "dependencies": { 148 | "lodash": "^4.17.4" 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/configuration.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import * as vscode from 'vscode'; 4 | import { platform } from 'os'; 5 | import { join } from 'path'; 6 | import { each, isNull } from 'lodash'; 7 | import { existsSync } from 'fs'; 8 | 9 | export class ConfigManager { 10 | 11 | private static _instance: ConfigManager = new ConfigManager(); 12 | 13 | private config: { [key: string]: any } = {}; 14 | 15 | constructor() { 16 | if (ConfigManager._instance) { 17 | throw new Error("Error: Instantiation failed: Use ConfigManager.getInstance() instead of new."); 18 | } 19 | ConfigManager._instance = this; 20 | } 21 | 22 | public static getInstance(): ConfigManager { 23 | return ConfigManager._instance; 24 | } 25 | 26 | public getConfig(): { [key: string]: any } { 27 | return this.config; 28 | } 29 | 30 | private findCpplintPath(settings: vscode.WorkspaceConfiguration): string { 31 | let cpplintPath = settings.get('cpplintPath', null); 32 | 33 | if (isNull(cpplintPath)) { 34 | let p = platform(); 35 | if (p === 'win32') { 36 | // TODO: add win32 and win64 cpplint path 37 | } 38 | else if (p === 'linux' || p === 'darwin') { 39 | let attempts = ['/usr/local/bin/cpplint']; 40 | for (let index = 0; index < attempts.length; index++) { 41 | if (existsSync(attempts[index])) { 42 | cpplintPath = attempts[index]; 43 | break; 44 | } 45 | } 46 | } 47 | } 48 | 49 | return cpplintPath; 50 | } 51 | 52 | public isSingleMode(): boolean { 53 | if (this.config['lintMode'] == 'single') { 54 | return true; 55 | } else { 56 | return false; 57 | } 58 | } 59 | 60 | public isSupportLanguage(language: string): boolean { 61 | if (this.config["languages"].indexOf(language) >= 0) { 62 | return true; 63 | } else { 64 | return false; 65 | } 66 | } 67 | 68 | public initialize() { 69 | this.config = {}; 70 | let settings = vscode.workspace.getConfiguration('cpplint'); 71 | 72 | if (settings) { 73 | var cpplintPath = this.findCpplintPath(settings); 74 | 75 | if (!existsSync(cpplintPath)) { 76 | vscode.window.showErrorMessage('Cpplint: Could not find cpplint executable'); 77 | } 78 | 79 | this.config['cpplintPath'] = cpplintPath; 80 | 81 | var linelength = settings.get("lineLength", 80); 82 | this.config['lineLength'] = linelength; 83 | 84 | var lintmode = settings.get('lintMode', 'single'); 85 | this.config['lintMode'] = lintmode; 86 | 87 | var excludes = settings.get('excludes', []) 88 | this.config['excludes'] = excludes; 89 | 90 | var filters = settings.get("filters", []) 91 | this.config["filters"] = filters; 92 | 93 | var root = settings.get("root", "") 94 | this.config["root"] = root; 95 | 96 | var languages = settings.get("languages", []) 97 | this.config["languages"] = languages; 98 | 99 | var extensions = settings.get("extensions", "") 100 | this.config["extensions"] = extensions; 101 | 102 | var headers = settings.get("headers", "") 103 | this.config["headers"] = headers; 104 | 105 | var repository = settings.get("repository", "") 106 | this.config["repository"] = repository; 107 | 108 | this.config["filters"].forEach(element => { 109 | if (element[0] != '-' && element[0] != '+') { 110 | vscode.window.showErrorMessage("filter [" + element + '] must start with + or -, please check your settings'); 111 | return false; 112 | } 113 | }); 114 | 115 | var verbose = settings.get("verbose", 0) 116 | this.config['verbose'] = verbose; 117 | } 118 | return this.config; 119 | } 120 | } -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // The module 'vscode' contains the VS Code extensibility API 3 | // Import the module and reference it with the alias vscode in your code below 4 | import * as vscode from 'vscode'; 5 | import * as an from './runner'; 6 | import { Lint } from './lint'; 7 | import { analysisResult } from './lint' 8 | import * as configuration from './configuration' 9 | import { ConfigManager } from './configuration'; 10 | 11 | let outputChannel: vscode.OutputChannel; 12 | let statusItem: vscode.StatusBarItem; 13 | let timer: NodeJS.Timer; 14 | 15 | let diagnosticCollection: vscode.DiagnosticCollection = vscode.languages.createDiagnosticCollection('cpplint'); 16 | 17 | // this method is called when your extension is activated 18 | // your extension is activated the very first time the command is executed 19 | export function activate(context: vscode.ExtensionContext) { 20 | outputChannel = vscode.window.createOutputChannel('CppLint'); 21 | // outputChannel.appendLine('CppLint is running.'); 22 | // Use the console to output diagnostic information (console.log) and errors (console.error) 23 | // This line of code will only be executed once when your extension is activated 24 | console.log('Congratulations, your extension "cpplint" is now active!'); 25 | 26 | loadConfigure(); 27 | 28 | // The command has been defined in the package.json file 29 | // Now provide the implementation of the command with registerCommand 30 | // The commandId parameter must match the command field in package.json 31 | 32 | let single = vscode.commands.registerCommand('cpplint.runAnalysis', runAnalysis); 33 | context.subscriptions.push(single); 34 | 35 | let whole = vscode.commands.registerCommand('cpplint.runWholeAnalysis', runWholeAnalysis); 36 | context.subscriptions.push(whole); 37 | 38 | vscode.workspace.onDidChangeConfiguration((()=>loadConfigure()).bind(this)); 39 | } 40 | 41 | function runAnalysis(): Promise