Typescript: Emit tidak mempertahankan baris kosong

Dibuat pada 7 Okt 2014  ·  36Komentar  ·  Sumber: microsoft/TypeScript

Hai,

TS Versi : 1.1.0

Diberikan

function foo() {

    var x = 10;

    var y = 11;
}

Kami biasa mendapatkan

function foo() {
    var x = 10;

    var y = 11;
}

Dalam kompilator baru, jeda baris tidak ada

function foo() {
    var x = 10;
    var y = 11;
}

(Kedua kompiler menghapus baris kosong pertama, tetapi kompilator baru melangkah lebih jauh.)

Ini dapat memengaruhi pengalaman saat men-debug JavaScript di browser.

Bug help wanted

Komentar yang paling membantu

Kerumunan menginginkan preserveWhitespace: true/false
@ORESoftware ++

Semua 36 komentar

Menambahkan beberapa info latar belakang ... Alasan kompilator baru menghapus semua baris kosong adalah karena ini adalah satu-satunya hal yang dapat kita lakukan _consistently_. Pemeliharaan baris kosong akan selalu menjadi hit atau miss ketika datang ke konstruksi yang tunduk pada penulisan ulang, misalnya deklarasi kelas dan modul. Kami menghadapi masalah yang persis sama dengan penyimpanan komentar. Jadi, meskipun saya bersimpati untuk menyelesaikan masalah ini, itu bukanlah hal yang mudah untuk dilakukan.

@NoelAbrahams Saya ingin tahu masalah apa yang Anda lihat saat debugging?

@ahejlsberg @NoelAbrahams Saya membuat prototipe yang dipancarkan dalam proyek CodePlex asli yang benar-benar melakukan pekerjaan hebat dengan komentar dan pelestarian baris baru. Bahkan pada konstruksi yang banyak ditulis ulang (seperti fungsi panah ke ekspresi fungsi) itu hampir selalu melakukan apa yang Anda harapkan secara intuitif.

Pemeliharaan baris sebagian besar merupakan fungsi yang hanya menggunakan kembali baris baru saat mempertahankan kode lama, dan menggunakan spasi relatif saat melakukan transformasi. yaitu jika Anda memiliki:

module M {
}
module N {
}

Kemudian ketika Anda memancarkan IIFE untuk 'N' Anda berkata "kita harus menyimpan trivia antara modul yang kita tulis ulang dan elemen sintaksis sebelumnya".

Berikut adalah sebelum / sesudah bagaimana prototipe emitor saya bekerja yang menyimpan komentar / baris baru dengan tingkat kesetiaan yang tinggi:

https://typescript.codeplex.com/SourceControl/latest#tests/Fidelity/emitter2/ecmascript5/Parser.ts
https://typescript.codeplex.com/SourceControl/latest#tests/Fidelity/emitter2/ecmascript5/Parser.ts.expected

Anda juga dapat melihat banyak contoh di sini:
https://typescript.codeplex.com/SourceControl/latest#tests/Fidelity/emitter/ecmascript5/

Satu-satunya fitur yang tidak saya terapkan adalah 'penyelarasan'. yaitu jika Anda memiliki kode yang diselaraskan dalam beberapa cara dengan aslinya (sangat umum dengan deklarasi parameter), kami ingin kode yang dipancarkan untuk mempertahankannya juga.

Tapi itu akan sangat sepele untuk dilakukan.

Konon, konversi konstruksi dari TS ke JS memang mencoba untuk mempertahankan lekukan. Anda dapat melihatnya di sini:
https://typescript.codeplex.com/SourceControl/latest#tests/Fidelity/emitter/ecmascript5/ClassDeclaration/ClassDeclaration2.ts
https://typescript.codeplex.com/SourceControl/latest#tests/Fidelity/emitter/ecmascript5/ClassDeclaration/ClassDeclaration2.ts.expected

Perhatikan bagaimana pernyataan diindenden dengan benar (bahkan ketika tersebar di beberapa baris) bahkan setelah kita mengonversi modul dan kelas bersarang menjadi IIFE

@ahejlsberg , tidak ada masalah yang berarti saat melakukan debug di browser. Itu hanya membuatnya lebih mudah untuk menavigasi kode JavaScript dan menemukan baris untuk menetapkan titik putus ketika ada korespondensi yang tepat dengan kode sumber TypeScript yang sebenarnya.

Saya pribadi bisa hidup tanpa baris kosong, tetapi karena TS telah berusaha keras untuk melestarikan dan memancarkan _beautiful _ JavaScript (: smile :) tampaknya wajar saja ini diterapkan.

