Repository: nteract/nteract (language: python)

Issue:
Monaco autocompletion should return suggestion content after the last dot
**Application or Package Used**
Regression within the nteract monaco-editor package.

**Describe the bug**
Monaco autocompletion should return suggestion content after the last dot. Today, there are cases that a kernel when given "suggestion1.itemA" text and typing "." that it will suggest the full path of "suggestion.itemA.itemB" instead of just "itemB". Another case is where given "suggestion1.itemA.it" text and typing "e" will suggest the full path of "suggestion.itemA.itemB" instead of just "itemB".

This is a regression. We used to handle the scenarios above.

Regression caused by this commit:
https://github.com/nteract/nteract/commit/867dd720f49de6d4de315764f67b7118e54050ba#diff-a55f42bbb6045da0f938cd149964b418f08e33fa143062d8cecaaeba4a996373

**To Reproduce**
Steps to reproduce the behavior:

Pre-requisite:
0. Install Python kernel 3.6 and install azureml-sdk (via pip install azureml-sdk)

1. Open a notebook with nteract and enable using monaco editor instead of code mirror.
2. Create a cell and type: from azureml.core.a

**Expected behavior**
Autocompletion suggests "authentication" as an item instead of "azureml.core.authentication" as an item.

**Desktop (please complete the following information):**

- OS: [e.g. macOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

**Additional context**
Add any other context about the problem here.

Fix issues with handling of kernel completions
## Checklist

<!-- If this is your first PR for nteract, please mark these boxes to confirm (otherwise you can exclude them) -->

<!-- Thank you for submitting a pull request to nteract. After all, open source is powered by contributors like you! -->

<!-- Before you submit your PR, make sure that you have gone through the following checklist to ensure that everything goes smoothly. -->

<!-- If you're PR is not fully polished yet or you'd like to park some work, you can open a draft PR. -->

- [x] I have read the [Contributor Guide](https://github.com/nteract/nteract/blob/master/CONTRIBUTING.md)
- [x] I have updated the changelogs/current_changelog.md file with some information about the change that I am making the appropriate file.
- [x] I have validated or unit-tested the changes that I have made.
- [x] I have run through the TEST_PLAN.md to ensure that my change does not break anything else.

<!-- Questions? Feel free to ping us on https://nteract.slack.com/ -->

## Context
There were two issues with the previous approach of sanitization:
1. Anything that had a "." in the completion was being rewritten to be only the part trailing the "." when this wasn't always what we wanted. E.g. folders generally support "." and file names with extensions do too!

### [OLD] File path with "."
![intellisense3](https://user-images.githubusercontent.com/8560030/102826706-0f8d3580-4396-11eb-99a7-85175597c508.gif)

2. We also want to apply a similar logic to paths, e.g. for a path `some/path` we want to only be suggested `path` instead of `some/path` because otherwise we end up with `some/some/path` after accepting the completion

### [OLD] Full file paths were being offered
![intellisense5](https://user-images.githubusercontent.com/8560030/102826631-ecfb1c80-4395-11eb-98fd-1df0e46f001d.gif)

### [OLD] File path with whitespace
![intellisense4](https://user-images.githubusercontent.com/8560030/102826724-1a47ca80-4396-11eb-9f75-efa70be56141.gif)

## Solution
We should make use of the context available for the completion. In other words, in the example above we should check that we are currently receiving suggestions off of `some/` and use this to our advantage by removing it from the suggestion.

### [FIXED] Paths with "."
![intellisense1](https://user-images.githubusercontent.com/8560030/102825023-d4d5ce00-4392-11eb-9dc1-1126ada8fa51.gif)

### [FIXED] Paths with whitespace
![intellisense2](https://user-images.githubusercontent.com/8560030/102825028-d8695500-4392-11eb-8d20-a16fa5436f0a.gif)

## Known issues
See https://github.com/ipython/ipython/issues/2463 - we just make sure that the completion up to that point works


Discussion / hints:

Verified same scenarios on Python 2.7.15.

Note that the following scenario
```
myarray = []
myarray.
```
Isn't provided by the Python 2.7.15 kernel at all
@captainsafia please let me know if there are any next steps before merging! thanks

Fix patch:
diff --git a/changelogs/current_changelog.md b/changelogs/current_changelog.md
index bf2fc62179..2a9a12d2a5 100644
--- a/changelogs/current_changelog.md
+++ b/changelogs/current_changelog.md
@@ -57,6 +57,8 @@ Provide a bulleted list of new features or improvements and a reference to the P
 
 #### Bug Fixes
 
+- Monaco autocompletion should return suggestion content after the last dot - issue #5545 ([#5546](https://github.com/nteract/nteract/pull/5546))
+
 Provide a bulleted list of bug fixes and a reference to the PR(s) containing the changes.
 
 ### @nteract/connected-components ([publish-version-here])
diff --git a/packages/monaco-editor/src/completions/completionItemProvider.ts b/packages/monaco-editor/src/completions/completionItemProvider.ts
index 7f324f9756..0aadd9b7a8 100644
--- a/packages/monaco-editor/src/completions/completionItemProvider.ts
+++ b/packages/monaco-editor/src/completions/completionItemProvider.ts
@@ -252,6 +252,16 @@ class CompletionItemProvider
       return text.substr(toRemove.length);
     }
 
+    // Handle taking only the suggestion content after the last dot. There are cases that a kernel when given 
+    // "suggestion1.itemA" text and typing "." that it will suggest the full path of "suggestion.itemA.itemB" instead of 
+    // just "itemB". The logic below handles these cases. This also handles the case where given "suggestion1.itemA.it" 
+    // text and typing "e" will suggest the full path of "suggestion.itemA.itemB" instead of "itemB". 
+    // This logic also covers that scenario.
+    const index = text.lastIndexOf(".");
+    if (index > -1 && index < text.length - 1) {
+      return text.substring(index + 1);
+    }
+
     return text;
   }
 


Test patch:
diff --git a/packages/monaco-editor/__tests__/completionItemProvider.test.ts b/packages/monaco-editor/__tests__/completionItemProvider.test.ts
index 8a75cacc96..564f293f50 100644
--- a/packages/monaco-editor/__tests__/completionItemProvider.test.ts
+++ b/packages/monaco-editor/__tests__/completionItemProvider.test.ts
@@ -211,4 +211,34 @@ describe("Appropriate completions should be provided", () => {
     channels.next(mockCompleteReply);
     channels.complete();
   });
+
+  it("Should return suggestions with content after any last dots", (done) => {
+    const mockCompleteReply = createMessage("complete_reply", {
+      content: {
+        status: "some_status",
+        cursor_start: 3,
+        cursor_end: 5,
+        matches: ["completion1.itemA.itemB", "completion2.itemC"]
+      },
+      parent_header: mockCompletionRequest.header
+    });
+
+    const channels = new Subject<JupyterMessage>();
+    completionProvider.setChannels(channels);
+    completionProvider.provideCompletionItems(testModel, testPos).then((result) => {
+      expect(result).toHaveProperty("suggestions");
+      const returnedSuggestions = result.suggestions;
+      expect(returnedSuggestions.length).toEqual(2);
+      expect(returnedSuggestions[0].kind).toEqual(Monaco.languages.CompletionItemKind.Field);
+      expect(returnedSuggestions[0].label).toEqual("itemB");
+      expect(returnedSuggestions[0].insertText).toEqual("itemB");
+      expect(returnedSuggestions[1].kind).toEqual(Monaco.languages.CompletionItemKind.Field);
+      expect(returnedSuggestions[1].label).toEqual("itemC");
+      expect(returnedSuggestions[1].insertText).toEqual("itemC");
+      done();
+    });
+    // Set the reply message on channels and complete the stream
+    channels.next(mockCompleteReply);
+    channels.complete();
+  });
 });