Skip to content

Commit

Permalink
refactor: console.log(式); //=> 評価結果 に表記を統一 (#212)
Browse files Browse the repository at this point in the history
* refactor: `console.log(式); //=> 評価結果` に表記を統一

fix #195

* refactor(operator): console.logを使うように

* Revert "refactor(operator): console.logを使うように"

This reverts commit e222f1d.

* fix(test): Identifierを含んでいるかを判定に追加

* refactor(data-type): リテラルからはconsole.logを削除

* docs(CONTRIBUTING): どちらを優先するかを記述

* test(comment): 1行以下のもおんはチェックしないように
  • Loading branch information
azu authored Mar 28, 2017
1 parent 4e13431 commit 1e90b91
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,12 @@ or
console.log(評価したい式); // => 期待する評価結果
```

基本的には、`console.log(式); // => 期待する評価結果`を利用し、
`console.log`が冗長な場合は `式; // => 期待する評価結果`と書いても良い。

**関連**

- [console.logと// => の使い分け · Issue #195 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/issues/195 "console.logと// => の使い分け · Issue #195 · asciidwango/js-primer")
- [power-assertを使ったDoctestツール power-doctestを書き直した | Web Scratch](http://efcl.info/2015/08/10/power-doctest1.0/)
- [JavaScriptでdoctestを行う power-doctest を作った | Web Scratch](http://efcl.info/2013/1201/res3494/)
- [25.2. doctest — 対話的な実行例をテストする — Python 2.7.x ドキュメント](http://docs.python.jp/2/library/doctest.html "25.2. doctest — 対話的な実行例をテストする — Python 2.7.x ドキュメント")
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"babel-preset-power-assert": "^1.0.0",
"babel-register": "^6.7.2",
"eslint": "^3.0.0",
"esprima": "^3.1.3",
"esquery": "^1.0.0",
"front-matter": "^2.1.0",
"gitbook-cli": "^2.1.2",
"gitbook-plugin-canonical-link": "^2.0.2",
Expand Down
6 changes: 3 additions & 3 deletions source/basic/data-type/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ JavaScriptの浮動小数点数は[IEEE 754][]を採用しています。
- `3.14159` のような `.`(ドット)を含んだ数値
- `2e8` のような `e` または `E` を含んだ数値

`0`から始まる浮動小数点数は、`0`を省略し書くことができます
`0`から始まる浮動小数点数は、`0`を省略して書くことができます

```js
.123; // => 0.123
Expand Down Expand Up @@ -245,7 +245,7 @@ foo;// "ReferenceError: foo is not defined"
{{book.console}}
```js
var foo = null;
foo; // => null
console.log(foo); // => null
```

### オブジェクトリテラル {#object}
Expand Down Expand Up @@ -344,7 +344,7 @@ console.log(array[array.length - 1]); // => "2番目"
```js
var numberRegExp = /\d+/; // 1文字以上の数字にマッチする正規表現
// 123が正規表現にマッチするかをテストする
numberRegExp.test(123); // => true
console.log(numberRegExp.test(123)); // => true
```

`RegExp`今ストラクを使うことで文字列から正規表現オブジェクトを作成することもできますが、
Expand Down
4 changes: 2 additions & 2 deletions source/basic/function-method/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function multiple(num) {
return num * 2;
}

multiple(10); // => 20
console.log(multiple(10)); // => 20
```

値を返していない又は空の`return;`と書いた場合、関数は`undefined`を返します。
Expand All @@ -68,7 +68,7 @@ multiple(10); // => 20
function noop() {
}

noop(); // => undefined;
console.log(noop()); // => undefined;
```

### 可変長引数
Expand Down
4 changes: 2 additions & 2 deletions source/basic/implicit-coercion/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ JavaScriptには、文字列に対するマイナス演算子(`-`)の定義
{{book.console}}
```js
var x = 1, y = "2", z = 3;
x + y + z; // => "123"
y + x + z; // => "213"
console.log(x + y + z); // => "123"
console.log(y + x + z); // => "213"
```

このように、処理の過程でオペランドの型によって、
Expand Down
6 changes: 3 additions & 3 deletions source/basic/operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ Math.pow(2, 4); // => 16
{{book.console}}
```js
// 自分自身とも一致しない
NaN === NaN; // => false
console.log(NaN === NaN); // => false
// Number型である
typeof NaN; // => "number"
console.log(typeof NaN); // => "number"
// Number.isNaNでNaNかどうかを判定
Number.isNaN(NaN); // => true
console.log(Number.isNaN(NaN)); // => true
```

しかし、単項演算子の`+`は文字列から数値への変換に使うべきではありません。
Expand Down
11 changes: 6 additions & 5 deletions source/basic/string/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ ES2015で追加された`String#codePointAt`メソッドを使うことで、そ

```js
// 文字列"あ"の0番目のCode Pointを取得
"".codePointAt(0); // => 12354
console.log("".codePointAt(0)); // => 12354
```

逆に、`String.fromCodePoint`メソッドを使うことで、指定したCode Pointの文字を取得できます。

```js
// 符号位置12354の文字を取得する
String.fromCodePoint(12354); // => "あ"
console.log(String.fromCodePoint(12354)); // => "あ"
```

また、文字列リテラル中にはUnicodeエスケープシーケンスで、直接Code Pointを書くこともできます。
Expand All @@ -128,7 +128,7 @@ Code Pointは`\u{Code Pointの16進数の値}`で書くことができます。
```js
// "あ"のCode Pointは12354
// 12354の16進数表現は3042
"\u{3042}"; // => "あ"
console.log("\u{3042}"); // => "あ"
```

Code Pointの16進数表現は次のようにして求めることができます。
Expand All @@ -139,7 +139,7 @@ var codePointOfあ = "あ".codePointAt(0);
// 12354の16進数表現は"3042"
var hexOfCodePoint = codePointOfあ.toString(16);
// \はエスケープシーケンスであるため、\自体を表現するにはエスケープが必要
"\\u{" + hexOfCodePoint + "}"; // => "\\u{3042}"
console.log("\\u{" + hexOfCodePoint + "}"); // => "\\u{3042}"
```

直接キーボードから入力が難しい特殊な文字や絵文字などは、Unicodeエスケープシーケンスを使うことでソースコード上に安全に書くことができます。
Expand Down Expand Up @@ -423,7 +423,8 @@ JavaScriptでは、ECMAScriptの関連仕様として国際化API(ECMAScript I
// numericをtrueとすると数字が数値として比較されるようになる
var collator = new Intl.Collator("ja", { numeric: true });
// collator.compareはsortに渡せる関数となっている
["1", "10", "2"].sort(collator.compare); // => ["1", "2", "10"]
var sortedValues = ["1", "10", "2"].sort(collator.compare);
console.log(sortedValues); // => ["1", "2", "10"]
```

文字列の比較においては、単純な比較であれば、`===`(厳密比較演算子)や`>`(大なり演算子)を利用します。
Expand Down
87 changes: 87 additions & 0 deletions test/lib/console-comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// MIT © 2017 azu
"use strict";
const esprima = require("esprima");
const esquery = require("esquery");
const path = require("path");
const ignoreFileList = [
// 演算子はいいかな
"source/basic/operator",
// これもリテラルの話なので…
"source/basic/implicit-coercion"
];
/**
* 変数を含んでいるか
* @param {Object} AST
* @returns {boolean}
*/
const isIncludeVariableInExpression = (AST) => {
// 例外
// call({ x : 1})
const Identifiers = esquery(AST, "*:not(Property) Identifier");
if (Identifiers.length > 0) {
return true;
}
return false;
};
/**
* コードで `評価式; // => 評価値` を利用している箇所で
* `console.log`を付けるかどうかを判定する
* https://github.com/asciidwango/js-primer/issues/195
*
* - 基本的にはconsole.logを利用する
* - リテラルや変数が登場しないコードでは`console.log`を省いても良い
*
* lineが問題ある行ならばErrorオブジェクトを返す
* @param {string} text
* @param {string} filePath ファイルパスは無視したい対象の指定に使う
* @returns {Error|undefined}
*/
module.exports = function shouldConsoleWithComment(text, filePath) {
const lines = text.split("\n");
// 1行以下なら無視する
if (lines.length <= 1) {
return;
}
lines.forEach(line => {
const error = checkLineThatShouldHaveComment(line, filePath);
if (error instanceof Error) {
throw error;
}
});
};
/**
* @param {string} line
* @param {string} filePath
* @returns {Error|undefined}
*/
function checkLineThatShouldHaveComment(line, filePath) {
if (!/\/\/\s*=>\s*/.test(text)) {
return;
}
if (text.includes("console.")) {
return;
}
// エラーの場合は無視
if (/=>.*Error/.test(text)) {
return;
}
// template literalっぽいのは無視
if (text.includes("`")) {
return;
}

const AST = esprima.parse(text);
// 変数を含まないリテラルのみであるならパスする
if (!isIncludeVariableInExpression(AST)) {
return;
}
// 無視リストに含まれているなら無視
const isIgnored = ignoreFileList.some(ignoreFilePath => {
return filePath.includes(path.normalize(ignoreFilePath));
});
if (isIgnored) {
return;
}
return new Error(`console.log(式); // => 評価結果 にそろえてください
該当コード: ${text}`);
}
9 changes: 8 additions & 1 deletion test/markdown-doc-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const sourceDir = path.join(__dirname, "..", "source");
const toDoc = require("power-doctest");
const remark = require("remark")();
const select = require('unist-util-select');
const shouldConsoleWithComment = require('./lib/console-comment');

/**
* 指定した文字列を含んだコードは実行環境によってはサポートされてないので無視する
Expand All @@ -35,7 +36,11 @@ const disableComment = "disable-doc-test";
* CodeBlockは必ず実行できるとは限らないので、
* AssertionError(doctestにおける失敗)以外は成功したことにして無視する
* Node.js v6はES2016-が実行できないのでスルーする
* 詳細は CONTRIBUTING.md を読む
*
* `console.log(式); // => 結果` の書式で書かれているをチェックする
* https://github.com/asciidwango/js-primer/issues/195
*
* その他詳細は CONTRIBUTING.md を読む
**/
describe("doctest:md", function() {
const files = globby.sync([`${sourceDir}/**/*.md`, `!${sourceDir}/**/node_modules{,/**}`]);
Expand All @@ -56,6 +61,8 @@ describe("doctest:md", function() {
return codeValue.includes(version);
});
try {
// console.logと// => の書式をチェック
shouldConsoleWithComment(codeBlock.value, filePath);
const poweredCode = toDoc.convertCode(codeBlock.value, filePath);
strictEval(poweredCode);
} catch (error) {
Expand Down

0 comments on commit 1e90b91

Please sign in to comment.