Repository: FHIR/sushi (ts)

Issue:
Comment on the last line of a FSH file causes an error
If the last line of a FSH file is a comment or if the last line ends with an inline comment, the following error is reported: 

`error: extraneous input '//' expecting {<EOF>, KW_ALIAS, KW_PROFILE, KW_EXTENSION, KW_INSTANCE, KW_INVARIANT, KW_VALUESET, KW_CODESYSTEM}`

This may be related to the fix for #130 because I did not see this issue prior the the PR that addressed that bug.

Example FSH files that will report that error:

```
Instance: Example
InstanceOf: Patient
// Comment
```

```
Instance: Example
InstanceOf: Patient // Comment
```

Pull request description:
Add trailing newline to files without one
Fixes #145 

There was an issue with comments (line and block) causing a syntax error if they are at the end of a file, and there is no newline in the file. This PR addresses the issue by solving it the way some other languages do; adding a trailing newline to the end of the file content being processed if there isn't one already.

I'd like someone on Windows to test this out, since I know newlines can be kind of messy across operating systems.

I'm going to add a couple of tests to verify these work as well; stand by for that.

Patch:
diff --git a/src/import/FSHImporter.ts b/src/import/FSHImporter.ts
index 5358341..6cfcd9f 100644
--- a/src/import/FSHImporter.ts
+++ b/src/import/FSHImporter.ts
@@ -111,7 +111,13 @@ export class FSHImporter extends FSHVisitor {
       docs.push(doc);
 
       // Create and store context for main import process
-      const ctx = this.parseDoc(rawFSH.content, rawFSH.path);
+      // We are appending a newline to the file content if there is not one there already.
+      // This is being done because we discovered a syntax error that occurs if a comments
+      // ends a file, and there is no newline after it. Comments are only tokenized in our
+      // grammar if a newline follows it. In order to prevent this error from occurring,
+      // we add a newline to the content before we parse it so comments at EOF can be tokenized.
+      const content = rawFSH.content.endsWith('\n') ? rawFSH.content : rawFSH.content + '\n';
+      const ctx = this.parseDoc(content, rawFSH.path);
       contexts.push(ctx);
 
       // Collect the aliases and store in global map


Test patch:
diff --git a/test/import/FSHImporter.test.ts b/test/import/FSHImporter.test.ts
index 05d67dc..c3bf640 100644
--- a/test/import/FSHImporter.test.ts
+++ b/test/import/FSHImporter.test.ts
@@ -5,6 +5,8 @@ import { assertFixedValueRule } from '../testhelpers/asserts';
 import { importSingleText } from '../testhelpers/importSingleText';
 
 describe('FSHImporter', () => {
+  beforeEach(() => loggerSpy.reset());
+
   it('should default filename to blank string', () => {
     const input = '';
     const result = importSingleText(input);
@@ -114,4 +116,27 @@ describe('FSHImporter', () => {
     expect(results[1].profiles.size).toBe(0);
     expect(results[1].extensions.size).toBe(0);
   });
+
+  it('should allow a FSH document with a line comment at EOF without newline', () => {
+    const input = `
+    Profile: ObservationProfile
+    Parent: Observation
+    //Comment`;
+    const result = importSingleText(input);
+    expect(result.profiles.size).toBe(1);
+    expect(loggerSpy.getAllLogs().length).toBe(0);
+  });
+
+  it('should allow a FSH document with a block comment at EOF without newline', () => {
+    const input = `
+    Profile: ObservationProfile
+    Parent: Observation
+    /*
+    Comment
+    Comment
+    */`;
+    const result = importSingleText(input);
+    expect(result.profiles.size).toBe(1);
+    expect(loggerSpy.getAllLogs().length).toBe(0);
+  });
 });