Skip to content

feat: add use_nearest_context rule#293

Open
solid-illiaaihistov wants to merge 7 commits into
solid-software:analysis_server_migrationfrom
solid-illiaaihistov:issue-190-implement-use_nearest_context
Open

feat: add use_nearest_context rule#293
solid-illiaaihistov wants to merge 7 commits into
solid-software:analysis_server_migrationfrom
solid-illiaaihistov:issue-190-implement-use_nearest_context

Conversation

@solid-illiaaihistov

Copy link
Copy Markdown
Collaborator

Closes #190

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the use_nearest_context lint rule along with two quick fixes (RenameNearestContextParameterFix and ReplaceWithNearestContextParameterFix) to ensure BuildContext is accessed from the nearest available scope. It also updates isBuildContext to support nullable types and includes comprehensive unit tests. The review feedback highlights two important improvements: first, ReplaceWithNearestContextParameterFix should be extended to handle direct usage of context (not just property accesses on this); second, the visitor can be simplified by using element.nameOffset directly to avoid an unnecessary null check.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lib/src/lints/use_nearest_context/visitors/use_nearest_context_visitor.dart Outdated
@solid-illiaaihistov

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the use_nearest_context lint rule, which encourages using the BuildContext from the nearest available scope. It includes the rule implementation, a visitor, utility functions, unit tests, and two quick fixes: RenameNearestContextParameterFix and ReplaceWithNearestContextParameterFix. The feedback highlights an issue in the ReplaceWithNearestContextParameterFix where plain SimpleIdentifiers (like plain context usage) are not replaced, and suggests adding a fallback. Additionally, it recommends simplifying the scope check in UseNearestContextVisitor by using element.nameOffset directly to avoid null checks.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lib/src/lints/use_nearest_context/visitors/use_nearest_context_visitor.dart Outdated
Comment on lines +403 to +407
class BuildContext {
Object? get size => null;
}
class Widget {}
void showModalBottomSheet({required BuildContext context, required Widget Function(BuildContext?) builder}) {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can extract that from all tests

@override
  void setUp() {
    final flutter = newPackage('flutter');
    flutter.addFile('lib/material.dart', r'''
class BuildContext {
  Object? get size => null;
}
class Widget {}
void showModalBottomSheet({required BuildContext context, required Widget Function(BuildContext?) builder}) {}
''');

And there are few other things that can be extracted there too scattered across other tests, like Future.microtask, etc

and then in each test we only need one line:

import 'package:flutter/material.dart';

);
}
''',
[lint(345, 12)],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use this instead

String expectLint(String code) {

e.g.

Future<void> test_reports_if_where_type_filters_nullable_type() async {
await assertAutoDiagnostics('''
void fun() {
${expectLint('[1.0, 2.0].whereType<double?>()')};
}
''');
}

Comment on lines +22 to +26
if (closestBuildContext.name?.lexeme != node.name) {
if (_isDeclaredInNearestScope(node, closestBuildContext)) return;

_rule.reportAtNode(node);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (closestBuildContext.name?.lexeme != node.name) {
if (_isDeclaredInNearestScope(node, closestBuildContext)) return;
_rule.reportAtNode(node);
}
if (closestBuildContext.name?.lexeme == node.name) return;
if (_isDeclaredInNearestScope(node, closestBuildContext)) return;
_rule.reportAtNode(node);

@solid-illiaaihistov solid-illiaaihistov changed the title feat: add use_nearest_context rule (#190) feat: add use_nearest_context rule Jun 18, 2026

@solid-danylosafonov solid-danylosafonov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, two optional suggestions

Comment on lines +38 to +53
/// Returns `true` if [node] is a property accessed on another object
/// (e.g. `state.context`), but not on `this` (e.g. `this.context`).
bool _isPropertyOfOtherObject(SimpleIdentifier node) {
final parent = node.parent;
if (parent is PrefixedIdentifier && node == parent.identifier) {
return true;
}
if (parent is PropertyAccess && node == parent.propertyName) {
var target = parent.target;
while (target is ParenthesizedExpression) {
target = target.expression;
}
return target is! ThisExpression && target is! SuperExpression;
}
return false;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit - maybe we should extract it to utils/node_utils.dart? - seems rather generic with potential for future reuse

Comment on lines +55 to +58
/// Returns `true` if [node] refers to a variable declared inside the body
/// of the function that owns [closestParam] (i.e. a local variable
/// in the same scope, like `final localCtx = innerContext;`).
bool _isDeclaredInNearestScope(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

  1. We probably can extract it to utils as well
  2. But, I'm not sure if the name reflects what this function does in the best way - maybe it should be something like isDeclaredInSameFunction? - that naming also leads me to think that it would look better as an extension for node so the call would look like node.isDeclaredInSameFunction(as: param)? WDYT?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a great idea! I've updated it accordingly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants