Repository: eslint/eslint (js)

Issue:
Running eslint in STDIN mode on an empty file prints weirdly formated help text
* **ESLint Version:** 3.7.1
* **Node Version:** 8.7.0
* **npm Version:** 5.4.2

**What parser (default, Babel-ESLint, etc.) are you using?** default

**Please show your full configuration:** None

Running eslint in STDIN mode on an empty file prints weirdly formated help text:

```
$ touch a.js
$ eslint --format=checkstyle --stdin --stdin-filename a.js < a.js
eslint [options] file.js [file.js] [dir]

Basic configuration:
  -c, --config path::String

      Use
      configuration
      from
      this
      file
      or
      shareable
      config
  --no-eslintrc

      Disable
      use
      of
      configuration
      from
      .eslintrc
  --env [String]

      Specify
      environments
  --ext [String]

      Specify
      JavaScript
      file
      extensions
      -
      default:
      .js
[… lots more output …]
$ echo $?
0
```

Is this expected?

Pull request:
Fix: allow linting the empty string from stdin (fixes #9515)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[x] Bug fix (fixes https://github.com/eslint/eslint/issues/9515)

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**

This fixes an issue where `cli` would treat an empty-string argument as missing.

**Is there anything you'd like reviewers to focus on?**

Nothing in particular

Patch:
diff --git a/Makefile.js b/Makefile.js
index f5fd5ab37..81d4d34d0 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -978,7 +978,7 @@ target.checkGitCommit = function() {
     }
 
     // Only check non-release messages
-    if (!semver.valid(commitMsgs[0]) && !/^Revert /.test(commitMsgs[0])) {
+    if (!semver.valid(commitMsgs[0]) && !commitMsgs[0].startsWith("Revert")) {
         if (commitMsgs[0].split(/\r?\n/)[0].length > 72) {
             echo(" - First line of commit message must not exceed 72 characters");
             failed = true;
diff --git a/lib/cli-engine.js b/lib/cli-engine.js
index 38c49cb31..5fc35ae0a 100644
--- a/lib/cli-engine.js
+++ b/lib/cli-engine.js
@@ -240,8 +240,8 @@ function processFile(filename, configHelper, options, linter) {
 function createIgnoreResult(filePath, baseDir) {
     let message;
     const isHidden = /^\./.test(path.basename(filePath));
-    const isInNodeModules = baseDir && /^node_modules/.test(path.relative(baseDir, filePath));
-    const isInBowerComponents = baseDir && /^bower_components/.test(path.relative(baseDir, filePath));
+    const isInNodeModules = baseDir && path.relative(baseDir, filePath).startsWith("node_modules");
+    const isInBowerComponents = baseDir && path.relative(baseDir, filePath).startsWith("bower_components");
 
     if (isHidden) {
         message = "File ignored by default.  Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
diff --git a/lib/cli.js b/lib/cli.js
index f04448097..6a5482bf9 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -144,6 +144,8 @@ const cli = {
 
         const files = currentOptions._;
 
+        const useStdin = typeof text === "string";
+
         if (currentOptions.version) { // version from package.json
 
             log.info(`v${require("../package.json").version}`);
@@ -153,7 +155,7 @@ const cli = {
                 log.error("The --print-config option must be used with exactly one file name.");
                 return 1;
             }
-            if (text) {
+            if (useStdin) {
                 log.error("The --print-config option is not available for piped-in code.");
                 return 1;
             }
@@ -164,27 +166,27 @@ const cli = {
 
             log.info(JSON.stringify(fileConfig, null, "  "));
             return 0;
-        } else if (currentOptions.help || (!files.length && !text)) {
+        } else if (currentOptions.help || (!files.length && !useStdin)) {
 
             log.info(options.generateHelp());
 
         } else {
 
-            debug(`Running on ${text ? "text" : "files"}`);
+            debug(`Running on ${useStdin ? "text" : "files"}`);
 
             if (currentOptions.fix && currentOptions.fixDryRun) {
                 log.error("The --fix option and the --fix-dry-run option cannot be used together.");
                 return 1;
             }
 
-            if (text && currentOptions.fix) {
+            if (useStdin && currentOptions.fix) {
                 log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead.");
                 return 1;
             }
 
             const engine = new CLIEngine(translateOptions(currentOptions));
 
-            const report = text ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);
+            const report = useStdin ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);
 
             if (currentOptions.fix) {
                 debug("Fix mode enabled - applying fixes");


Test patch:
diff --git a/tests/lib/cli.js b/tests/lib/cli.js
index b77cfcde7..8a8bc938a 100644
--- a/tests/lib/cli.js
+++ b/tests/lib/cli.js
@@ -101,6 +101,13 @@ describe("cli", () => {
             assert.strictEqual(result, 1);
         });
 
+        it("should not print debug info when passed the empty string as text", () => {
+            const result = cli.execute(["--stdin", "--no-eslintrc"], "");
+
+            assert.strictEqual(result, 0);
+            assert.isTrue(log.info.notCalled);
+        });
+
         it("should return no error when --ext .js2 is specified", () => {
             const filePath = getFixturePath("files");
             const result = cli.execute(`--ext .js2 ${filePath}`);