Repository: dotenv-linter/dotenv-linter (rust)

Issue:
Support multi-line values
[bkeepers/dotenv](https://github.com/bkeepers/dotenv), [motdotla/dotenv](https://github.com/motdotla/dotenv), [python-dotenv](https://github.com/theskumar/python-dotenv) and [stackbuilders/dotenv-hs](https://github.com/stackbuilders/dotenv-hs) support multi-line values. For example:

```bash
MULTILINE="new\nline"
```

Pull request description:
Add support for multiline values
Closes #339 

Added tests for the `QuoteCharacterChecker` check 

#### ✔ Checklist:

- [x] This PR has been added to [CHANGELOG.md](https://github.com/dotenv-linter/dotenv-linter/blob/master/CHANGELOG.md) (at the top of the list);
- [x] Tests for the changes have been added (for bug fixes / features);
- [x] Docs have been added / updated (for bug fixes / features).


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4084143..0c7a1af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ ### 🚀 Added
 - Display linted files when run [#311](https://github.com/dotenv-linter/dotenv-linter/pull/311) ([@Anthuang](https://github.com/anthuang))
 
 ### 🔧 Changed
+- Changed behavior of QuoteCharacterChecker for multiline values support [#341](https://github.com/dotenv-linter/dotenv-linter/pull/341) ([@artem-russkikh](http://github.com/artem-russkikh))
 - Make an output on-the-fly [#336](https://github.com/dotenv-linter/dotenv-linter/pull/336) ([@DDtKey](https://github.com/DDtKey))
 
 ## [v2.2.1] - 2020-10-24
diff --git a/src/checks/quote_character.rs b/src/checks/quote_character.rs
index 13f85b7..426e788 100644
--- a/src/checks/quote_character.rs
+++ b/src/checks/quote_character.rs
@@ -24,6 +24,10 @@ fn default() -> Self {
 impl Check for QuoteCharacterChecker<'_> {
     fn run(&mut self, line: &LineEntry) -> Option<Warning> {
         let val = line.get_value()?;
+        if val.contains("\\n") {
+            return None;
+        }
+
         if val.contains('\"') || val.contains('\'') {
             Some(Warning::new(line.clone(), self.name(), self.message()))
         } else {


Test patch:
diff --git a/tests/checks/mod.rs b/tests/checks/mod.rs
index f1d3af9..e01e14a 100644
--- a/tests/checks/mod.rs
+++ b/tests/checks/mod.rs
@@ -1,2 +1,3 @@
 mod ending_blank_line;
 mod extra_blank_line;
+mod quote_character;
diff --git a/tests/checks/quote_character.rs b/tests/checks/quote_character.rs
new file mode 100644
index 0000000..ec6c1a4
--- /dev/null
+++ b/tests/checks/quote_character.rs
@@ -0,0 +1,58 @@
+use crate::common::*;
+
+#[test]
+fn correct_files() {
+    let contents = vec![
+        "A=B\nF=BAR\nFOO=BAR\n",
+        "A=B\r\nF=BAR\r\nFOO=BAR\r\n",
+        "# comment\nABC=DEF\n",
+    ];
+
+    for content in contents {
+        let testdir = TestDir::new();
+        let testfile = testdir.create_testfile(".env", content);
+        let args = &[testfile.as_str()];
+
+        let expected_output = check_output(&[(".env", &[])]);
+
+        testdir.test_command_success_with_args(args, expected_output);
+    }
+}
+
+#[test]
+fn incorrect_files() {
+    let contents = vec![
+        "A=\"B\"\nF=BAR\nFOO=BAR\n",
+        "A=B\r\nF=BAR\r\nFOO=\"BAR\"\r\n",
+        "# comment\nABC=\"DEF\"\n",
+    ];
+    let expected_line_numbers = vec![1, 3, 2];
+
+    for (i, content) in contents.iter().enumerate() {
+        let testdir = TestDir::new();
+        let testfile = testdir.create_testfile(".env", content);
+        let args = &[testfile.as_str()];
+        let expected_output = check_output(&[(
+            ".env",
+            &[format!(
+                ".env:{} QuoteCharacter: The value has quote characters (', \")",
+                expected_line_numbers[i]
+            )
+            .as_str()],
+        )]);
+
+        testdir.test_command_fail_with_args(args, expected_output);
+    }
+}
+
+#[test]
+fn multiline_value() {
+    let content = "FOO=\"new\\nline\"\n";
+
+    let testdir = TestDir::new();
+    let testfile = testdir.create_testfile(".env", content);
+    let args = &[testfile.as_str()];
+    let expected_output = check_output(&[(".env", &[])]);
+
+    testdir.test_command_success_with_args(args, expected_output);
+}