Skip to content

Commit 3d377b7

Browse files
author
Andy Hanson
committed
Add "inline-comment-spacing" lint rule
1 parent eef7d8b commit 3d377b7

File tree

16 files changed

+154
-58
lines changed

16 files changed

+154
-58
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import assert = require("assert");
2+
import * as Lint from "tslint/lib";
3+
import * as ts from "typescript";
4+
5+
export class Rule extends Lint.Rules.AbstractRule {
6+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
7+
return this.applyWithFunction(sourceFile, ctx => walk(ctx));
8+
}
9+
}
10+
11+
function walk(ctx: Lint.WalkContext<void>): void {
12+
const { sourceFile } = ctx;
13+
const { text } = sourceFile;
14+
forEachComment(sourceFile, (node, { pos, end, kind }) => {
15+
if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
16+
return;
17+
}
18+
19+
const startLine = sourceFile.getLineAndCharacterOfPosition(pos).line;
20+
const endLine = sourceFile.getLineAndCharacterOfPosition(end).line;
21+
if (startLine !== endLine) {
22+
return;
23+
}
24+
25+
assert(text[pos] === "/");
26+
assert(text[pos + 1] === "*");
27+
assert(text[end - 2] === "*");
28+
assert(text[end - 1] === "/");
29+
const trailingWhitespace = text[end - 3] === " ";
30+
if (inCallExpressionArgument(node)) {
31+
const leadingWhitespace = text[pos + 2] === " ";
32+
if (leadingWhitespace) {
33+
fail(pos + 2, "/*comment*/ should not start with space");
34+
}
35+
if (trailingWhitespace) {
36+
fail(end - 3, "/*comment*/ should not end with space");
37+
}
38+
}
39+
else {
40+
// TODO: this causes a lot of errors -- we're not consistent about whether statement comments should have spaces.
41+
/*
42+
const startPos = text[pos + 2] === "*" ? pos + 3 : pos + 2;
43+
const leadingWhitespace = text[startPos] === " ";
44+
if (!leadingWhitespace) {
45+
fail(startPos, "/* comment * / should start with space");
46+
}
47+
if (!trailingWhitespace) {
48+
fail(end - 3, "/* comment * / should end in space");
49+
}
50+
*/
51+
}
52+
});
53+
54+
function fail(pos: number, reason: string): void {
55+
ctx.addFailure(pos, pos + 1, reason);
56+
}
57+
}
58+
59+
function inCallExpressionArgument(node: ts.Node): boolean {
60+
const { parent } = node;
61+
if (!parent) {
62+
return false;
63+
}
64+
65+
switch (parent.kind) {
66+
case ts.SyntaxKind.CallExpression:
67+
return (parent as ts.CallExpression).expression !== node;
68+
case ts.SyntaxKind.Block:
69+
case ts.SyntaxKind.ModuleBlock:
70+
case ts.SyntaxKind.CaseBlock:
71+
return false;
72+
default:
73+
return inCallExpressionArgument(parent);
74+
}
75+
}
76+
77+
function forEachComment(sourceFile: ts.SourceFile, cb: (node: ts.Node, comment: ts.CommentRange) => void): void {
78+
const { text } = sourceFile;
79+
sourceFile.forEachChild(function recur(node) {
80+
const leading = ts.getLeadingCommentRanges(text, node.pos);
81+
if (leading) {
82+
for (const range of leading) {
83+
cb(node, range);
84+
}
85+
}
86+
const trailing = ts.getTrailingCommentRanges(text, node.pos);
87+
if (trailing) {
88+
for (const range of trailing) {
89+
cb(node, range);
90+
}
91+
}
92+
node.forEachChild(recur);
93+
});
94+
}
95+
96+
97+
98+

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12446,7 +12446,7 @@ namespace ts {
1244612446
function checkThisExpression(node: Node): Type {
1244712447
// Stop at the first arrow function so that we can
1244812448
// tell whether 'this' needs to be captured.
12449-
let container = getThisContainer(node, /* includeArrowFunctions */ true);
12449+
let container = getThisContainer(node, /*includeArrowFunctions*/ true);
1245012450
let needToCaptureLexicalThis = false;
1245112451

1245212452
if (container.kind === SyntaxKind.Constructor) {
@@ -12455,7 +12455,7 @@ namespace ts {
1245512455

1245612456
// Now skip arrow functions to get the "real" owner of 'this'.
1245712457
if (container.kind === SyntaxKind.ArrowFunction) {
12458-
container = getThisContainer(container, /* includeArrowFunctions */ false);
12458+
container = getThisContainer(container, /*includeArrowFunctions*/ false);
1245912459

1246012460
// When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code
1246112461
needToCaptureLexicalThis = (languageVersion < ScriptTarget.ES2015);

src/compiler/commandLineParser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,8 +1148,8 @@ namespace ts {
11481148
}
11491149
else {
11501150
return convertObjectLiteralExpressionToJson(
1151-
objectLiteralExpression, /* knownOptions*/ undefined,
1152-
/*extraKeyDiagnosticMessage */ undefined, /*parentOption*/ undefined);
1151+
objectLiteralExpression, /*knownOptions*/ undefined,
1152+
/*extraKeyDiagnosticMessage*/ undefined, /*parentOption*/ undefined);
11531153
}
11541154

11551155
case SyntaxKind.ArrayLiteralExpression:

src/compiler/scanner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,7 @@ namespace ts {
14431443
}
14441444
else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) {
14451445
pos += 2;
1446-
let value = scanBinaryOrOctalDigits(/* base */ 2);
1446+
let value = scanBinaryOrOctalDigits(/*base*/ 2);
14471447
if (value < 0) {
14481448
error(Diagnostics.Binary_digit_expected);
14491449
value = 0;
@@ -1454,7 +1454,7 @@ namespace ts {
14541454
}
14551455
else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) {
14561456
pos += 2;
1457-
let value = scanBinaryOrOctalDigits(/* base */ 8);
1457+
let value = scanBinaryOrOctalDigits(/*base*/ 8);
14581458
if (value < 0) {
14591459
error(Diagnostics.Octal_digit_expected);
14601460
value = 0;

src/compiler/tsc.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ namespace ts {
117117

118118
if (commandLine.options.locale) {
119119
if (!isJSONSupported()) {
120-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* host */ undefined);
120+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /*host*/ undefined);
121121
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
122122
}
123123
validateLocaleAndSetLanguage(commandLine.options.locale, sys, commandLine.errors);
@@ -148,26 +148,26 @@ namespace ts {
148148

149149
if (commandLine.options.project) {
150150
if (!isJSONSupported()) {
151-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* host */ undefined);
151+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /*host*/ undefined);
152152
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
153153
}
154154
if (commandLine.fileNames.length !== 0) {
155-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* host */ undefined);
155+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /*host*/ undefined);
156156
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
157157
}
158158

159159
const fileOrDirectory = normalizePath(commandLine.options.project);
160160
if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) {
161161
configFileName = combinePaths(fileOrDirectory, "tsconfig.json");
162162
if (!sys.fileExists(configFileName)) {
163-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* host */ undefined);
163+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /*host*/ undefined);
164164
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
165165
}
166166
}
167167
else {
168168
configFileName = fileOrDirectory;
169169
if (!sys.fileExists(configFileName)) {
170-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* host */ undefined);
170+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /*host*/ undefined);
171171
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
172172
}
173173
}
@@ -185,7 +185,7 @@ namespace ts {
185185

186186
if (isWatchSet(commandLine.options)) {
187187
if (!sys.watchFile) {
188-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined);
188+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /*host*/ undefined);
189189
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
190190
}
191191
if (configFileName) {
@@ -218,21 +218,21 @@ namespace ts {
218218
}
219219
if (!cachedConfigFileText) {
220220
const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName);
221-
reportDiagnostics([error], /* compilerHost */ undefined);
221+
reportDiagnostics([error], /*compilerHost*/ undefined);
222222
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
223223
return;
224224
}
225225

