@@ -212,7 +212,10 @@ pub fn completion<'db>(
212212 offset : TextSize ,
213213) -> Vec < Completion < ' db > > {
214214 let parsed = parsed_module ( db, file) . load ( db) ;
215- if is_in_comment ( & parsed, offset) || is_in_string ( & parsed, offset) {
215+
216+ let tokens = tokens_start_before ( parsed. tokens ( ) , offset) ;
217+
218+ if is_in_comment ( tokens) || is_in_string ( tokens) || is_in_definition_place ( db, tokens, file) {
216219 return vec ! [ ] ;
217220 }
218221
@@ -829,8 +832,7 @@ fn find_typed_text(
829832
830833/// Whether the given offset within the parsed module is within
831834/// a comment or not.
832- fn is_in_comment ( parsed : & ParsedModuleRef , offset : TextSize ) -> bool {
833- let tokens = tokens_start_before ( parsed. tokens ( ) , offset) ;
835+ fn is_in_comment ( tokens : & [ Token ] ) -> bool {
834836 tokens. last ( ) . is_some_and ( |t| t. kind ( ) . is_comment ( ) )
835837}
836838
@@ -839,8 +841,7 @@ fn is_in_comment(parsed: &ParsedModuleRef, offset: TextSize) -> bool {
839841///
840842/// Note that this will return `false` when positioned within an
841843/// interpolation block in an f-string or a t-string.
842- fn is_in_string ( parsed : & ParsedModuleRef , offset : TextSize ) -> bool {
843- let tokens = tokens_start_before ( parsed. tokens ( ) , offset) ;
844+ fn is_in_string ( tokens : & [ Token ] ) -> bool {
844845 tokens. last ( ) . is_some_and ( |t| {
845846 matches ! (
846847 t. kind( ) ,
@@ -849,6 +850,29 @@ fn is_in_string(parsed: &ParsedModuleRef, offset: TextSize) -> bool {
849850 } )
850851}
851852
853+ /// If the tokens end with `class f` or `def f` we return true.
854+ /// If the tokens end with `class` or `def`, we return false.
855+ /// This is fine because we don't provide completions anyway.
856+ fn is_in_definition_place ( db : & dyn Db , tokens : & [ Token ] , file : File ) -> bool {
857+ tokens
858+ . len ( )
859+ . checked_sub ( 2 )
860+ . and_then ( |i| tokens. get ( i) )
861+ . is_some_and ( |t| {
862+ if matches ! (
863+ t. kind( ) ,
864+ TokenKind :: Def | TokenKind :: Class | TokenKind :: Type
865+ ) {
866+ true
867+ } else if t. kind ( ) == TokenKind :: Name {
868+ let source = source_text ( db, file) ;
869+ & source[ t. range ( ) ] == "type"
870+ } else {
871+ false
872+ }
873+ } )
874+ }
875+
852876/// Order completions according to the following rules:
853877///
854878/// 1) Names with no underscore prefix
@@ -4058,6 +4082,83 @@ def f[T](x: T):
40584082 test. build ( ) . contains ( "__repr__" ) ;
40594083 }
40604084
4085+ #[ test]
4086+ fn no_completions_in_function_def_name ( ) {
4087+ let builder = completion_test_builder (
4088+ "\
4089+ def f<CURSOR>
4090+ " ,
4091+ ) ;
4092+
4093+ builder. auto_import ( ) . build ( ) . not_contains ( "fabs" ) ;
4094+ }
4095+
4096+ #[ test]
4097+ fn no_completions_in_function_def_empty_name ( ) {
4098+ let builder = completion_test_builder (
4099+ "\
4100+ def <CURSOR>
4101+ " ,
4102+ ) ;
4103+
4104+ builder. auto_import ( ) . build ( ) . not_contains ( "fabs" ) ;
4105+ }
4106+
4107+ #[ test]
4108+ fn no_completions_in_class_def_name ( ) {
4109+ let builder = completion_test_builder (
4110+ "\
4111+ class f<CURSOR>
4112+ " ,
4113+ ) ;
4114+
4115+ builder. auto_import ( ) . build ( ) . not_contains ( "fabs" ) ;
4116+ }
4117+
4118+ #[ test]
4119+ fn no_completions_in_class_def_empty_name ( ) {
4120+ let builder = completion_test_builder (
4121+ "\
4122+ class <CURSOR>
4123+ " ,
4124+ ) ;
4125+
4126+ builder. auto_import ( ) . build ( ) . not_contains ( "fabs" ) ;
4127+ }
4128+
4129+ #[ test]
4130+ fn no_completions_in_type_def_name ( ) {
4131+ let builder = completion_test_builder (
4132+ "\
4133+ type f<CURSOR> = int
4134+ " ,
4135+ ) ;
4136+
4137+ builder. auto_import ( ) . build ( ) . not_contains ( "fabs" ) ;
4138+ }
4139+
4140+ #[ test]
4141+ fn no_completions_in_maybe_type_def_name ( ) {
4142+ let builder = completion_test_builder (
4143+ "\
4144+ type f<CURSOR>
4145+ " ,
4146+ ) ;
4147+
4148+ builder. auto_import ( ) . build ( ) . not_contains ( "fabs" ) ;
4149+ }
4150+
4151+ #[ test]
4152+ fn no_completions_in_type_def_empty_name ( ) {
4153+ let builder = completion_test_builder (
4154+ "\
4155+ type <CURSOR>
4156+ " ,
4157+ ) ;
4158+
4159+ builder. auto_import ( ) . build ( ) . not_contains ( "fabs" ) ;
4160+ }
4161+
40614162 /// A way to create a simple single-file (named `main.py`) completion test
40624163 /// builder.
40634164 ///
0 commit comments