Skip to content
This repository was archived by the owner on Aug 7, 2023. It is now read-only.

Commit 95d152e

Browse files
authored
Merge pull request #191 from AtomLinter/arcanemagus/cleanup
Update to Linter v2
2 parents 5f633c6 + 363109f commit 95d152e

File tree

7 files changed

+260
-95
lines changed

7 files changed

+260
-95
lines changed

lib/main.js

Lines changed: 157 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,201 @@
11
'use babel';
22

3-
export default {
4-
config: {
5-
// It should be noted that I, Kepler, hate these Config names. However these
6-
// are the names in use by many people. Changing them for the sake of clean
7-
// of clean code would cause a mess for our users. Because of this we
8-
// override the titles the editor gives them in the settings pane.
9-
execPath: {
10-
type: 'string',
11-
default: 'clang',
12-
},
13-
clangIncludePaths: {
14-
type: 'array',
15-
default: ['.'],
16-
},
17-
clangSuppressWarnings: {
18-
type: 'boolean',
19-
default: false,
20-
},
21-
clangDefaultCFlags: {
22-
type: 'string',
23-
default: '-Wall',
24-
},
25-
clangDefaultCppFlags: {
26-
type: 'string',
27-
default: '-Wall -std=c++11',
28-
},
29-
clangDefaultObjCFlags: {
30-
type: 'string',
31-
default: '',
32-
},
33-
clangDefaultObjCppFlags: {
34-
type: 'string',
35-
default: '',
36-
},
37-
clangErrorLimit: {
38-
type: 'integer',
39-
default: 0,
40-
},
41-
verboseDebug: {
42-
type: 'boolean',
43-
default: false,
44-
},
45-
},
3+
// eslint-disable-next-line import/extensions, import/no-extraneous-dependencies
4+
import { CompositeDisposable } from 'atom';
5+
import { dirname, extname } from 'path';
466

7+
let helpers = null;
8+
let clangFlags = null;
9+
const regex = /(.+):(\d+):(\d+):(?:{(\d+):(\d+)-(\d+):(\d+)}.*:)? ([\w \\-]+): (.*)/g;
10+
11+
export default {
4712
activate() {
4813
require('atom-package-deps').install('linter-clang');
14+
15+
// FIXME: Remove backwards compatibility in a future minor version
16+
const oldPath = atom.config.get('linter-clang.execPath');
17+
if (oldPath !== undefined) {
18+
atom.config.unset('linter-clang.execPath');
19+
if (oldPath !== 'clang') {
20+
// If the old config wasn't set to the default migrate it over
21+
atom.config.set('linter-pylint.executablePath', oldPath);
22+
}
23+
}
24+
25+
this.subscriptions = new CompositeDisposable();
26+
this.subscriptions.add(
27+
atom.config.observe('linter-clang.executablePath', (value) => {
28+
this.executablePath = value;
29+
}),
30+
);
31+
this.subscriptions.add(
32+
atom.config.observe('linter-clang.clangIncludePaths', (value) => {
33+
this.clangIncludePaths = value;
34+
}),
35+
);
36+
this.subscriptions.add(
37+
atom.config.observe('linter-clang.clangSuppressWarnings', (value) => {
38+
this.clangSuppressWarnings = value;
39+
}),
40+
);
41+
this.subscriptions.add(
42+
atom.config.observe('linter-clang.clangDefaultCFlags', (value) => {
43+
this.clangDefaultCFlags = value;
44+
}),
45+
);
46+
this.subscriptions.add(
47+
atom.config.observe('linter-clang.clangDefaultCppFlags', (value) => {
48+
this.clangDefaultCppFlags = value;
49+
}),
50+
);
51+
this.subscriptions.add(
52+
atom.config.observe('linter-clang.clangDefaultObjCFlags', (value) => {
53+
this.clangDefaultObjCFlags = value;
54+
}),
55+
);
56+
this.subscriptions.add(
57+
atom.config.observe('linter-clang.clangDefaultObjCppFlags', (value) => {
58+
this.clangDefaultObjCppFlags = value;
59+
}),
60+
);
61+
this.subscriptions.add(
62+
atom.config.observe('linter-clang.clangErrorLimit', (value) => {
63+
this.clangErrorLimit = value;
64+
}),
65+
);
66+
},
67+
68+
deactivate() {
69+
this.subscriptions.dispose();
4970
},
5071

5172
provideLinter() {
52-
const helpers = require('atom-linter');
53-
const clangFlags = require('clang-flags');
54-
const regex = '(?<file>.+):(?<line>\\d+):(?<col>\\d+):({(?<lineStart>\\d+):(?<colStart>\\d+)-(?<lineEnd>\\d+):(?<colEnd>\\d+)}.*:)? (?<type>[\\w \\-]+): (?<message>.*)';
5573
return {
5674
name: 'clang',
57-
grammarScopes: ['source.c', 'source.cpp', 'source.objc', 'source.objcpp'],
5875
scope: 'file',
59-
lintOnFly: false,
60-
lint: (activeEditor) => {
61-
const command = atom.config.get('linter-clang.execPath');
62-
const file = activeEditor.getPath();
63-
const args = ['-fsyntax-only',
76+
lintsOnChange: false,
77+
grammarScopes: ['source.c', 'source.cpp', 'source.objc', 'source.objcpp'],
78+
lint: async (editor) => {
79+
if (helpers === null) {
80+
helpers = require('atom-linter');
81+
}
82+
if (clangFlags === null) {
83+
clangFlags = require('clang-flags');
84+
}
85+
86+
const filePath = editor.getPath();
87+
const fileExt = extname(filePath);
88+
const fileText = editor.getText();
89+
90+
const args = [
91+
'-fsyntax-only',
6492
'-fno-caret-diagnostics',
6593
'-fno-diagnostics-fixit-info',
6694
'-fdiagnostics-print-source-range-info',
67-
'-fexceptions'];
95+
'-fexceptions',
96+
`-ferror-limit=${this.clangErrorLimit}`,
97+
];
6898

69-
const grammar = activeEditor.getGrammar().name;
99+
const grammar = editor.getGrammar().name;
70100

71-
if (/^C\+\+/.test(grammar)) {
72-
// const language = "c++";
73-
args.push('-xc++');
74-
args.push(...atom.config.get('linter-clang.clangDefaultCppFlags').split(/\s+/));
75-
}
76-
if (grammar === 'Objective-C++') {
77-
// const language = "objective-c++";
78-
args.push('-xobjective-c++');
79-
args.push(...atom.config.get('linter-clang.clangDefaultObjCppFlags').split(/\s+/));
101+
switch (grammar) {
102+
case 'Objective-C':
103+
args.push('-xobjective-c');
104+
args.push(...this.clangDefaultObjCFlags.split(/\s+/));
105+
break;
106+
case 'Objective-C++':
107+
args.push('-xobjective-c++');
108+
args.push(...this.clangDefaultObjCppFlags.split(/\s+/));
109+
break;
110+
case 'C':
111+
args.push('-xc');
112+
args.push(...this.clangDefaultCFlags.split(/\s+/));
113+
break;
114+
default:
115+
case 'C++':
116+
case 'C++14':
117+
args.push('-xc++');
118+
args.push(...this.clangDefaultCppFlags.split(/\s+/));
119+
break;
80120
}
81-
if (grammar === 'C') {
82-
// const language = "c";
83-
args.push('-xc');
84-
args.push(...atom.config.get('linter-clang.clangDefaultCFlags').split(/\s+/));
85-
}
86-
if (grammar === 'Objective-C') {
87-
// const language = "objective-c";
88-
args.push('-xobjective-c');
89-
args.push(...atom.config.get('linter-clang.clangDefaultObjCFlags').split(/\s+/));
121+
122+
if (fileExt === '.hpp' || fileExt === '.hh' || fileExt === '.h') {
123+
// Don't warn about #pragma once when linting header files
124+
args.push('-Wno-pragma-once-outside-header');
90125
}
91126

92-
args.push(`-ferror-limit=${atom.config.get('linter-clang.clangErrorLimit')}`);
93-
if (atom.config.get('linter-clang.clangSuppressWarnings')) {
127+
if (this.clangSuppressWarnings) {
94128
args.push('-w');
95129
}
96-
if (atom.config.get('linter-clang.verboseDebug')) {
130+
131+
if (atom.inDevMode()) {
97132
args.push('--verbose');
98133
}
99134

100-
atom.config.get('linter-clang.clangIncludePaths').forEach(path =>
135+
this.clangIncludePaths.forEach(path =>
101136
args.push(`-I${path}`),
102137
);
103138

104139
try {
105-
const flags = clangFlags.getClangFlags(activeEditor.getPath());
140+
const flags = clangFlags.getClangFlags(filePath);
106141
if (flags) {
107142
args.push(...flags);
108143
}
109144
} catch (error) {
110-
if (atom.config.get('linter-clang.verboseDebug')) {
145+
if (atom.inDevMode()) {
111146
// eslint-disable-next-line no-console
112147
console.log(error);
113148
}
114149
}
115150

116-
// The file is added to the arguments last.
117-
args.push(file);
151+
args.push(filePath);
152+
153+
let [projectPath] = atom.project.relativizePath(filePath);
154+
if (projectPath === null) {
155+
projectPath = dirname(filePath);
156+
}
157+
118158
const execOpts = {
119159
stream: 'stderr',
120160
allowEmptyStderr: true,
161+
cwd: projectPath,
121162
};
122-
return helpers.exec(command, args, execOpts).then(output =>
123-
helpers.parse(output, regex),
124-
);
163+
164+
const output = await helpers.exec(this.executablePath, args, execOpts);
165+
166+
if (editor.getText() !== fileText) {
167+
// Editor contents have changed, tell Linter not to update results
168+
// eslint-disable-next-line no-console
169+
console.warn('linter-clang: Editor contents changed, not updating results');
170+
return null;
171+
}
172+
173+
const toReturn = [];
174+
let match = regex.exec(output);
175+
176+
while (match !== null) {
177+
let position;
178+
if (match[4] !== undefined) {
179+
const lineStart = Number.parseInt(match[4], 10) - 1;
180+
const colStart = Number.parseInt(match[5], 10) - 1;
181+
const lineEnd = Number.parseInt(match[6], 10) - 1;
182+
const colEnd = Number.parseInt(match[7], 10) - 1;
183+
position = [[lineStart, colStart], [lineEnd, colEnd]];
184+
} else {
185+
const line = Number.parseInt(match[2], 10) - 1;
186+
const col = Number.parseInt(match[3], 10) - 1;
187+
position = helpers.generateRange(editor, line, col);
188+
}
189+
const severity = /error/.test(match[8]) ? 'error' : 'warning';
190+
toReturn.push({
191+
severity,
192+
location: { file: match[1], position },
193+
excerpt: match[9],
194+
});
195+
match = regex.exec(output);
196+
}
197+
198+
return toReturn;
125199
},
126200
};
127201
},

package.json

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,43 @@
99
},
1010
"license": "MIT",
1111
"engines": {
12-
"atom": ">0.50.0"
12+
"atom": ">=1.4.0 <2.0.0"
13+
},
14+
"configSchema": {
15+
"executablePath": {
16+
"type": "string",
17+
"default": "clang"
18+
},
19+
"clangIncludePaths": {
20+
"type": "array",
21+
"default": [
22+
"."
23+
]
24+
},
25+
"clangSuppressWarnings": {
26+
"type": "boolean",
27+
"default": false
28+
},
29+
"clangDefaultCFlags": {
30+
"type": "string",
31+
"default": "-Wall"
32+
},
33+
"clangDefaultCppFlags": {
34+
"type": "string",
35+
"default": "-Wall -std=c++11"
36+
},
37+
"clangDefaultObjCFlags": {
38+
"type": "string",
39+
"default": ""
40+
},
41+
"clangDefaultObjCppFlags": {
42+
"type": "string",
43+
"default": ""
44+
},
45+
"clangErrorLimit": {
46+
"type": "integer",
47+
"default": 0
48+
}
1349
},
1450
"scripts": {
1551
"test": "apm test",
@@ -18,13 +54,13 @@
1854
"providedServices": {
1955
"linter": {
2056
"versions": {
21-
"1.0.0": "provideLinter"
57+
"2.0.0": "provideLinter"
2258
}
2359
}
2460
},
2561
"dependencies": {
2662
"atom-linter": "^9.0.0",
27-
"atom-package-deps": "^4.0.1",
63+
"atom-package-deps": "^4.5.0",
2864
"clang-flags": "^0.2.2"
2965
},
3066
"devDependencies": {
@@ -34,7 +70,7 @@
3470
"jasmine-fix": "^1.0.1"
3571
},
3672
"package-deps": [
37-
"linter"
73+
"linter:2.0.0"
3874
],
3975
"eslintConfig": {
4076
"extends": "airbnb-base",

spec/files/pragma/pragma_once.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
int main() {}

spec/files/pragma/pragma_once.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
int main() {}

spec/files/pragma/pragma_once.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
int main() {}

spec/files/pragma/pragma_once.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
int main() {}

0 commit comments

Comments
 (0)