mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-13 03:33:15 +08:00
fix(project-detect): match packageKeys on boundaries, not substrings (#2181)
Framework detection matched a dependency against a framework's packageKeys with unbounded substring containment (dep.includes(key)), so any dependency whose name merely contained a key was misclassified: `preact` and even `reactive` were both detected as `react`. Match only when the dependency equals the key, or the key is a prefix immediately followed by a delimiter (/ . _ -). This still matches every real case (react-dom, @remix-run/node, spring-boot-starter, org.springframework.boot, github.com/labstack/echo/v4, phoenix_live_view) while excluding preact/reactive (and incidentally nextra). Adds regression tests. Co-authored-by: bymle <229636660+bymle@users.noreply.github.com>
This commit is contained in:
@@ -390,7 +390,20 @@ function detectProjectType(projectDir) {
|
|||||||
depList = elixirDeps;
|
depList = elixirDeps;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hasDep = rule.packageKeys.some(key => depList.some(dep => dep.toLowerCase().includes(key.toLowerCase())));
|
// Boundary-aware match: a dependency matches a packageKey only when it
|
||||||
|
// equals the key, or the key is a prefix immediately followed by a
|
||||||
|
// delimiter (/ . _ -). Plain substring matching wrongly classified
|
||||||
|
// `preact` / `reactive` as `react`. This still matches the real cases:
|
||||||
|
// react-dom, @remix-run/node, spring-boot-starter, org.springframework.boot,
|
||||||
|
// github.com/labstack/echo/v4, phoenix_live_view.
|
||||||
|
hasDep = rule.packageKeys.some(key => {
|
||||||
|
const k = key.toLowerCase();
|
||||||
|
return depList.some(dep => {
|
||||||
|
const d = dep.toLowerCase();
|
||||||
|
if (!d.startsWith(k)) return false;
|
||||||
|
return d.length === k.length || /[/._-]/.test(d[k.length]);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasMarker || hasDep) {
|
if (hasMarker || hasDep) {
|
||||||
|
|||||||
@@ -207,6 +207,39 @@ function runTests() {
|
|||||||
}
|
}
|
||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('does not misclassify preact as react (substring guard)', () => {
|
||||||
|
const dir = createTempDir();
|
||||||
|
try {
|
||||||
|
writeTestFile(dir, 'package.json', '{"dependencies":{"preact":"10.0.0"}}');
|
||||||
|
const result = detectProjectType(dir);
|
||||||
|
assert.ok(!result.frameworks.includes('react'), `preact wrongly detected as react: ${JSON.stringify(result.frameworks)}`);
|
||||||
|
} finally {
|
||||||
|
cleanupDir(dir);
|
||||||
|
}
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('does not misclassify reactive as react (substring guard)', () => {
|
||||||
|
const dir = createTempDir();
|
||||||
|
try {
|
||||||
|
writeTestFile(dir, 'package.json', '{"dependencies":{"reactive":"1.0.0"}}');
|
||||||
|
const result = detectProjectType(dir);
|
||||||
|
assert.ok(!result.frameworks.includes('react'), `reactive wrongly detected as react: ${JSON.stringify(result.frameworks)}`);
|
||||||
|
} finally {
|
||||||
|
cleanupDir(dir);
|
||||||
|
}
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('still detects react from react-dom alone (prefix-delimiter match preserved)', () => {
|
||||||
|
const dir = createTempDir();
|
||||||
|
try {
|
||||||
|
writeTestFile(dir, 'package.json', '{"dependencies":{"react-dom":"18.0.0"}}');
|
||||||
|
const result = detectProjectType(dir);
|
||||||
|
assert.ok(result.frameworks.includes('react'), `react-dom should still map to react: ${JSON.stringify(result.frameworks)}`);
|
||||||
|
} finally {
|
||||||
|
cleanupDir(dir);
|
||||||
|
}
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
if (test('detects angular from angular.json', () => {
|
if (test('detects angular from angular.json', () => {
|
||||||
const dir = createTempDir();
|
const dir = createTempDir();
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user