Skip to content

Commit

Permalink
fix: language server would crash if main class could not be identified (
Browse files Browse the repository at this point in the history
#578)

Fixes forcedotcom/salesforcedx-vscode#4994.

Co-authored-by: Cristina Cañizales <113132642+CristiCanizales@users.noreply.github.com>
  • Loading branch information
divmain and CristiCanizales authored Sep 27, 2023
1 parent 7bfa0dc commit d96478d
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ export default class Foo extends LightningElement {
@api property = true;
}
`;
const codeWithoutDefaultExportSingleClass = `
import { api, LightningElement } from 'lwc';
class Foo extends LightningElement {
@api foo;
}
`;
const codeWithoutDefaultExportMultipleClasses = `
import { api, LightningElement } from 'lwc';
class Foo extends LightningElement {
@api foo;
}
class Bar extends LightningElement {
@api bar;
}
`;

it('can get metadata from a simple component', async () => {
await compileSource(codeOk, 'foo.js');
Expand All @@ -46,6 +61,21 @@ it('displays an error for a component with syntax error', async () => {
expect(diagnostic.message).toMatch('Unexpected token (4:17)');
});

it('returns empty metadata for a script without a clear main component class', async () => {
const result = await compileSource(codeWithoutDefaultExportMultipleClasses, 'foo.js');
expect(result.metadata?.decorators).toHaveLength(0);
expect(result.metadata?.classMembers).toHaveLength(0);
expect(result.metadata?.exports).toHaveLength(0);
});

it('returns metadata for a script with one component class, even when not exported', async () => {
const result = await compileSource(codeWithoutDefaultExportSingleClass, 'foo.js');
console.log(result);
expect(result.metadata?.decorators).toHaveLength(1);
expect(result.metadata?.classMembers).toHaveLength(1);
expect(result.metadata?.exports).toHaveLength(0);
});

it('displays an error for a component with other errors', async () => {
const result = await compileSource(codeError, 'foo.js');
expect(result.metadata).toBeUndefined();
Expand Down
21 changes: 18 additions & 3 deletions packages/lwc-language-server/src/javascript/type-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,24 @@ function getExports(lwcExports: LwcExport[]): InternalModuleExports[] {
* LWC language server to analyze code in a user's IDE.
*/
export function mapLwcMetadataToInternal(lwcMeta: ScriptFile): InternalMetadata {
const mainClassObj = lwcMeta.classes.find(classObj => {
return classObj.id == lwcMeta.mainClass.refId;
});
let mainClassObj;
if (lwcMeta.mainClass) {
mainClassObj = lwcMeta.classes.find(classObj => {
return classObj.id == lwcMeta.mainClass.refId;
});
} else if (lwcMeta.classes.length === 1) {
mainClassObj = lwcMeta.classes[0];
}

// If we are unable to identify the main class object from the provided metadata,
// it will not be possible calculate decorators, members, etc.
if (!mainClassObj) {
return {
decorators: [],
classMembers: [],
exports: [],
};
}

const defaultExport = lwcMeta.exports.filter((exp) => exp.defaultExport)[0];
const declarationLoc = externalToInternalLoc(defaultExport?.location ?? mainClassObj.location);
Expand Down

0 comments on commit d96478d

Please sign in to comment.