226226
const result = parseJsonText(configFileName, cachedConfigFileText);
227-
reportDiagnostics(result.parseDiagnostics, /* compilerHost */ undefined);
227+
reportDiagnostics(result.parseDiagnostics, /*compilerHost*/ undefined);
228228

229229
const cwd = sys.getCurrentDirectory();
230230
const configParseResult = parseJsonSourceFileConfigFileContent(result, sys, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), commandLine.options, getNormalizedAbsolutePath(configFileName, cwd));
231-
reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined);
231+
reportDiagnostics(configParseResult.errors, /*compilerHost*/ undefined);
232232

233233
if (isWatchSet(configParseResult.options)) {
234234
if (!sys.watchFile) {
235-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined);
235+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /*host*/ undefined);
236236
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
237237
}
238238

@@ -654,11 +654,11 @@ namespace ts {
654654
const currentDirectory = sys.getCurrentDirectory();
655655
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
656656
if (sys.fileExists(file)) {
657-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
657+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /*host*/ undefined);
658658
}
659659
else {
660660
sys.writeFile(file, generateTSConfig(options, fileNames, sys.newLine));
661-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
661+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /*host*/ undefined);
662662
}
663663

664664
return;

src/harness/fourslash.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ namespace FourSlash {
332332
ts.forEach(referencedFiles, referenceFile => {
333333
// Fourslash insert tests/cases/fourslash into inputFile.unitName so we will properly append the same base directory to refFile path
334334
const referenceFilePath = this.basePath + "/" + referenceFile.fileName;
335-
this.addMatchedInputFile(referenceFilePath, /* extensions */ undefined);
335+
this.addMatchedInputFile(referenceFilePath, /*extensions*/ undefined);
336336
});
337337

338338
// Add import files into language-service host
@@ -2222,10 +2222,7 @@ namespace FourSlash {
22222222

22232223
public verifyProjectInfo(expected: string[]) {
22242224
if (this.testType === FourSlashTestType.Server) {
2225-
const actual = (<ts.server.SessionClient>this.languageService).getProjectInfo(
2226-
this.activeFile.fileName,
2227-
/* needFileNameList */ true
2228-
);
2225+
const actual = (<ts.server.SessionClient>this.languageService).getProjectInfo(this.activeFile.fileName, /*needFileNameList*/ true);
22292226
assert.equal(
22302227
expected.join(","),
22312228
actual.fileNames.map(file => {

src/harness/harnessLanguageService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ namespace Harness.LanguageService {
239239
getHost() { return this.host; }
240240
getLanguageService(): ts.LanguageService { return ts.createLanguageService(this.host); }
241241
getClassifier(): ts.Classifier { return ts.createClassifier(); }
242-
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJavaScriptFileExtension(fileName)); }
242+
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /*readImportFiles*/ true, ts.hasJavaScriptFileExtension(fileName)); }
243243
}
244244

245245
/// Shim adapter

src/harness/rwcRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ namespace RWC {
138138
const output = Harness.Compiler.compileFiles(
139139
inputFiles,
140140
otherFiles,
141-
/* harnessOptions */ undefined,
141+
/*harnessOptions*/ undefined,
142142
opts.options,
143143
// Since each RWC json file specifies its current directory in its json file, we need
144144
// to pass this information in explicitly instead of acquiring it from the process.

src/harness/test262Runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ class Test262BaselineRunner extends RunnerBase {
5555
const output = Harness.Compiler.compileFiles(
5656
[Test262BaselineRunner.helperFile].concat(inputFiles),
5757
/*otherFiles*/ [],
58-
/* harnessOptions */ undefined,
58+
/*harnessOptions*/ undefined,
5959
Test262BaselineRunner.options,
60-
/* currentDirectory */ undefined
60+
/*currentDirectory*/ undefined
6161
);
6262
testState.compilerResult = output.result;
6363
});

src/harness/unittests/cachingInServerLSHost.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace ts {
6161
typingsInstaller: undefined
6262
};
6363
const projectService = new server.ProjectService(svcOpts);
64-
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /* openedByClient */ true, /*containingProject*/ undefined);
64+
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /*openedByClient*/ true, /*containingProject*/ undefined);
6565

6666
const project = projectService.createInferredProjectWithRootFileIfNecessary(rootScriptInfo);
6767
project.setCompilerOptions({ module: ts.ModuleKind.AMD, noLib: true } );

0 commit comments

Comments
 (0)