@ahejlsberg @NoelAbrahams Ada satu masalah yang terjadi dengan debugging di browser yang sedikit terkait dengan percakapan ini. Saat menggunakan rantai penyetel / pengambil (seperti dengan jquery) atau rantai janji, umpan baris baru akan hilang selama terjemahan. Karena itu, ini adalah titik sakit yang sangat besar saat bekerja dengan fungsi Panah.

Sebagai contoh:

(<any> x).a('#test')
    .b('test')
    .c(() => 'foo')
    .d(() => 'bar')
    .e(() => 5)
    .f(() => 6);

Menjadi:

x.a('#test').b('test').c(function () { return 'foo'; }).d(function () { return 'bar'; }).e(function () { return 5; }).f(function () { return 6; });

Menggunakan Chrome dan sourceMaps, breakpoint masih dilewati.

http://www.typescriptlang.org/Playground#src = (% 3Cany% 3E% 20x) .a ('% 23test')% 0A% 20% 20% 20% 20.b ('test')% 0A% 09.c (()% 20% 3D% 3E% 20'foo ')% 0A% 09.d (()% 20% 3D% 3E% 20'bar')% 0A% 09.e (()% 20 % 3D% 3E% 205)% 0A% 09.f (()% 20% 3D% 3E% 206)% 3B

@mtraynham , sebenarnya menurut saya masalah yang Anda soroti adalah masalah yang sedikit berbeda.

Di versi sebelumnya, badan fungsi sebaris selalu dipancarkan di baris baru:

// TS
var x = () => 'foo';

// JS - old
var x = function () { 
             return 'foo'; 
       };

// JS - new
var x = function () { return 'foo'; };

Saya juga menemukan ini menjadi masalah - harus sesekali kembali dan membuat function sehingga saya dapat menetapkan breakpoint saat debugging di browser.

@NoelAbrahams Ahh ya, saya telah menggunakan solusi temp yang sama persis ... Saya tidak yakin apakah ini adalah bug yang tepat untuk menyebabkan masalah ini (penghapusan feed baris), atau haruskah saya membuka yang lain?

Saya membuat # 2259 untuk masalah terpisah.

Sebagai direktur teknik yang mengeksplorasi pemindahan komunitas pengembangan javascript kami ke skrip ketikan, kemampuan baris baru akan sangat membantu. Salah satu daya tarik utama dari naskah ketikan adalah menjaga keterbacaan dan struktur kode yang dibuat dalam naskah ketikan yang dihasilkanJavascript.

Sangat menyenangkan melihat komentar disimpan dalam pembaruan terkini dan penambahan dari perintah baris perintah “--removeComments".

Saya juga ingin ini karena alasan yang sama seperti @timjmartel - ketika pengembang melihat JS yang dipancarkan terlihat _nice_, mereka kurang tahan untuk mengadopsi. Mempertahankan spasi (setidaknya vertikal) membuat kode terlihat kurang seperti yang dihasilkan oleh mesin dan lebih seperti kode JS idomatic yang ditulis oleh manusia.

Jika tim kami memutuskan untuk meninggalkan TS dan sebaliknya melanjutkan dengan JS yang ditranspilasi, akan lebih mudah untuk mengadopsi sumber JS yang dipancarkan jika mereka memiliki spasi kosong yang ramah manusia.

Berkenaan dengan baris kosong, apakah mungkin - untuk saat ini - membiarkannya dipancarkan, bahkan jika terkena atau luput? Fitur eksperimental seperti itu dapat ditanyakan dengan opsi "--keepEmptyLines". Ini tidak akan terlalu berarti jika memiliki JS yang bagus, tetapi karena memiliki JS yang lebih mudah dibaca.

Berkenaan dengan panggilan fungsi yang dirantai, apakah mungkin memiliki satu panggilan untuk baris, untuk membiarkan pengguna mengatur breakpoint? Sekali lagi, fitur ini dapat ditanyai dengan opsi "--oneCallForLine", jika itu adalah "untung-untungan" lainnya.

Terima kasih atas perhatiannya.

Sebenarnya, panggilan fungsi yang dirantai dapat dipisahkan oleh beautifier kode sumber, oleh karena itu tidak masuk akal untuk menyematkan fitur seperti itu di TypeScript.

Ini seharusnya tidak terlalu sulit, seharusnya tidak hanya ada opsi di tsconfig.json

preserveWhitespace: true/false

?

Tetapi saya tidak melihat ini sebagai opsi kompiler: https://www.typescriptlang.org/docs/handbook/compiler-options.html

Aku baru menyadari. Salah satu alasan bagus untuk tidak menyimpan spasi adalah karena ini akan sangat membantu mencegah Anda mengedit .js alih-alih .ts secara tidak sengaja. Saya kira satu hal yang harus dilakukan adalah menulis file .js sebagai readonly / execution only. Jadi mungkin ini bukan masalah.

Karena itu, saya tidak berpikir tsc menulis file .js sebagai readonly / execution only, apakah ada cara untuk mengkonfigurasi tsc untuk melakukan ini?

Tidak, tidak untuk saat ini. Jangan ragu untuk membuka masalah terpisah untuk itu.

@DanielRosenwasser Anda mengatakan jika kita ingin menjaga ruang kosong, kita harus membuka masalah terpisah? Apakah masalah ini tidak cukup? Nevermind LOL lebih dari sebulan kemudian saya menyadari Anda mengatakan untuk membuka masalah terpisah untuk izin baca / tulis / eksekusi pada file transparan :)

Akan menyenangkan memiliki ini.

+1

+1

+1

Kerumunan menginginkan preserveWhitespace: true/false
@ORESoftware ++

Alasan pentingnya hal ini adalah karena TypeScript seharusnya "menurunkan kualitas dengan baik" ke JS. Saat ini ia tidak dapat mempertahankan baris baru yang membuat JS sedikit padat untuk dibaca, terutama jika Anda menulis TypeScript, tetapi Anda seharusnya mengirimkan JS ke tempat lain.

+1 preserveWhitespace: true/false

Retas sementara

Gunakan esformatter untuk menambahkan

Dengan file konfigurasi berikut:

{
  "lineBreak": {
    "before": {
      "FunctionDeclaration": ">=2",
      "FunctionDeclarationOpeningBrace": 0,
      "FunctionDeclarationClosingBrace": 1,
      "MethodDefinition": ">=2",
      "ClassDeclaration": ">=2"
    },
    "after": {
      "FunctionDeclaration": ">=2",
      "FunctionDeclarationOpeningBrace": 1,
      "MethodDefinitionClosingBrace": ">=2",
      "ClassClosingBrace": ">=2"
    }
  }
}

@mtraynham Contoh Anda:

(<any> x).a('#test')
    .b('test')
    .c(() => 'foo')
    .d(() => 'bar')
    .e(() => 5)
    .f(() => 6);

dengan kompiler terbaru menghasilkan JS ini:

x.a('#test')
    .b('test')
    .c(function () { return 'foo'; })
    .d(function () { return 'bar'; })
    .e(function () { return 5; })
    .f(function () { return 6; });

(lihat TS PlayGround https://goo.gl/JViurr)

Banyak yang telah berubah sejak TS Versi 1.1 (versi TypeScript yang menyebabkan masalah ini). Mungkin masalah ini bisa ditutup? @ahejlsberg ?

@ valera-rozuvan Saya telah membuka # 2259 sebagai gantinya. Masalah saya terkait dengan feed baris, tetapi bukan masalah yang persis sama yang dijelaskan oleh bug ini. # 2259 ditutup beberapa waktu lalu (Mei 2015).

Ini adalah konfigurasi esformatter bril-andrew tetapi dengan bug yang diperbaiki, (ketika deklarasi kelas berisi kata import tidak ada baris baru):

{
    "lineBreak": {
        "before": {
            "FunctionDeclaration": ">=2",
            "FunctionDeclarationOpeningBrace": 0,
            "FunctionDeclarationClosingBrace": 1,
            "MethodDefinition": ">=2",
            "ClassDeclaration": ">=2",
            "ExportNamedDeclaration": 2
        },
        "after": {
            "FunctionDeclaration": ">=2",
            "FunctionDeclarationOpeningBrace": 1,
            "MethodDefinitionClosingBrace": ">=2",
            "ClassClosingBrace": ">=2"
        }
    }
}

Saya tidak berpikir menggunakan esformatter menyelesaikan seluruh masalah. Tentu, itu dapat secara otomatis memasukkan baris kosong di sekitar fungsi dll. Tapi bagi saya, baris kosong di dalam fungsi bahkan lebih penting. Kami menggunakan baris kosong seperti paragraf dalam prosa: untuk mengelompokkan pemikiran individu.

Baris kosong di dalam fungsi membantu mengomunikasikan struktur fungsi. Tanpa mereka, saya menemukan bahwa keterbacaan menderita.

@ahejlsberg Saya melihat nomor baris yang salah dalam keluaran pengujian unit saya saat menggunakan ts-jest, dan masalah ini tampaknya disebabkan oleh baris kosong yang dihapus dalam keluaran js. Saya ingin tahu mengapa begitu sulit untuk meninggalkan baris ini di js akhir. Apakah ada lebih banyak informasi di luar sana tentang ini? Bisakah kami membantu membuat ini terjadi? :)

