diff --git a/languageserver/integration/commands_test.go b/languageserver/integration/commands_test.go index 732e90bf..ba7be099 100644 --- a/languageserver/integration/commands_test.go +++ b/languageserver/integration/commands_test.go @@ -67,7 +67,7 @@ func Test_ExecuteScript(t *testing.T) { {args: []json.RawMessage{[]byte("1"), []byte("2")}, err: "invalid URI argument: 1"}, {args: []json.RawMessage{locationURL, []byte("3")}, err: "invalid script arguments: 3"}, {args: []json.RawMessage{locationURL, invalidCadenceArg}, err: "invalid script arguments cadence encoding format: {foo}, error: invalid character 'f' looking for beginning of object key string"}, - {args: []json.RawMessage{locationURL, invalidCadenceValue}, err: `invalid script arguments cadence encoding format: [{ "type": "Bool", "value": "we are the knights who say niii" }], error: failed to decode value: invalid JSON Cadence structure`}, + {args: []json.RawMessage{locationURL, invalidCadenceValue}, err: `invalid script arguments cadence encoding format: [{ "type": "Bool", "value": "we are the knights who say niii" }], error: failed to decode JSON-Cadence value: expected JSON bool, got we are the knights who say niii`}, }) t.Run("successful script execution with arguments", func(t *testing.T) { diff --git a/languageserver/integration/contracts.go b/languageserver/integration/contracts.go index 82f6e601..37adbe76 100644 --- a/languageserver/integration/contracts.go +++ b/languageserver/integration/contracts.go @@ -45,7 +45,7 @@ type contractInfo struct { startPos *ast.Position kind contractKind name string - parameters []*sema.Parameter + parameters []sema.Parameter pragmaArgumentStrings []string pragmaArguments [][]Argument pragmaSignersNames []string @@ -65,7 +65,7 @@ func (c *contractInfo) update(uri protocol.DocumentURI, version int32, checker * c.name = contractDeclaration.Identifier.String() c.startPos = &contractDeclaration.StartPos c.kind = contractTypeDeclaration - contractType := checker.Elaboration.CompositeDeclarationTypes[contractDeclaration] + contractType := checker.Elaboration.CompositeDeclarationType(contractDeclaration) c.parameters = contractType.ConstructorParameters } else if contractInterfaceDeclaration != nil { docString = contractInterfaceDeclaration.DocString diff --git a/languageserver/integration/contracts_test.go b/languageserver/integration/contracts_test.go index cf49d9db..a9bd919e 100644 --- a/languageserver/integration/contracts_test.go +++ b/languageserver/integration/contracts_test.go @@ -34,6 +34,7 @@ import ( ) func Test_ContractUpdate(t *testing.T) { + const code = ` /// pragma signers Alice pub contract HelloWorld { @@ -47,8 +48,9 @@ func Test_ContractUpdate(t *testing.T) { self.greeting = a } } - ` - program, err := parser.ParseProgram([]byte(code), nil) + ` + + program, err := parser.ParseProgram(nil, []byte(code), parser.Config{}) require.NoError(t, err) location := common.StringLocation("foo") diff --git a/languageserver/integration/entrypoint.go b/languageserver/integration/entrypoint.go index 04050eea..52c52282 100644 --- a/languageserver/integration/entrypoint.go +++ b/languageserver/integration/entrypoint.go @@ -49,7 +49,7 @@ type entryPointInfo struct { documentVersion int32 startPos *ast.Position kind entryPointKind - parameters []*sema.Parameter + parameters []sema.Parameter pragmaArgumentStrings []string pragmaArguments [][]Argument // todo can we refactor into a 1D list pragmaSignerNames []string @@ -67,14 +67,14 @@ func (e *entryPointInfo) update(uri protocol.DocumentURI, version int32, checker if transactionDeclaration != nil { docString = transactionDeclaration.DocString - transactionType := checker.Elaboration.TransactionDeclarationTypes[transactionDeclaration] + transactionType := checker.Elaboration.TransactionDeclarationType(transactionDeclaration) e.startPos = &transactionDeclaration.StartPos e.kind = entryPointKindTransaction e.parameters = transactionType.Parameters e.numberOfSigners = len(transactionType.PrepareParameters) } else if functionDeclaration != nil { docString = functionDeclaration.DocString - functionType := checker.Elaboration.FunctionDeclarationFunctionTypes[functionDeclaration] + functionType := checker.Elaboration.FunctionDeclarationFunctionType(functionDeclaration) e.startPos = &functionDeclaration.StartPos e.kind = entryPointKindScript e.parameters = functionType.Parameters @@ -125,7 +125,6 @@ func (e *entryPointInfo) update(uri protocol.DocumentURI, version int32, checker // codelens shows an execute button when there is exactly one valid entry point // (valid script function or transaction declaration) and no other actionable declarations. -// func (e *entryPointInfo) codelens(client flowClient) []*protocol.CodeLens { if e.kind == entryPointKindUnknown || e.startPos == nil { return nil diff --git a/languageserver/integration/entrypoint_test.go b/languageserver/integration/entrypoint_test.go index f1344c24..b61835f6 100644 --- a/languageserver/integration/entrypoint_test.go +++ b/languageserver/integration/entrypoint_test.go @@ -37,7 +37,7 @@ import ( ) func buildEntrypoint(t *testing.T, code string) entryPointInfo { - program, err := parser.ParseProgram([]byte(code), nil) + program, err := parser.ParseProgram(nil, []byte(code), parser.Config{}) require.NoError(t, err) location := common.StringLocation("foo") diff --git a/languageserver/server/parameter.go b/languageserver/server/parameter.go index 4acdf2aa..7c031df1 100644 --- a/languageserver/server/parameter.go +++ b/languageserver/server/parameter.go @@ -29,7 +29,7 @@ type Parameter struct { Type string `json:"type"` } -func encodeParameters(parameters []*sema.Parameter) []Parameter { +func encodeParameters(parameters []sema.Parameter) []Parameter { encodedParameters := make([]Parameter, len(parameters)) diff --git a/languageserver/server/server.go b/languageserver/server/server.go index 6223fa29..37c409bc 100644 --- a/languageserver/server/server.go +++ b/languageserver/server/server.go @@ -1399,7 +1399,7 @@ func (s *Server) prepareFunctionMemberCompletionItem( func (s *Server) prepareParametersCompletionItem( item *protocol.CompletionItem, name string, - parameters []*sema.Parameter, + parameters []sema.Parameter, ) { item.InsertTextFormat = protocol.SnippetTextFormat @@ -1706,7 +1706,7 @@ func (s *Server) InlayHint( }) for _, variableDeclaration := range variableDeclarations { - targetType := checker.Elaboration.VariableDeclarationTypes[variableDeclaration].TargetType + targetType := checker.Elaboration.VariableDeclarationTypes(variableDeclaration).TargetType if targetType == nil { // bugfix getting nil target continue // todo this should never occur } @@ -1934,7 +1934,7 @@ func parse(code, location string, log func(*protocol.LogMessageParams)) (*ast.Pr defer sentry.RecoverWithContext(ctx) start := time.Now() - program, err := parser.ParseProgram([]byte(code), nil) + program, err := parser.ParseProgram(nil, []byte(code), parser.Config{}) elapsed := time.Since(start) log(&protocol.LogMessageParams{ @@ -1976,7 +1976,7 @@ func (s *Server) resolveImport(location common.Location) (program *ast.Program, return nil, err } - return parser.ParseProgram([]byte(code), nil) + return parser.ParseProgram(nil, []byte(code), parser.Config{}) } func (s *Server) GetDocument(uri protocol.DocumentURI) (doc Document, ok bool) { @@ -2067,7 +2067,7 @@ func (s *Server) getContractInitializerParameters(args ...json2.RawMessage) (int return []Parameter{}, nil } - compositeType := checker.Elaboration.CompositeDeclarationTypes[compositeDeclaration] + compositeType := checker.Elaboration.CompositeDeclarationType(compositeDeclaration) encodedParameters := encodeParameters(compositeType.ConstructorParameters) @@ -2206,11 +2206,11 @@ func (s *Server) convertError( switch ty := err.Type.(type) { case *sema.CompositeType: declarationGetter = func(elaboration *sema.Elaboration) ast.Declaration { - return elaboration.CompositeTypeDeclarations[ty] + return elaboration.CompositeTypeDeclaration(ty) } case *sema.InterfaceType: declarationGetter = func(elaboration *sema.Elaboration) ast.Declaration { - return elaboration.InterfaceTypeDeclarations[ty] + return elaboration.InterfaceTypeDeclaration(ty) } } @@ -2492,7 +2492,7 @@ func formatNewMember(member *sema.Member, indentation string) string { var returnType string returnTypeAnnotation := functionType.ReturnTypeAnnotation - if returnTypeAnnotation != nil && returnTypeAnnotation.Type != sema.VoidType { + if returnTypeAnnotation.Type != nil && returnTypeAnnotation.Type != sema.VoidType { returnType = fmt.Sprintf(": %s", returnTypeAnnotation.QualifiedString()) } @@ -2556,8 +2556,9 @@ func (s *Server) maybeAddDeclarationActionsResolver( case *ast.InvocationExpression: isInvoked = parent.InvokedExpression == errorExpression - invocationArgumentTypes = checker.Elaboration.InvocationExpressionTypes[parent].ArgumentTypes - invocationReturnType = checker.Elaboration.InvocationExpressionTypes[parent].ReturnType + invocationExpressionTypes := checker.Elaboration.InvocationExpressionTypes(parent) + invocationArgumentTypes = invocationExpressionTypes.ArgumentTypes + invocationReturnType = invocationExpressionTypes.ReturnType invocationArgumentLabels = make([]string, 0, len(parent.Arguments)) for _, argument := range parent.Arguments { @@ -2652,7 +2653,7 @@ func (s *Server) maybeAddDeclarationActionsResolver( insertionPos = memberInsertionPosGetter(checker, false) memberExpression := errorExpression.(*ast.MemberExpression) - expectedType := checker.Elaboration.MemberExpressionExpectedTypes[memberExpression] + expectedType := checker.Elaboration.MemberExpressionExpectedType(memberExpression) var typeString string if expectedType != nil { @@ -2785,9 +2786,10 @@ func (s *Server) handleImport( error, ) { switch importedLocation { - case stdlib.CryptoChecker.Location: + case stdlib.CryptoCheckerLocation: + cryptoChecker := stdlib.CryptoChecker() return sema.ElaborationImport{ - Elaboration: stdlib.CryptoChecker.Elaboration, + Elaboration: cryptoChecker.Elaboration, }, nil default: diff --git a/languageserver/server/stdlib.go b/languageserver/server/stdlib.go index 14d4ec09..eeedec80 100644 --- a/languageserver/server/stdlib.go +++ b/languageserver/server/stdlib.go @@ -30,12 +30,7 @@ type standardLibrary struct { baseValueActivation *sema.VariableActivation } -var _ stdlib.Logger = standardLibrary{} -var _ stdlib.UnsafeRandomGenerator = standardLibrary{} -var _ stdlib.BlockAtHeightProvider = standardLibrary{} -var _ stdlib.CurrentBlockProvider = standardLibrary{} -var _ stdlib.PublicAccountHandler = standardLibrary{} -var _ stdlib.AccountCreator = standardLibrary{} +var _ stdlib.StandardLibraryHandler = standardLibrary{} func (standardLibrary) ProgramLog(_ string) error { // Implementation should never be called, @@ -205,24 +200,59 @@ func (standardLibrary) CreateAccount(_ common.Address) (address common.Address, panic(errors.NewUnreachableError()) } -func newStandardLibrary() (result standardLibrary) { - // TODO: either: - // - use runtime's script environment. requires it to become more configurable - // - separate out stdlib definitions from script environment, and use them here instead +func (standardLibrary) ValidatePublicKey(_ *stdlib.PublicKey) error { + // Implementation should never be called, + // only its definition is used for type-checking + panic(errors.NewUnreachableError()) +} + +func (standardLibrary) VerifySignature( + _ []byte, + _ string, + _ []byte, + _ []byte, + _ sema.SignatureAlgorithm, + _ sema.HashAlgorithm, +) (bool, error) { + // Implementation should never be called, + // only its definition is used for type-checking + panic(errors.NewUnreachableError()) +} + +func (standardLibrary) BLSVerifyPOP(_ *stdlib.PublicKey, _ []byte) (bool, error) { + // Implementation should never be called, + // only its definition is used for type-checking + panic(errors.NewUnreachableError()) +} +func (standardLibrary) Hash(_ []byte, _ string, _ sema.HashAlgorithm) ([]byte, error) { + // Implementation should never be called, + // only its definition is used for type-checking + panic(errors.NewUnreachableError()) +} + +func (standardLibrary) AccountKeysCount(_ common.Address) (uint64, error) { + // Implementation should never be called, + // only its definition is used for type-checking + panic(errors.NewUnreachableError()) +} + +func (standardLibrary) BLSAggregatePublicKeys(_ []*stdlib.PublicKey) (*stdlib.PublicKey, error) { + // Implementation should never be called, + // only its definition is used for type-checking + panic(errors.NewUnreachableError()) +} + +func (standardLibrary) BLSAggregateSignatures(_ [][]byte) ([]byte, error) { + // Implementation should never be called, + // only its definition is used for type-checking + panic(errors.NewUnreachableError()) +} + +func newStandardLibrary() (result standardLibrary) { result.baseValueActivation = sema.NewVariableActivation(sema.BaseValueActivation) - for _, valueDeclaration := range append( - stdlib.BuiltinValues[:], - stdlib.NewLogFunction(result), - stdlib.NewUnsafeRandomFunction(result), - stdlib.NewGetBlockFunction(result), - stdlib.NewGetCurrentBlockFunction(result), - stdlib.NewGetAccountFunction(result), - stdlib.NewAuthAccountConstructor(result), - stdlib.NewGetAuthAccountFunction(result), - ) { + for _, valueDeclaration := range stdlib.DefaultStandardLibraryValues(result) { result.baseValueActivation.DeclareValue(valueDeclaration) } - return }