celador / ForceCode

ForceCode is a Visual Studio Code extension for Salesforce development
MIT License
160 stars 69 forks source link

"Refresh from server" at src level fails #238

Closed stephenroden closed 5 years ago

stephenroden commented 5 years ago

Describe the bug In a Salesforce project when I right click on the src folder and select "ForceCode: Refresh From Server" it starts the running task "Refreshing src". However it never completes.

To Reproduce Steps to reproduce the behavior:

  1. Open a Salesforce project in VSC
  2. Right click on the src folder to bring up menu.
  3. Click "ForceCode: Refresh from server"

Expected behavior There are two possible expectations. The obvious one is that the src folder is successfully refreshed. The less obvious, if refreshing from this level is difficult/impossible, is that the menu option is not offered.

Desktop (please complete the following information):

Additional context From what I can see in open.ts there is a line in parsers/open.ts: const ffNameParts: string[] = uri.fsPath.split(projRoot)[1].split(path.sep); If the uri and projRoot is the same then the [1] part produces an undefined. The second split then crashes out. I tried changing the code so that it didn't get upset but then realized that what the code is doing is attempting to work out the object type it is attempting to refresh. At this point I also realized that I'm currently a bit out of my depth!

daishi4u commented 5 years ago

You are correct in assuming that Forcecode isn't supposed to refresh at the src level. I will look into a way at disabling the context menu at that level.

stephenroden commented 5 years ago

Thanks @daishi4u I've been playing around a bit more and I came up with this. Basically if it's on the src folder it'll return back a Promise with an array of PXMLMembers. If it's not on src it'll return back a single array element of what it would have before. I really need to work out what I need for a push request so that I can help don't I (blush) ...

In parser/open.ts


export function getAnyNamesFromUri(uri: vscode.Uri): Promise<PXMLMember[]> {
    return new Promise((resolve) => {
        const projRoot: string = vscode.window.forceCode.projectRoot + path.sep;
        const uriNameParts: string[] = uri.fsPath.split(projRoot);
        let ret: PXMLMember[] = [];

        if (uriNameParts.length > 1) {
            ret.push(getAnyNameFromUri(uri)[0]);
        }
        else {
            vscode.window.forceCode.describe.metadataObjects.forEach(function (metadataObject: IMetadataObject) {
                ret.push({ name: metadataObject.xmlName, members: ['*'] });
            })
        }

        resolve(ret);
    });
}

and in commands.ts

import { getAnyNamesFromUri } from '../parsers/open';

and

    {
        commandName: 'ForceCode.refreshContext',
        name: 'Retrieving ',
        hidden: true,
        command: async function (context, selectedResource?) {
            if(selectedResource && selectedResource instanceof Array) {
                return new Promise((resolve) => {
                    var files: PXMLMember[] = [];
                    var proms: Promise<PXMLMember[]>[] = [];
                    selectedResource.forEach(curRes => {
                        proms = proms.concat(getAnyNamesFromUri(curRes));
                    });
                    Promise.all(proms).then(member => {
                        member.forEach(theNames => {
                            theNames.forEach(curName => {
                                var index: number = getTTIndex(curName.name, files);
                                if(index >= 0) {
                                    if(curName.members === ['*']) {
                                        files[index].members = ['*'];
                                    } else {
                                        files[index].members.push(...curName.members);
                                    }
                                } else {
                                    files.push(curName);
                                }
                            });
                        });
                        resolve(commands.retrieve({types: files}));
                    });
                });
            }
            if(context) {
                return commands.retrieve(context);
            }
            if(!vscode.window.activeTextEditor) {
                return undefined;
            }
            return commands.retrieve(vscode.window.activeTextEditor.document.uri);

            function getTTIndex(toolType: string, arr: ToolingType[]): number {
                return arr.findIndex(cur => {
                    return cur.name === toolType && cur.members !== ['*'];
                });
            }
        }
    },
daishi4u commented 5 years ago

Since VSCode currently doesn't offer any access to their explorer view in the VSCode API, I have added a nice error message when trying to refresh the src folder or any other file/folder outside of it