github.com/tiagovtristao/plz@v13.4.0+incompatible/tools/build_langserver/langserver/completion_test.go (about)

     1  package langserver
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/thought-machine/please/tools/build_langserver/lsp"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  /***************************************
    14   *Tests for Attributes
    15   ***************************************/
    16  func TestCompletionWithCONFIG(t *testing.T) {
    17  	ctx := context.Background()
    18  
    19  	// Test completion on CONFIG with no starting character
    20  	items, err := handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 4, Character: 7})
    21  	assert.Equal(t, nil, err)
    22  	assert.Equal(t, len(analyzer.State.Config.TagsToFields()), len(items))
    23  	for _, i := range items {
    24  		assert.Equal(t, i.Kind, lsp.Property)
    25  	}
    26  
    27  	// Test completion on CONFIG with 1 starting character
    28  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 5, Character: 8})
    29  	assert.Equal(t, nil, err)
    30  	assert.True(t, len(analyzer.State.Config.TagsToFields()) > len(items))
    31  	assert.True(t, itemInList(items, "JARCAT_TOOL"))
    32  	assert.False(t, itemInList(items, "PLZ_VERSION"))
    33  
    34  	// Test completion on CONFIG with a word
    35  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 6, Character: 11})
    36  	assert.Equal(t, nil, err)
    37  	assert.True(t, len(analyzer.State.Config.TagsToFields()) > len(items))
    38  	assert.True(t, itemInList(items, "JAVAC_TOOL"))
    39  	for _, i := range items {
    40  		assert.True(t, strings.Contains(i.Label, "JAVA"))
    41  	}
    42  
    43  	// Test completion with assignment
    44  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 7, Character: 18})
    45  	assert.Equal(t, nil, err)
    46  	assert.True(t, len(analyzer.State.Config.TagsToFields()) > len(items))
    47  	assert.True(t, itemInList(items, "JAVAC_TOOL"))
    48  	for _, i := range items {
    49  		assert.True(t, strings.Contains(i.Label, "JAVA"))
    50  	}
    51  
    52  	// Test completion on empty line
    53  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 9, Character: 13})
    54  	assert.Equal(t, nil, err)
    55  	assert.Equal(t, 0, len(items))
    56  
    57  	// Test config should be empty
    58  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 8, Character: 14})
    59  	assert.Equal(t, nil, err)
    60  	assert.Equal(t, 0, len(items))
    61  }
    62  
    63  func TestCompletionWithStringMethods(t *testing.T) {
    64  	ctx := context.Background()
    65  	context.Background()
    66  
    67  	// Tests completion on no letters follows after dot(.)
    68  	items, err := handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 10, Character: 19})
    69  	assert.Equal(t, nil, err)
    70  	assert.Equal(t, len(analyzer.Attributes["str"]), len(items))
    71  	assert.True(t, itemInList(items, "replace"))
    72  	assert.True(t, itemInList(items, "format"))
    73  
    74  	// Test completion with 1 starting character: f
    75  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 11, Character: 20})
    76  	assert.Equal(t, nil, err)
    77  	assert.True(t, itemInList(items, "format"))
    78  	assert.True(t, itemInList(items, "find"))
    79  	assert.True(t, itemInList(items, "rfind"))
    80  
    81  	// Test completion with a three letters: for
    82  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 12, Character: 22})
    83  	assert.Equal(t, nil, err)
    84  	assert.Equal(t, 1, len(items))
    85  	assert.Equal(t, "format", items[0].Label)
    86  
    87  	// Test completion with assignment
    88  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 13, Character: 19})
    89  	assert.Equal(t, nil, err)
    90  	assert.Equal(t, 1, len(items))
    91  	assert.Equal(t, "format", items[0].Label)
    92  
    93  	// Test str method completion with variables
    94  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 14, Character: 16})
    95  	assert.Equal(t, nil, err)
    96  	assert.Equal(t, len(analyzer.Attributes["str"]), len(items))
    97  	assert.True(t, itemInList(items, "replace"))
    98  	assert.True(t, itemInList(items, "format"))
    99  }
   100  
   101  func TestCompletionWithDictMethods(t *testing.T) {
   102  	ctx := context.Background()
   103  
   104  	// Tests completion on no letters follows after dot(.)
   105  	items, err := handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 17, Character: 25})
   106  	assert.Equal(t, nil, err)
   107  	assert.Equal(t, len(analyzer.Attributes["dict"]), len(items))
   108  	assert.True(t, itemInList(items, "get"))
   109  	assert.True(t, itemInList(items, "keys"))
   110  	assert.True(t, itemInList(items, "items"))
   111  
   112  	// Test completion with 1 starting character: k
   113  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 18, Character: 16})
   114  	assert.Equal(t, nil, err)
   115  	assert.Equal(t, 1, len(items))
   116  	assert.Equal(t, "keys", items[0].Label)
   117  
   118  	// Test completion with a three letters: get
   119  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 19, Character: 18})
   120  	assert.Equal(t, nil, err)
   121  	assert.Equal(t, 1, len(items))
   122  	assert.Equal(t, "get", items[0].Label)
   123  
   124  	// Test dict method completion with variables
   125  	items, err = handler.getCompletionItemsList(ctx, completionPropURI, lsp.Position{Line: 20, Character: 17})
   126  	assert.Equal(t, nil, err)
   127  	assert.Equal(t, len(analyzer.Attributes["dict"]), len(items))
   128  	assert.True(t, itemInList(items, "get"))
   129  	assert.True(t, itemInList(items, "keys"))
   130  	assert.True(t, itemInList(items, "items"))
   131  }
   132  
   133  /***************************************
   134   *Tests for Build label completions
   135   ***************************************/
   136  func TestCompletionWithBuildLabels(t *testing.T) {
   137  	ctx := context.Background()
   138  
   139  	items, err := handler.getCompletionItemsList(ctx, completionLabelURI, lsp.Position{Line: 0, Character: 6})
   140  	assert.Equal(t, nil, err)
   141  	assert.True(t, itemInList(items, "src/cache"))
   142  	for _, i := range items {
   143  		assert.True(t, strings.HasPrefix(i.Label, "src"))
   144  	}
   145  
   146  	items, err = handler.getCompletionItemsList(ctx, completionLabelURI, lsp.Position{Line: 1, Character: 13})
   147  	assert.Equal(t, nil, err)
   148  	assert.Equal(t, 1, len(items))
   149  	assert.Equal(t, "query", items[0].Label)
   150  
   151  	items, err = handler.getCompletionItemsList(ctx, completionLabelURI, lsp.Position{Line: 2, Character: 14})
   152  	assert.Equal(t, nil, err)
   153  	assert.Equal(t, 1, len(items))
   154  	assert.Equal(t, "query", items[0].Label)
   155  	t.Log(items[0].Label)
   156  
   157  	// Ensure handling of partially completed labels
   158  	items, err = handler.getCompletionItemsList(ctx, completionLabelURI, lsp.Position{Line: 4, Character: 8})
   159  	assert.Equal(t, nil, err)
   160  	assert.Equal(t, 2, len(items))
   161  	assert.True(t, itemInList(items, "query"))
   162  	assert.True(t, itemInList(items, "query:query"))
   163  	assert.Equal(t, items[1].Detail, " BUILD Label: //src/query")
   164  }
   165  
   166  func TestCompletionWithBuildLabels2(t *testing.T) {
   167  	ctx := context.Background()
   168  
   169  	analyzer.State.Config.Parse.BuildFileName = []string{"completion2.build", "BUILD"}
   170  	// Ensure relative label working correctly
   171  	items, err := handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 15, Character: 11})
   172  	assert.Equal(t, nil, err)
   173  	assert.Equal(t, 4, len(items))
   174  
   175  	assert.True(t, itemInList(items, "my_binary"))
   176  	assert.True(t, itemInList(items, "langserver_test"))
   177  }
   178  
   179  /***************************************
   180   *Tests for Builtin rules
   181   ***************************************/
   182  func TestCompletionWithBuiltins(t *testing.T) {
   183  	ctx := context.Background()
   184  
   185  	items, err := handler.getCompletionItemsList(ctx, completionLiteralURI, lsp.Position{Line: 2, Character: 3})
   186  	assert.Equal(t, nil, err)
   187  	assert.True(t, itemInList(items, "go_library"))
   188  	assert.True(t, itemInList(items, "go_binary"))
   189  	assert.True(t, itemInList(items, "go_test"))
   190  	assert.True(t, itemInList(items, "go_get"))
   191  	for _, item := range items {
   192  		if item.Label == "go_library" {
   193  			expectedDetail := "(name:str, srcs:list, asm_srcs:list=None, hdrs:list=None, out:str=None, deps:list=[],\n" +
   194  				"               visibility:list=None, test_only:bool&testonly=False, complete:bool=True, cover:bool=True,\n" +
   195  				"               filter_srcs:bool=True)"
   196  			assert.Equal(t, expectedDetail, item.Detail)
   197  		}
   198  	}
   199  
   200  	items, err = handler.getCompletionItemsList(ctx, completionLiteralURI, lsp.Position{Line: 4, Character: 8})
   201  	assert.Equal(t, nil, err)
   202  	assert.Equal(t, 1, len(items))
   203  	assert.True(t, itemInList(items, "python_library"))
   204  }
   205  
   206  /***************************************
   207   *Tests for Variables
   208   ***************************************/
   209  func TestCompletionWithVars(t *testing.T) {
   210  	ctx := context.Background()
   211  
   212  	items, err := handler.getCompletionItemsList(ctx, completionLiteralURI, lsp.Position{Line: 7, Character: 3})
   213  	assert.Equal(t, nil, err)
   214  	assert.Equal(t, 1, len(items))
   215  	assert.Equal(t, "my_str", items[0].Label)
   216  
   217  	// Test none existing variable
   218  	items, err = handler.getCompletionItemsList(ctx, completionLiteralURI, lsp.Position{Line: 6, Character: 10})
   219  	assert.Equal(t, nil, err)
   220  	assert.Equal(t, 0, len(items))
   221  }
   222  
   223  /***************************************
   224   *Tests for Statements
   225   ***************************************/
   226  func TestCompletionWithIf(t *testing.T) {
   227  	ctx := context.Background()
   228  
   229  	// test within if statement
   230  	items, err := handler.getCompletionItemsList(ctx, completionStmtURI, lsp.Position{Line: 7, Character: 7})
   231  	assert.Equal(t, nil, err)
   232  	assert.True(t, itemInList(items, "go_library"))
   233  
   234  	items, err = handler.getCompletionItemsList(ctx, completionStmtURI, lsp.Position{Line: 1, Character: 21})
   235  	assert.Equal(t, nil, err)
   236  	assert.Equal(t, len(items), 2)
   237  	assert.True(t, itemInList(items, "query"))
   238  	assert.True(t, itemInList(items, "query:query"))
   239  
   240  	// test at the beginning of if statement
   241  	items, err = handler.getCompletionItemsList(ctx, completionStmtURI, lsp.Position{Line: 9, Character: 6})
   242  	assert.Equal(t, nil, err)
   243  	assert.True(t, itemInList(items, "python_library"))
   244  
   245  	// test else statement
   246  	items, err = handler.getCompletionItemsList(ctx, completionStmtURI, lsp.Position{Line: 4, Character: 17})
   247  	assert.Equal(t, nil, err)
   248  	assert.True(t, itemInList(items, "format"))
   249  	assert.True(t, itemInList(items, "find"))
   250  }
   251  
   252  /***************************************
   253   *Tests for Subincludes
   254   ***************************************/
   255  func TestCompletionSubinclude(t *testing.T) {
   256  	ctx := context.Background()
   257  
   258  	// test within if statement
   259  	items, err := handler.getCompletionItemsList(ctx, subincludeURI, lsp.Position{Line: 6, Character: 4})
   260  	assert.Equal(t, nil, err)
   261  	assert.Equal(t, len(items), 1)
   262  	assert.True(t, itemInList(items, "plz_e2e_test"))
   263  }
   264  
   265  /***************************************
   266   *Tests for argument name completion
   267   ***************************************/
   268  func TestCompletionArgNameBuild(t *testing.T) {
   269  	ctx := context.Background()
   270  	analyzer.State.Config.Parse.BuildFileName = []string{"completion2.build", "BUILD"}
   271  
   272  	// test completion for a "visibility" arg
   273  	items, err := handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 28, Character: 6})
   274  	assert.Equal(t, nil, err)
   275  	assert.Equal(t, 1, len(items))
   276  
   277  	items, err = handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 29, Character: 6})
   278  	assert.Equal(t, nil, err)
   279  	assert.Equal(t, 0, len(items))
   280  
   281  	items, err = handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 30, Character: 6})
   282  	assert.Equal(t, nil, err)
   283  	assert.Equal(t, 2, len(items))
   284  	assert.True(t, itemInList(items, "filter_srcs="))
   285  	assert.True(t, itemInList(items, "asm_srcs="))
   286  
   287  }
   288  
   289  func TestCompletionArgSrcLocalFiles(t *testing.T) {
   290  	ctx := context.Background()
   291  	analyzer.State.Config.Parse.BuildFileName = []string{"completion2.build", "BUILD"}
   292  
   293  	items, err := handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 26, Character: 11})
   294  	assert.Equal(t, nil, err)
   295  	assert.Equal(t, 3, len(items))
   296  	assert.True(t, itemInList(items, "foo.go"))
   297  
   298  	// test completion with non-existent srcs
   299  	items, err = handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 25, Character: 12})
   300  	assert.Equal(t, nil, err)
   301  	assert.Nil(t, items)
   302  
   303  	// test completion with string without ','
   304  	items, err = handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 36, Character: 6})
   305  	assert.Equal(t, nil, err)
   306  	assert.Equal(t, 7, len(items))
   307  	assert.True(t, itemInList(items, "foo.go"))
   308  
   309  	items, err = handler.getCompletionItemsList(ctx, completion2URI, lsp.Position{Line: 42, Character: 15})
   310  	assert.Equal(t, nil, err)
   311  	assert.Equal(t, 2, len(items))
   312  	assert.True(t, itemInList(items, "reformat.build"))
   313  	assert.True(t, itemInList(items, "reformat2.build"))
   314  }
   315  
   316  /***************************************
   317   * Helpers
   318   ***************************************/
   319  func itemInList(itemList []*lsp.CompletionItem, targetLabel string) bool {
   320  	for _, item := range itemList {
   321  		if item.Label == targetLabel {
   322  			return true
   323  		}
   324  	}
   325  	return false
   326  }