Atau sudah digabungkan dan belum dirilis? -> V4 Versi Besar Berikutnya # 3143

@JimTheMan Jika Anda menggunakan sumber peta maka mungkin source-map-support paket dapat membantu Anda mendapatkan jejak stack yang benar dalam output.

Saya juga mengalami masalah ini. Saya datang dengan solusi dengan membuat patch diff dan mengembalikan perubahan whitespace di patch. jsdiff memungkinkan Anda membuat objek patch terstruktur dan memanipulasinya sesuai keinginan.

import * as diff from 'diff';

const patch =
      diff.parsePatch(diff.createPatch('file', oldText, newText, '', ''));
const hunks = patch[0].hunks;
for (let i = 0; i < hunks.length; ++i) {
  let lineOffset = 0;
  const hunk = hunks[i];
  hunk.lines = hunk.lines.map(line => {
    if (line === '-') {
      lineOffset++;
      return ' ';
    }
    return line;
  });
  hunk.newLines += lineOffset;
  for (let j = i + 1; j < hunks.length; ++j) {
    hunks[j].newStart += lineOffset;
  }
}
return diff.applyPatch(oldText, patch);

Dengan solusi ini, Anda dapat mempertahankan semua jeda baris dari file asli.

@zeroliu Apakah ini menyebabkan penundaan waktu yang nyata dalam langkah kompilasi?

@ahejlsberg Menurut Anda apakah ada gunanya memperbaiki masalah ini?

@ valera-rozuvan tergantung pada ukuran proyek Anda. Untuk kasus penggunaan saya di mana saya mentranspilasi file 10-ish dari 100-1000 LOC, itu tidak menyebabkan penundaan yang nyata.

Ada solusi di sini? Saya mengalami masalah ini juga ...

Saya sedang mencoba memperbaiki ini di kompiler itu sendiri ketika rekan setim saya @emadum mengingatkan saya bahwa tsc dapat menyimpan komentar. Berikut adalah pipeline teguk kecil yang tampaknya melakukan pekerjaan yang cukup baik untuk mempertahankan baris baru:

const gulp = require('gulp');
const ts = require('gulp-typescript');
const through = require('through2');

function preserveNewlines() {
  return through.obj(function(file, encoding, callback) {
    const data = file.contents.toString('utf8');
    const fixedUp = data.replace(/\n\n/g, '\n/** THIS_IS_A_NEWLINE **/');
    file.contents = Buffer.from(fixedUp, 'utf8');
    callback(null, file);
  });
}

function restoreNewlines() {
  return through.obj(function(file, encoding, callback) {
    const data = file.contents.toString('utf8');
    const fixedUp = data.replace(/\/\*\* THIS_IS_A_NEWLINE \*\*\//g, '\n');
    file.contents = Buffer.from(fixedUp, 'utf8');
    callback(null, file);
  });
}

gulp.task('default', function () {
  return gulp.src('src/**/*.ts')
    .pipe(preserveNewlines())
    .pipe(ts({
      removeComments: false
    }))
    .pipe(restoreNewlines())
    .pipe(gulp.dest('lib'));
});

Saya pikir komentar yang lebih pintar akan mencegah beberapa kesalahan positif, tetapi tampaknya berhasil dengan baik untuk kita hari ini. Saya hanya menguji ini pada file yang relatif kecil, tetapi overhead kinerja di sana minimal.

hth

@bayu_joo

Saya akhirnya menggunakan ide Anda sebagai basis, dan akhirnya mengembangkannya hingga menjadi modul npm:
https://www.npmjs.com/package/gulp-preserve-typescript-whitespace

Saya mengkreditkan posting Anda di Readme, semoga Anda tidak keberatan :)

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

bgrieder picture bgrieder  ·  3Komentar

kyasbal-1994 picture kyasbal-1994  ·  3Komentar

wmaurer picture wmaurer  ·  3Komentar

Antony-Jones picture Antony-Jones  ·  3Komentar

manekinekko picture manekinekko  ·  3Komentar