diff --git a/languageserver/integration/flow.go b/languageserver/integration/flow.go index fa3e6310..372af368 100644 --- a/languageserver/integration/flow.go +++ b/languageserver/integration/flow.go @@ -21,17 +21,17 @@ package integration import ( "context" "fmt" - "github.com/onflow/flow-cli/flowkit/accounts" - "github.com/onflow/flow-cli/flowkit/transactions" "net/url" "os" "path/filepath" "github.com/onflow/cadence" "github.com/onflow/flow-cli/flowkit" + "github.com/onflow/flow-cli/flowkit/accounts" "github.com/onflow/flow-cli/flowkit/config" "github.com/onflow/flow-cli/flowkit/gateway" "github.com/onflow/flow-cli/flowkit/output" + "github.com/onflow/flow-cli/flowkit/transactions" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/crypto" ) @@ -393,23 +393,39 @@ func (f *flowkitClient) createSigner(address flow.Address) (*accounts.Account, e } func (f *flowkitClient) GetCodeByName(name string) (string, error) { - contracts, err := f.state.DeploymentContractsByNetwork(config.EmulatorNetwork) + // Try to find the contract by name + contract, err := f.state.Contracts().ByName(name) if err != nil { - return "", err + return "", fmt.Errorf("couldn't find the contract by import identifier: %s", name) } - for _, contract := range contracts { - if name == contract.Name { - return string(contract.Code()), nil - } + // If no location is set, return an error + if contract.Location == "" { + return "", fmt.Errorf("source file could not be found for import identifier: %s", name) } - return "", fmt.Errorf(fmt.Sprintf("couldn't find the contract by import identifier: %s", name)) + // Resolve the contract source code from file location + code, err := f.getCodeFromLocation(name, contract.Location) + if err != nil { + return "", err + } + return code, nil } // Helpers // +// Helper function to get code from a source file location +func (f *flowkitClient) getCodeFromLocation(name, location string) (string, error) { + dir := filepath.Dir(f.getConfigPath()) + path := filepath.Join(dir, location) + code, err := f.loader.ReadFile(path) + if err != nil { + return "", err + } + return string(code), nil +} + // resolveFilename helper converts the transaction file to a relative location to config file func resolveFilename(configPath string, path string) (string, error) { if filepath.Dir(configPath) == "." { // if flow.json is passed as relative use current dir diff --git a/languageserver/test/a.cdc b/languageserver/test/a.cdc new file mode 100644 index 00000000..434b521f --- /dev/null +++ b/languageserver/test/a.cdc @@ -0,0 +1 @@ +pub contract A {} \ No newline at end of file diff --git a/languageserver/test/flow.json b/languageserver/test/flow.json index 78180465..6640247e 100644 --- a/languageserver/test/flow.json +++ b/languageserver/test/flow.json @@ -7,7 +7,11 @@ }, "contracts": { "Foo": "./foo.cdc", - "Bar": "./bar.cdc" + "Bar": "./bar.cdc", + "A": { + "source": "./a.cdc", + "aliases": {} + } }, "networks": { "emulator": "127.0.0.1:3569", diff --git a/languageserver/test/index.test.ts b/languageserver/test/index.test.ts index 94945b0d..f02bb86a 100644 --- a/languageserver/test/index.test.ts +++ b/languageserver/test/index.test.ts @@ -393,6 +393,23 @@ describe("diagnostics", () => { expect(script.diagnostics).toHaveLength(0) }) + test("script with string import non-deployment contract", async () => { + const scriptName = "script"; + const scriptCode = ` + import "A" + pub fun main() { } + `; + + let docNotifications = await testImports([ + { name: scriptName, code: scriptCode }, + ]); + + let script = await docNotifications.find((n) => n.name == scriptName) + .notification + expect(script.uri).toEqual(`file://${scriptName}.cdc`) + expect(script.diagnostics).toHaveLength(0) + }) + test("script import failure", async() => { const contractName = "foo" const scriptName = "script"