mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-26 03:29:00 +01:00
Implements code-no-observable-get-in-reactive-context (#267526)
* Implements code-no-observable-get-in-reactive-context * Improves code * Fixes lint warnings
This commit is contained in:
committed by
GitHub
parent
b20a91e37a
commit
dace6b32b3
@@ -0,0 +1,202 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// Test file to verify the code-no-observable-get-in-reactive-context ESLint rule works correctly
|
||||
|
||||
import { observableValue, derived, autorun } from '../../src/vs/base/common/observable.js';
|
||||
|
||||
export function testValidUsage() {
|
||||
const obs = observableValue('test', 0);
|
||||
|
||||
// Valid: Using .read(reader) in derived
|
||||
const validDerived = derived(reader => {
|
||||
const value = obs.read(reader);
|
||||
return value * 2;
|
||||
});
|
||||
|
||||
// Valid: Using .read(reader) in autorun
|
||||
autorun(rdr => {
|
||||
const value = validDerived.read(rdr);
|
||||
console.log('Value:', value);
|
||||
});
|
||||
|
||||
// Valid: Using .get() outside reactive context
|
||||
const outsideValue = obs.get();
|
||||
console.log('Outside value:', outsideValue);
|
||||
}
|
||||
|
||||
export function testInvalidUsage() {
|
||||
const obs = observableValue('test', 0);
|
||||
|
||||
// Invalid: Using .get() in derived instead of .read(reader)
|
||||
const invalidDerived = derived(rdr => {
|
||||
// This should use obs.read(reader) instead
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
const value = obs.get();
|
||||
// Use reader for something valid to avoid unused var warning
|
||||
const validValue = obs.read(rdr);
|
||||
|
||||
obs.read(undefined);
|
||||
|
||||
return value * 2 + validValue;
|
||||
});
|
||||
|
||||
// Invalid: Using .get() in autorun instead of .read(reader)
|
||||
autorun(reader => {
|
||||
// This should use invalidDerived.read(reader) instead
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
const value = invalidDerived.get();
|
||||
// Use reader for something valid to avoid unused var warning
|
||||
const validValue = obs.read(reader);
|
||||
console.log('Value:', value, validValue);
|
||||
});
|
||||
|
||||
// Invalid: Using .get() in derivedWithStore
|
||||
derived(reader => {
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
const value = obs.get();
|
||||
reader.store.add({ dispose: () => { } });
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
export function testComplexCases() {
|
||||
const obs1 = observableValue('test1', 0);
|
||||
const obs2 = observableValue('test2', 10);
|
||||
|
||||
// Invalid: Using .get() in conditional within derived
|
||||
derived(reader => {
|
||||
const initial = obs1.read(reader);
|
||||
|
||||
if (initial > 0) {
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
return obs2.get();
|
||||
}
|
||||
|
||||
return initial;
|
||||
});
|
||||
|
||||
// Invalid: Using .get() in nested function call within autorun
|
||||
autorun(reader => {
|
||||
const process = () => {
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
return obs1.get() + obs2.get();
|
||||
};
|
||||
|
||||
// Use reader for something valid to avoid unused var warning
|
||||
const validValue = obs1.read(reader);
|
||||
const result = process();
|
||||
console.log('Result:', result, validValue);
|
||||
});
|
||||
|
||||
// Invalid: Using .get() in try-catch within derived
|
||||
derived(reader => {
|
||||
try {
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
const value = obs1.get();
|
||||
// Use reader for something valid to avoid unused var warning
|
||||
const validValue = obs2.read(reader);
|
||||
return value * 2 + validValue;
|
||||
} catch (e) {
|
||||
return obs2.read(reader);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function testValidComplexCases() {
|
||||
const obs1 = observableValue('test1', 0);
|
||||
const obs2 = observableValue('test2', 10);
|
||||
|
||||
// Valid: Proper usage with .read(reader)
|
||||
derived(reader => {
|
||||
const value1 = obs1.read(reader);
|
||||
const value2 = obs2.read(undefined);
|
||||
|
||||
if (value1 > 0) {
|
||||
return value2;
|
||||
}
|
||||
|
||||
return value1;
|
||||
});
|
||||
|
||||
// Valid: Using .get() outside reactive context
|
||||
function processValues() {
|
||||
const val1 = obs1.get();
|
||||
const val2 = obs2.get();
|
||||
return val1 + val2;
|
||||
}
|
||||
|
||||
// Valid: Mixed usage - .read(reader) inside reactive, .get() outside
|
||||
autorun(reader => {
|
||||
const reactiveValue = obs1.read(reader);
|
||||
const outsideValue = processValues();
|
||||
console.log('Values:', reactiveValue, outsideValue);
|
||||
});
|
||||
}
|
||||
|
||||
export function testEdgeCases() {
|
||||
const obs = observableValue('test', 0);
|
||||
|
||||
// Valid: Function with no reader parameter
|
||||
derived(() => {
|
||||
const value = obs.get();
|
||||
return value;
|
||||
});
|
||||
|
||||
// Invalid: Function with differently named parameter (now also flagged)
|
||||
derived(_someOtherName => {
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
const value = obs.get();
|
||||
return value;
|
||||
});
|
||||
|
||||
// Invalid: Correctly named reader parameter
|
||||
derived(reader => {
|
||||
// eslint-disable-next-line local/code-no-observable-get-in-reactive-context
|
||||
const value = obs.get();
|
||||
// Use reader for something valid to avoid unused var warning
|
||||
const validValue = obs.read(reader);
|
||||
return value + validValue;
|
||||
});
|
||||
}
|
||||
|
||||
export function testQuickFixScenarios() {
|
||||
const obs = observableValue('test', 0);
|
||||
const obs2 = observableValue('test2', 10);
|
||||
|
||||
// These examples show what the quick fix should transform:
|
||||
|
||||
// Example 1: Simple case with 'reader' parameter name
|
||||
derived(_reader => {
|
||||
const value = obs.read(undefined); // This should be the auto-fix result
|
||||
return value;
|
||||
});
|
||||
|
||||
// Example 2: Different parameter name
|
||||
derived(rdr => {
|
||||
// Before fix: obs2.get()
|
||||
// After fix: obs2.read(rdr)
|
||||
const value = obs2.read(rdr); // This should be the auto-fix result
|
||||
return value;
|
||||
});
|
||||
|
||||
// Example 3: Complex expression
|
||||
derived(ctx => {
|
||||
// Before fix: (someCondition ? obs : obs2).get()
|
||||
// After fix: (someCondition ? obs : obs2).read(ctx)
|
||||
const someCondition = true;
|
||||
const value = (someCondition ? obs : obs2).read(ctx); // This should be the auto-fix result
|
||||
return value;
|
||||
});
|
||||
|
||||
// Example 4: Multiple calls in same function
|
||||
autorun(reader => {
|
||||
// Before fix: obs.get() and obs2.get()
|
||||
// After fix: obs.read(reader) and obs2.read(reader)
|
||||
const val1 = obs.read(reader); // This should be the auto-fix result
|
||||
const val2 = obs2.read(reader); // This should be the auto-fix result
|
||||
console.log(val1, val2);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user