@@ -831,65 +831,79 @@ pub fn remove_binding(
831
831
) -> Result < lsp_types:: WorkspaceEdit > {
832
832
let source_file = element. with_element_node ( |node| node. source_file . clone ( ) ) ;
833
833
834
- let range = find_property_binding_offset ( element, property_name)
834
+ let token = find_property_binding_offset ( element, property_name)
835
835
. and_then ( |offset| {
836
836
element. with_element_node ( |node| node. token_at_offset ( offset. into ( ) ) . right_biased ( ) )
837
837
} )
838
- . and_then ( |token| {
839
- for ancestor in token. parent_ancestors ( ) {
840
- if ( ancestor. kind ( ) == SyntaxKind :: Binding )
841
- || ( ancestor. kind ( ) == SyntaxKind :: PropertyDeclaration )
842
- {
843
- let start = {
844
- let token = left_extend ( ancestor. first_token ( ) ?) ;
845
- let start = token. text_range ( ) . start ( ) ;
846
- token
847
- . prev_token ( )
848
- . and_then ( |t| {
849
- if t. kind ( ) == SyntaxKind :: Whitespace && t. text ( ) . contains ( '\n' ) {
850
- let to_sub =
851
- t. text ( ) . split ( '\n' ) . next_back ( ) . unwrap_or_default ( ) . len ( )
852
- as u32 ;
853
- start. checked_sub ( to_sub. into ( ) )
854
- } else {
855
- None
856
- }
857
- } )
858
- . unwrap_or ( start)
859
- } ;
860
- let end = {
861
- let token = right_extend ( ancestor. last_token ( ) ?) ;
862
- let end = token. text_range ( ) . end ( ) ;
863
- token
864
- . next_token ( )
865
- . and_then ( |t| {
866
- if t. kind ( ) == SyntaxKind :: Whitespace && t. text ( ) . contains ( '\n' ) {
867
- let to_add =
868
- t. text ( ) . split ( '\n' ) . next ( ) . unwrap_or_default ( ) . len ( )
869
- as u32 ;
870
- end. checked_add ( ( to_add + 1 /* <cr> */ ) . into ( ) )
871
- } else {
872
- None
873
- }
874
- } )
875
- . unwrap_or ( end)
876
- } ;
877
-
878
- return Some ( util:: text_range_to_lsp_range (
879
- & source_file,
880
- TextRange :: new ( start, end) ,
881
- ) ) ;
882
- }
883
- if ancestor. kind ( ) == SyntaxKind :: Element {
884
- // There should have been a binding before the element!
885
- break ;
886
- }
838
+ . ok_or ( "Could not find property to delete." ) ?;
839
+
840
+ for ancestor in token. parent_ancestors ( ) {
841
+ if ancestor. kind ( ) == SyntaxKind :: PropertyDeclaration {
842
+ let prop_decl = syntax_nodes:: PropertyDeclaration :: from ( ancestor. clone ( ) ) ;
843
+ let binding =
844
+ prop_decl. BindingExpression ( ) . ok_or ( "property declaration has no binding" ) ?;
845
+ let colon = ancestor
846
+ . child_token ( SyntaxKind :: Colon )
847
+ . ok_or ( "property peclaration has no colon" ) ?;
848
+ let start = colon. text_range ( ) . start ( ) ;
849
+ if let Some ( semi_colon) = binding. child_token ( SyntaxKind :: Semicolon ) {
850
+ let end = semi_colon. text_range ( ) . start ( ) ;
851
+ let range = util:: text_range_to_lsp_range ( & source_file, TextRange :: new ( start, end) ) ;
852
+ let edit = lsp_types:: TextEdit { range, new_text : String :: new ( ) } ;
853
+ return Ok ( common:: create_workspace_edit ( uri. clone ( ) , version, vec ! [ edit] ) ) ;
854
+ } else if let Some ( closing_brace) =
855
+ binding. CodeBlock ( ) . and_then ( |cb| cb. child_token ( SyntaxKind :: RBrace ) )
856
+ {
857
+ let end = closing_brace. text_range ( ) . end ( ) ;
858
+ let range = util:: text_range_to_lsp_range ( & source_file, TextRange :: new ( start, end) ) ;
859
+ let edit = lsp_types:: TextEdit { range, new_text : ";" . into ( ) } ;
860
+ return Ok ( common:: create_workspace_edit ( uri. clone ( ) , version, vec ! [ edit] ) ) ;
861
+ } else {
862
+ return Err ( "Could not find end of range to delete." . into ( ) ) ;
887
863
}
888
- None
889
- } )
890
- . ok_or_else ( || Into :: < common:: Error > :: into ( "Could not find range to delete." ) ) ?;
864
+ } else if ancestor. kind ( ) == SyntaxKind :: Binding {
865
+ let start = {
866
+ let token = left_extend ( ancestor. first_token ( ) . ok_or ( "empty binding" ) ?) ;
867
+ let start = token. text_range ( ) . start ( ) ;
868
+ token
869
+ . prev_token ( )
870
+ . and_then ( |t| {
871
+ if t. kind ( ) == SyntaxKind :: Whitespace && t. text ( ) . contains ( '\n' ) {
872
+ let to_sub =
873
+ t. text ( ) . split ( '\n' ) . next_back ( ) . unwrap_or_default ( ) . len ( ) as u32 ;
874
+ start. checked_sub ( to_sub. into ( ) )
875
+ } else {
876
+ None
877
+ }
878
+ } )
879
+ . unwrap_or ( start)
880
+ } ;
881
+ let end = {
882
+ let token = right_extend ( ancestor. last_token ( ) . ok_or ( "empty binding" ) ?) ;
883
+ let end = token. text_range ( ) . end ( ) ;
884
+ token
885
+ . next_token ( )
886
+ . and_then ( |t| {
887
+ if t. kind ( ) == SyntaxKind :: Whitespace && t. text ( ) . contains ( '\n' ) {
888
+ let to_add =
889
+ t. text ( ) . split ( '\n' ) . next ( ) . unwrap_or_default ( ) . len ( ) as u32 ;
890
+ end. checked_add ( ( to_add + 1 /* <cr> */ ) . into ( ) )
891
+ } else {
892
+ None
893
+ }
894
+ } )
895
+ . unwrap_or ( end)
896
+ } ;
891
897
892
- Ok ( create_workspace_edit_for_remove_binding ( uri, version, range) )
898
+ let range = util:: text_range_to_lsp_range ( & source_file, TextRange :: new ( start, end) ) ;
899
+ return Ok ( create_workspace_edit_for_remove_binding ( uri, version, range) ) ;
900
+ }
901
+ if ancestor. kind ( ) == SyntaxKind :: Element {
902
+ // There should have been a binding before the element!
903
+ break ;
904
+ }
905
+ }
906
+ Err ( "Could not find range to delete." . into ( ) )
893
907
}
894
908
895
909
#[ cfg( test) ]
@@ -1915,4 +1929,111 @@ component MyComp {
1915
1929
assert_eq ! ( tc. range. start, lsp_types:: Position { line: 17 , character: 27 } ) ;
1916
1930
assert_eq ! ( tc. range. end, lsp_types:: Position { line: 17 , character: 32 } ) ;
1917
1931
}
1932
+
1933
+ #[ test]
1934
+ fn test_remove_binding ( ) {
1935
+ let source = r#"
1936
+ component Foo inherits Window {
1937
+ width: 30px;
1938
+ background: red;
1939
+ Foo { background: blue; }
1940
+ }
1941
+ "# ;
1942
+ let ( dc, uri, _) = crate :: language:: test:: loaded_document_cache ( source. into ( ) ) ;
1943
+ let elem = dc
1944
+ . element_at_offset ( & uri, TextSize :: new ( source. find ( "Window" ) . unwrap ( ) as u32 ) )
1945
+ . unwrap ( ) ;
1946
+ let edit = remove_binding ( uri. clone ( ) , None , & elem, "background" ) . unwrap ( ) ;
1947
+
1948
+ let applied = crate :: common:: text_edit:: apply_workspace_edit ( & dc, & edit) . unwrap ( ) ;
1949
+ assert_eq ! (
1950
+ applied. first( ) . unwrap( ) . contents,
1951
+ r#"
1952
+ component Foo inherits Window {
1953
+ width: 30px;
1954
+ Foo { background: blue; }
1955
+ }
1956
+ "#
1957
+ ) ;
1958
+
1959
+ let elem = dc
1960
+ . element_at_offset ( & uri, TextSize :: new ( source. find ( "Foo {" ) . unwrap ( ) as u32 ) )
1961
+ . unwrap ( ) ;
1962
+ let edit = remove_binding ( uri. clone ( ) , None , & elem, "background" ) . unwrap ( ) ;
1963
+
1964
+ let applied = crate :: common:: text_edit:: apply_workspace_edit ( & dc, & edit) . unwrap ( ) ;
1965
+ assert_eq ! (
1966
+ applied. first( ) . unwrap( ) . contents,
1967
+ r#"
1968
+ component Foo inherits Window {
1969
+ width: 30px;
1970
+ background: red;
1971
+ Foo { }
1972
+ }
1973
+ "#
1974
+ ) ;
1975
+ }
1976
+
1977
+ #[ test]
1978
+ fn test_remove_binding_in_declaration ( ) {
1979
+ let source = r#"
1980
+ component Foo inherits Window {
1981
+ property <int> test1: 45 + 78; // comment
1982
+ property <int> test2: {
1983
+ return 4;
1984
+ }
1985
+ property <{x: int}> test3: { return { x: 0 }; };
1986
+ background: violet;
1987
+ }
1988
+ "# ;
1989
+ let ( dc, uri, _) = crate :: language:: test:: loaded_document_cache ( source. into ( ) ) ;
1990
+ let elem = dc
1991
+ . element_at_offset ( & uri, TextSize :: new ( source. find ( "Window" ) . unwrap ( ) as u32 ) )
1992
+ . unwrap ( ) ;
1993
+ let edit = remove_binding ( uri. clone ( ) , None , & elem, "test1" ) . unwrap ( ) ;
1994
+ let applied = crate :: common:: text_edit:: apply_workspace_edit ( & dc, & edit) . unwrap ( ) ;
1995
+ assert_eq ! (
1996
+ applied. first( ) . unwrap( ) . contents,
1997
+ r#"
1998
+ component Foo inherits Window {
1999
+ property <int> test1; // comment
2000
+ property <int> test2: {
2001
+ return 4;
2002
+ }
2003
+ property <{x: int}> test3: { return { x: 0 }; };
2004
+ background: violet;
2005
+ }
2006
+ "#
2007
+ ) ;
2008
+
2009
+ let edit = remove_binding ( uri. clone ( ) , None , & elem, "test2" ) . unwrap ( ) ;
2010
+ let applied = crate :: common:: text_edit:: apply_workspace_edit ( & dc, & edit) . unwrap ( ) ;
2011
+ assert_eq ! (
2012
+ applied. first( ) . unwrap( ) . contents,
2013
+ r#"
2014
+ component Foo inherits Window {
2015
+ property <int> test1: 45 + 78; // comment
2016
+ property <int> test2;
2017
+ property <{x: int}> test3: { return { x: 0 }; };
2018
+ background: violet;
2019
+ }
2020
+ "#
2021
+ ) ;
2022
+
2023
+ let edit = remove_binding ( uri. clone ( ) , None , & elem, "test3" ) . unwrap ( ) ;
2024
+ let applied = crate :: common:: text_edit:: apply_workspace_edit ( & dc, & edit) . unwrap ( ) ;
2025
+ assert_eq ! (
2026
+ applied. first( ) . unwrap( ) . contents,
2027
+ r#"
2028
+ component Foo inherits Window {
2029
+ property <int> test1: 45 + 78; // comment
2030
+ property <int> test2: {
2031
+ return 4;
2032
+ }
2033
+ property <{x: int}> test3;
2034
+ background: violet;
2035
+ }
2036
+ "#
2037
+ ) ;
2038
+ }
1918
2039
}
0 commit comments