Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 766, Uploading a document by closing it no longer tries to update the closed editor #818

Merged
merged 7 commits into from
Sep 27, 2018

Conversation

tec-goblin
Copy link
Contributor

Explanation: doc.isClosed (as its doc says) returns true if there are no visible editors for that document. You can get multiple editors open for a document for example by using Shift Left on the contextual menu of the first editor's tab.
I checked there are no regressions. I tested also by having other editors open, and also having twice the same editor open.
While I managed to reproduce the issue easily with the current version of the plugin in the marketplace, when trying the same in the emulator with the master, it doesn't even try to save the file. UploadToCloud is not called. That's weird and definitely not caused by this change.

Desired behaviour: when closing a cosmos document with pending changes, 1 get prompted to save it, then (depending on settings) 2 get prompted to upload it. Then 3 if there are still open editors for that document (it is possible to have 2 editors open for the same document), they are updated. If not, we don't update them.
Behaviour of the current version of the plugin in the marketplace: 1,2 as above, then 3 if there no other editors open, an error is shown. If there are any other editors shown, the active one has its contents replaced with the document you just uploaded to the cloud.
Behaviour of the master (at least in the extensions host): 1 never happens, so steps 2 and 3 don't happen either. This pull request only impacts step 3.

@@ -95,7 +95,11 @@ export class CosmosEditorManager {
const timestamp = (new Date()).toLocaleTimeString();
ext.outputChannel.appendLine(`${timestamp}: Updated entity "${editor.label}"`);
ext.outputChannel.show();
await this.updateEditor(updatedContent, vscode.window.activeTextEditor, editor);
if (doc.isClosed !== true) {
const firstRelatedEditor = vscode.window.visibleTextEditors.filter((ed) => ed.document === doc)[0];
Copy link
Contributor

@PrashanthCorp PrashanthCorp Sep 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for helping out with this issue! We appreciate you taking the time to figure out the root cause and the interesting side effect - the extension picking up another activeEditor when this doc is closed - that was nice catch!

I just have a couple of clarifications:

  1. The [0] suggests you're looking at the first matching document only. With that in mind, the comment two lines below could be a little confusing.
    The interesting case could be where you split the editor (Ctrl + '\' in windows; icon below). Here there would be two views of the same document. From my testing, the views are in sync, so editing one view updates the other. I'm wondering if this implementation would work fine in that case? If you haven't tried it, the steps below could help:
    open a document in a cosmos-document.json -> split the editor twice -> You should get 3 columns -> then repro the original bug.

  2. Just curious, is there a case (for example a race condition) where doc.isClosed is false, but doc is not present in visibleTextEditors? The if condition and the filter seem to be checking for the same thing. :)

Icon appears in top right corner, highlighted in red here -
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the encouragement! Those two points surprised me too when implementing (I started with just a simple if doc.isClosed and then from its documentation I realised the issue of multiple editors for the same document).

  1. I am looking for the first matching editor. When updating an editor through the API, VS Code updates the underlying document, thus all visible editors. I tested that with multiple open editors. It's also implied by the documentation of vscode.TextEditorEdit
  2. I don't think it could happen, taking into account the single-threaded model of javascript. That said, the condition is what allows me to safely do [0] in the next line. An alternative (but slightly slower) code would be:
const relatedEditors = vscode.window.visibleTextEditors.filter((ed) => ed.document === doc);
if (relatedEditors.length > 0) {
//update relatedEditors[0]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PrashanthCorp I suppose I'm not supposed to resolve the conversation myself :).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is there a case (for example a race condition) where doc.isClosed is false, but doc is not present in visibleTextEditors? The if condition and the filter seem to be checking for the same thing. :)

It's not a race condition, but this is possible. For example, follow these steps:

  1. Edit the file, but don't save
  2. Open another file (so that it covers the other tab)
  3. Select "File -> Save All"

In this case, isClosed is false because the editor is still open, but it's not in the list of visibleTextEditors because it's behind the other tab.

Please just do if (firstRelatedEditor) { before you call updateEditor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I misunderstood that visibleTextEditors would be all open text editors (it's not clear from the doc)
But in that case, if (firstRelatedEditor) won't do what we want: we want to update the hidden (open) editor with what we got from the server. I don't see a way to get "all open editors" . Anyway, just doing a if (firstRelatedEditor) is already an improvement. I will update the pull request immediately

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I agree this is an improvement and is worth getting in - even though it's not perfect

@@ -95,7 +95,11 @@ export class CosmosEditorManager {
const timestamp = (new Date()).toLocaleTimeString();
ext.outputChannel.appendLine(`${timestamp}: Updated entity "${editor.label}"`);
ext.outputChannel.show();
await this.updateEditor(updatedContent, vscode.window.activeTextEditor, editor);
if (doc.isClosed !== true) {
const firstRelatedEditor = vscode.window.visibleTextEditors.filter((ed) => ed.document === doc)[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Instead of .filter()[0], you can use .find() which automatically returns the first object found.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I didn't know that. I will send a fix.

@@ -95,7 +95,11 @@ export class CosmosEditorManager {
const timestamp = (new Date()).toLocaleTimeString();
ext.outputChannel.appendLine(`${timestamp}: Updated entity "${editor.label}"`);
ext.outputChannel.show();
await this.updateEditor(updatedContent, vscode.window.activeTextEditor, editor);
if (doc.isClosed !== true) {
const firstRelatedEditor = vscode.window.visibleTextEditors.filter((ed) => ed.document === doc)[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is there a case (for example a race condition) where doc.isClosed is false, but doc is not present in visibleTextEditors? The if condition and the filter seem to be checking for the same thing. :)

It's not a race condition, but this is possible. For example, follow these steps:

  1. Edit the file, but don't save
  2. Open another file (so that it covers the other tab)
  3. Select "File -> Save All"

In this case, isClosed is false because the editor is still open, but it's not in the list of visibleTextEditors because it's behind the other tab.

Please just do if (firstRelatedEditor) { before you call updateEditor

@@ -68,7 +68,7 @@ export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase<Collec
// Create a DB collection
public async createChild(_node: IAzureNode, showCreatingNode: (label: string) => void): Promise<IAzureTreeItem> {
const collectionName = await vscode.window.showInputBox({
placeHolder: `Enter a name for your ${this.childTypeLabel}`,
placeHolder: `Enter an Id for your ${this.childTypeLabel}`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also - please keep this change separate

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oups, newbie in GitHub mistake - for the next changes I did one branch for each pull request. Sorry

@ejizba ejizba merged commit a6e8aa4 into microsoft:master Sep 27, 2018
@github-actions github-actions bot locked and limited conversation to collaborators Apr 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants