mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-15 16:53:31 -06:00
commit
d855f47f01
@ -6565,6 +6565,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
function emitSourceFileNode(node: SourceFile) {
|
||||
// Start new file on new line
|
||||
writeLine();
|
||||
emitShebang();
|
||||
emitDetachedComments(node);
|
||||
|
||||
// emit prologue directives prior to __extends
|
||||
@ -6986,6 +6987,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitShebang() {
|
||||
let shebang = getShebang(currentSourceFile.text);
|
||||
if (shebang) {
|
||||
write(shebang);
|
||||
}
|
||||
}
|
||||
|
||||
function isPinnedOrTripleSlashComment(comment: CommentRange) {
|
||||
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
|
||||
|
||||
@ -401,6 +401,9 @@ namespace ts {
|
||||
case CharacterCodes.greaterThan:
|
||||
// Starts of conflict marker trivia
|
||||
return true;
|
||||
case CharacterCodes.hash:
|
||||
// Only if its the beginning can we have #! trivia
|
||||
return pos === 0;
|
||||
default:
|
||||
return ch > CharacterCodes.maxAsciiCharacter;
|
||||
}
|
||||
@ -461,6 +464,13 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
|
||||
case CharacterCodes.hash:
|
||||
if (isShebangTrivia(text, pos)) {
|
||||
pos = scanShebangTrivia(text, pos);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) {
|
||||
pos++;
|
||||
@ -528,6 +538,20 @@ namespace ts {
|
||||
return pos;
|
||||
}
|
||||
|
||||
const shebangTriviaRegex = /^#!.*/;
|
||||
|
||||
function isShebangTrivia(text: string, pos: number) {
|
||||
// Shebangs check must only be done at the start of the file
|
||||
Debug.assert(pos === 0);
|
||||
return shebangTriviaRegex.test(text);
|
||||
}
|
||||
|
||||
function scanShebangTrivia(text: string, pos: number) {
|
||||
let shebang = shebangTriviaRegex.exec(text)[0];
|
||||
pos = pos + shebang.length;
|
||||
return pos;
|
||||
}
|
||||
|
||||
// Extract comments from the given source text starting at the given position. If trailing is
|
||||
// false, whitespace is skipped until the first line break and comments between that location
|
||||
// and the next token are returned.If trailing is true, comments occurring between the given
|
||||
@ -617,6 +641,13 @@ namespace ts {
|
||||
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] {
|
||||
return getCommentRanges(text, pos, /*trailing*/ true);
|
||||
}
|
||||
|
||||
/** Optionally, get the shebang */
|
||||
export function getShebang(text: string): string {
|
||||
return shebangTriviaRegex.test(text)
|
||||
? shebangTriviaRegex.exec(text)[0]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean {
|
||||
return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
|
||||
@ -1087,6 +1118,18 @@ namespace ts {
|
||||
return token = SyntaxKind.EndOfFileToken;
|
||||
}
|
||||
let ch = text.charCodeAt(pos);
|
||||
|
||||
// Special handling for shebang
|
||||
if (ch === CharacterCodes.hash && pos === 0 && isShebangTrivia(text, pos)) {
|
||||
pos = scanShebangTrivia(text ,pos);
|
||||
if (skipTrivia) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
return token = SyntaxKind.ShebangTrivia;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case CharacterCodes.lineFeed:
|
||||
case CharacterCodes.carriageReturn:
|
||||
|
||||
@ -17,6 +17,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// token > SyntaxKind.Identifer => token is a keyword
|
||||
// Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync
|
||||
export const enum SyntaxKind {
|
||||
Unknown,
|
||||
EndOfFileToken,
|
||||
@ -24,6 +25,8 @@ namespace ts {
|
||||
MultiLineCommentTrivia,
|
||||
NewLineTrivia,
|
||||
WhitespaceTrivia,
|
||||
// We detect and preserve #! on the first line
|
||||
ShebangTrivia,
|
||||
// We detect and provide better error recovery when we encounter a git merge marker. This
|
||||
// allows us to edit files with git-conflict markers in them in a much more pleasant manner.
|
||||
ConflictMarkerTrivia,
|
||||
|
||||
@ -75,28 +75,28 @@ function delint(sourceFile) {
|
||||
delintNode(sourceFile);
|
||||
function delintNode(node) {
|
||||
switch (node.kind) {
|
||||
case 196 /* ForStatement */:
|
||||
case 197 /* ForInStatement */:
|
||||
case 195 /* WhileStatement */:
|
||||
case 194 /* DoStatement */:
|
||||
if (node.statement.kind !== 189 /* Block */) {
|
||||
case 197 /* ForStatement */:
|
||||
case 198 /* ForInStatement */:
|
||||
case 196 /* WhileStatement */:
|
||||
case 195 /* DoStatement */:
|
||||
if (node.statement.kind !== 190 /* Block */) {
|
||||
report(node, "A looping statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
break;
|
||||
case 193 /* IfStatement */:
|
||||
case 194 /* IfStatement */:
|
||||
var ifStatement = node;
|
||||
if (ifStatement.thenStatement.kind !== 189 /* Block */) {
|
||||
if (ifStatement.thenStatement.kind !== 190 /* Block */) {
|
||||
report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
if (ifStatement.elseStatement &&
|
||||
ifStatement.elseStatement.kind !== 189 /* Block */ &&
|
||||
ifStatement.elseStatement.kind !== 193 /* IfStatement */) {
|
||||
ifStatement.elseStatement.kind !== 190 /* Block */ &&
|
||||
ifStatement.elseStatement.kind !== 194 /* IfStatement */) {
|
||||
report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
break;
|
||||
case 178 /* BinaryExpression */:
|
||||
case 179 /* BinaryExpression */:
|
||||
var op = node.operatorToken.kind;
|
||||
if (op === 29 /* EqualsEqualsToken */ || op == 30 /* ExclamationEqualsToken */) {
|
||||
if (op === 30 /* EqualsEqualsToken */ || op == 31 /* ExclamationEqualsToken */) {
|
||||
report(node, "Use '===' and '!=='.");
|
||||
}
|
||||
break;
|
||||
|
||||
8
tests/baselines/reference/shebang.js
Normal file
8
tests/baselines/reference/shebang.js
Normal file
@ -0,0 +1,8 @@
|
||||
//// [shebang.ts]
|
||||
#!/usr/bin/env node
|
||||
var foo = 'I wish the generated JS to be executed in node';
|
||||
|
||||
|
||||
//// [shebang.js]
|
||||
#!/usr/bin/env node
|
||||
var foo = 'I wish the generated JS to be executed in node';
|
||||
5
tests/baselines/reference/shebang.symbols
Normal file
5
tests/baselines/reference/shebang.symbols
Normal file
@ -0,0 +1,5 @@
|
||||
=== tests/cases/compiler/shebang.ts ===
|
||||
#!/usr/bin/env node
|
||||
var foo = 'I wish the generated JS to be executed in node';
|
||||
>foo : Symbol(foo, Decl(shebang.ts, 1, 3))
|
||||
|
||||
6
tests/baselines/reference/shebang.types
Normal file
6
tests/baselines/reference/shebang.types
Normal file
@ -0,0 +1,6 @@
|
||||
=== tests/cases/compiler/shebang.ts ===
|
||||
#!/usr/bin/env node
|
||||
var foo = 'I wish the generated JS to be executed in node';
|
||||
>foo : string
|
||||
>'I wish the generated JS to be executed in node' : string
|
||||
|
||||
20
tests/baselines/reference/shebangError.errors.txt
Normal file
20
tests/baselines/reference/shebangError.errors.txt
Normal file
@ -0,0 +1,20 @@
|
||||
tests/cases/compiler/shebangError.ts(2,1): error TS1127: Invalid character.
|
||||
tests/cases/compiler/shebangError.ts(2,2): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
|
||||
tests/cases/compiler/shebangError.ts(2,12): error TS2304: Cannot find name 'env'.
|
||||
tests/cases/compiler/shebangError.ts(2,16): error TS1005: ';' expected.
|
||||
tests/cases/compiler/shebangError.ts(2,16): error TS2304: Cannot find name 'node'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/shebangError.ts (5 errors) ====
|
||||
var foo = 'Shebang is only allowed on the first line';
|
||||
#!/usr/bin/env node
|
||||
|
||||
!!! error TS1127: Invalid character.
|
||||
~~~~~~~~~
|
||||
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'env'.
|
||||
~~~~
|
||||
!!! error TS1005: ';' expected.
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'node'.
|
||||
8
tests/baselines/reference/shebangError.js
Normal file
8
tests/baselines/reference/shebangError.js
Normal file
@ -0,0 +1,8 @@
|
||||
//// [shebangError.ts]
|
||||
var foo = 'Shebang is only allowed on the first line';
|
||||
#!/usr/bin/env node
|
||||
|
||||
//// [shebangError.js]
|
||||
var foo = 'Shebang is only allowed on the first line';
|
||||
!/usr/bin / env;
|
||||
node;
|
||||
2
tests/cases/compiler/shebang.ts
Normal file
2
tests/cases/compiler/shebang.ts
Normal file
@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
var foo = 'I wish the generated JS to be executed in node';
|
||||
2
tests/cases/compiler/shebangError.ts
Normal file
2
tests/cases/compiler/shebangError.ts
Normal file
@ -0,0 +1,2 @@
|
||||
var foo = 'Shebang is only allowed on the first line';
|
||||
#!/usr/bin/env node
|
||||
Loading…
x
Reference in New Issue
Block a user