Skip to content

Commit 71eb563

Browse files
authored
fix: Use broader template-lint range
Use broader template-lint range
2 parents 0c27ced + 45158a0 commit 71eb563

File tree

5 files changed

+162
-42
lines changed

5 files changed

+162
-42
lines changed

src/project.ts

+2-24
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,8 @@ import {
77
getRegistryForRoots,
88
existsInRegistry,
99
} from './utils/registry-api';
10-
import { ProjectProviders, collectProjectProviders, AddonMeta, DependencyMeta, emptyProjectProviders } from './utils/addon-api';
11-
import {
12-
findTestsForProject,
13-
findAddonItemsForProject,
14-
findAppItemsForProject,
15-
isRootStartingWithFilePath,
16-
getDepIfExists,
17-
cached,
18-
PackageInfo,
19-
} from './utils/layout-helpers';
10+
import { ProjectProviders, collectProjectProviders, AddonMeta, emptyProjectProviders } from './utils/addon-api';
11+
import { findTestsForProject, findAddonItemsForProject, findAppItemsForProject, isRootStartingWithFilePath, cached, PackageInfo } from './utils/layout-helpers';
2012
import { BaseProject } from './base-project';
2113
import Server from './server';
2214
import { Diagnostic, FileChangeType } from 'vscode-languageserver/node';
@@ -49,7 +41,6 @@ export class Project extends BaseProject {
4941
providers!: ProjectProviders;
5042
builtinProviders!: ProjectProviders;
5143
addonsMeta: AddonMeta[] = [];
52-
dependenciesMeta: DependencyMeta[] = [];
5344
executors: Executors = {};
5445
watchers: Watcher[] = [];
5546
destructors: Destructor[] = [];
@@ -175,19 +166,6 @@ export class Project extends BaseProject {
175166
this.addons = addons;
176167
this.addonsMeta = [];
177168
this._packageJSON = pkg;
178-
// for now, let's collect only interesting deps
179-
const interestingDeps = ['ember-cli', 'ember-source', 'ember-template-lint', 'typescript', '@embroider/core'];
180-
181-
interestingDeps.forEach((dep) => {
182-
const version = getDepIfExists(pkg, dep);
183-
184-
if (version !== null) {
185-
this.dependenciesMeta.push({
186-
name: dep,
187-
version,
188-
});
189-
}
190-
});
191169
}
192170
async unload() {
193171
this.initIssues = [];

src/template-linter.ts

+36-13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import Server from './server';
1212
import { Project } from './project';
1313
import { getRequireSupport } from './utils/layout-helpers';
1414
import { getFileRanges, RangeWalker } from './utils/glimmer-script';
15+
import * as semver from 'semver';
16+
import { type SemVer } from 'semver';
1517

1618
type FindUp = (name: string, opts: { cwd: string; type: string }) => Promise<string | undefined>;
1719
type LinterVerifyArgs = { source: string; moduleId: string; filePath: string };
@@ -88,7 +90,7 @@ export default class TemplateLinter {
8890
return this.server.projectRoots.projectForUri(textDocument.uri);
8991
}
9092

91-
private sourcesForDocument(textDocument: TextDocument, templateLintVersion: string): string[] {
93+
private sourcesForDocument(textDocument: TextDocument, templateLintVersion: SemVer | null): string[] {
9294
const ext = getExtension(textDocument);
9395

9496
if (ext !== null && !extensionsToLint.includes(ext)) {
@@ -98,8 +100,11 @@ export default class TemplateLinter {
98100
const documentContent = textDocument.getText();
99101

100102
// we assume that ember-template-lint v5 could handle js/ts/gts/gjs files
103+
if (!templateLintVersion) {
104+
return [documentContent];
105+
}
101106

102-
if (templateLintVersion === '5') {
107+
if (semver.gte(templateLintVersion, '5.0.0')) {
103108
return [documentContent];
104109
}
105110

@@ -139,28 +144,46 @@ export default class TemplateLinter {
139144
});
140145
}
141146
}
147+
getSourcesForDocument(textDocument: TextDocument, project: Project): string[] {
148+
const linterMeta = project.dependencyMap.get('ember-template-lint');
149+
150+
if (!linterMeta) {
151+
return [];
152+
}
153+
154+
let sources = [];
155+
156+
try {
157+
/**
158+
* Semver parsing can throw errors, if the version is invalid,
159+
* we want behave as if there was no version specified.
160+
*
161+
* (same as when errors are thrown from sourcesForDocument)
162+
*/
163+
const version = linterMeta?.package.version;
164+
const linterVersion = version ? semver.parse(version) : null;
165+
166+
sources = this.sourcesForDocument(textDocument, linterVersion);
167+
} catch (e) {
168+
return [];
169+
}
170+
171+
return sources;
172+
}
142173
async lint(textDocument: TextDocument): Promise<Diagnostic[] | undefined> {
143174
if (this._isEnabled === false) {
144-
return;
175+
return [];
145176
}
146177

147178
const cwd = process.cwd();
179+
148180
const project = this.getProjectForDocument(textDocument);
149181

150182
if (!project) {
151183
return;
152184
}
153185

154-
const linterMeta = project.dependenciesMeta.find((dep) => dep.name === 'ember-template-lint');
155-
const linterVersion = linterMeta?.version.split('.')[0] || 'unknown';
156-
157-
let sources = [];
158-
159-
try {
160-
sources = this.sourcesForDocument(textDocument, linterVersion);
161-
} catch (e) {
162-
return;
163-
}
186+
const sources = this.getSourcesForDocument(textDocument, project);
164187

165188
if (!sources.length) {
166189
return;

src/utils/addon-api.ts

-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@ export async function collectProjectProviders(root: string, addons: string[], de
349349
}
350350

351351
export type AddonMeta = { root: string; name: string; version: null | 1 | 2 };
352-
export type DependencyMeta = { name: string; version: string };
353352

354353
export function emptyProjectProviders(providers?: Partial<ProjectProviders>): ProjectProviders {
355354
return {

src/utils/layout-helpers.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as memoize from 'memoizee';
22
import * as path from 'path';
33
import { CompletionItem, CompletionItemKind } from 'vscode-languageserver/node';
44
import { addToRegistry, normalizeMatchNaming } from './registry-api';
5-
import { clean, coerce, valid } from 'semver';
65
import { BaseProject } from '../base-project';
76
import { fsProvider } from '../fs-provider';
87
import walkAsync from './walk-async';
@@ -42,6 +41,7 @@ type StringConfig = Record<string, string>;
4241
export interface PackageInfo {
4342
keywords?: string[];
4443
name?: string;
44+
version?: string;
4545
'ember-language-server'?: UnknownConfig;
4646
peerDependencies?: StringConfig;
4747
devDependencies?: StringConfig;
@@ -297,9 +297,7 @@ export function getDepIfExists(pack: PackageInfo, depName: string): string | nul
297297

298298
const version: string = pack?.dependencies?.[depName] ?? pack?.devDependencies?.[depName] ?? pack?.peerDependencies?.[depName] ?? '';
299299

300-
const cleanVersion = clean(version);
301-
302-
return valid(coerce(cleanVersion));
300+
return version;
303301
}
304302

305303
export async function isGlimmerXProject(root: string) {

test/template-linter-test.ts

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import TemplateLinter from '../src/template-linter';
2+
import { type Project, type Server } from '../src';
3+
import { type TextDocument } from 'vscode-languageserver-textdocument';
4+
5+
function getLinterInstance(depName?: string, depVersion?: string): [TemplateLinter, Project] {
6+
const linter = new TemplateLinter({
7+
projectRoots: {
8+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
9+
projectForUri(_url: string) {
10+
return {
11+
dependencyMap: new Map(depName ? [[depName, { package: { name: depName, version: depVersion } }]] : []),
12+
} as Project;
13+
},
14+
},
15+
options: {
16+
type: 'node',
17+
},
18+
} as Server);
19+
20+
return [linter, linter['server'].projectRoots.projectForUri('') as Project];
21+
}
22+
23+
describe('template-linter', function () {
24+
describe('sourcesForDocument', function () {
25+
it('supports empty template-lint version', function () {
26+
const [linter, project] = getLinterInstance();
27+
28+
const doc: TextDocument = {
29+
uri: 'test.gjs',
30+
getText() {
31+
return 'let a = 12;<template>1</template>';
32+
},
33+
} as TextDocument;
34+
35+
expect(linter.getSourcesForDocument(doc, project)).toEqual([]);
36+
});
37+
it('supports incorrect template-lint version [foo-bar]', function () {
38+
const [linter, project] = getLinterInstance('ember-template-lint', 'foo-bar');
39+
40+
const doc: TextDocument = {
41+
uri: 'test.gjs',
42+
getText() {
43+
return 'let a = 12;<template>1</template>';
44+
},
45+
} as TextDocument;
46+
47+
expect(linter.getSourcesForDocument(doc, project)).toEqual([doc.getText()]);
48+
});
49+
it('supports incorrect template-lint version [*]', function () {
50+
const [linter, project] = getLinterInstance('ember-template-lint', '*');
51+
52+
const doc: TextDocument = {
53+
uri: 'test.gjs',
54+
getText() {
55+
return 'let a = 12;<template>1</template>';
56+
},
57+
} as TextDocument;
58+
59+
expect(linter.getSourcesForDocument(doc, project)).toEqual([doc.getText()]);
60+
});
61+
it('process gjs for template-lint v2 with', function () {
62+
const [linter, project] = getLinterInstance('ember-template-lint', '2.0.0');
63+
64+
const doc: TextDocument = {
65+
uri: 'test.gjs',
66+
getText() {
67+
return 'let a = 12;<template>1</template>';
68+
},
69+
} as TextDocument;
70+
71+
expect(linter.getSourcesForDocument(doc, project)).toEqual([' 1']);
72+
});
73+
it('process gjs for template-lint v3 with', function () {
74+
const [linter, project] = getLinterInstance('ember-template-lint', '3.3.1');
75+
76+
const doc: TextDocument = {
77+
uri: 'test.gjs',
78+
getText() {
79+
return 'let a = 12;<template>1</template>';
80+
},
81+
} as TextDocument;
82+
83+
expect(linter.getSourcesForDocument(doc, project)).toEqual([' 1']);
84+
});
85+
it('process gjs for template-lint v4 with', function () {
86+
const [linter, project] = getLinterInstance('ember-template-lint', '4.3.1');
87+
88+
const doc: TextDocument = {
89+
uri: 'test.gjs',
90+
getText() {
91+
return 'let a = 12;<template>1</template>';
92+
},
93+
} as TextDocument;
94+
95+
expect(linter.getSourcesForDocument(doc, project)).toEqual([' 1']);
96+
});
97+
it('skip gjs processing for template-lint v5', function () {
98+
const [linter, project] = getLinterInstance('ember-template-lint', '5.0.0');
99+
100+
const doc: TextDocument = {
101+
uri: 'test.gjs',
102+
getText() {
103+
return 'let a = 12;<template>1</template>';
104+
},
105+
} as TextDocument;
106+
107+
expect(linter.getSourcesForDocument(doc, project)).toEqual([doc.getText()]);
108+
});
109+
it('skip gjs processing for template-lint v6', function () {
110+
const [linter, project] = getLinterInstance('ember-template-lint', '6.0.0');
111+
112+
const doc: TextDocument = {
113+
uri: 'test.gjs',
114+
getText() {
115+
return 'let a = 12;<template>1</template>';
116+
},
117+
} as TextDocument;
118+
119+
expect(linter.getSourcesForDocument(doc, project)).toEqual([doc.getText()]);
120+
});
121+
});
122+
});

0 commit comments

Comments
 (0)