diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 0ec0eb0cc..b408681c7 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -58,11 +58,19 @@ void ContractDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError( "Non-empty \"returns\" directive for constructor.")); - FunctionDefinition const* fallbackFunction = getFallbackFunction(); - if (fallbackFunction && fallbackFunction->getScope() == this && !fallbackFunction->getParameters().empty()) - BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError( - "Fallback function cannot take parameters.")); - + FunctionDefinition const* fallbackFunction = nullptr; + for (ASTPointer const& function: getDefinedFunctions()) + if (function->getName().empty()) + { + if (fallbackFunction) + BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Only one fallback function is allowed.")); + else + { + fallbackFunction = function.get(); + if (!fallbackFunction->getParameters().empty()) + BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError("Fallback function cannot take parameters.")); + } + } for (ASTPointer const& modifier: getFunctionModifiers()) modifier->checkTypeRequirements(); @@ -478,7 +486,7 @@ void FunctionCall::checkTypeRequirements() if (m_arguments.size() != 1) BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion.")); if (!m_names.empty()) - BOOST_THROW_EXCEPTION(createTypeError("Type conversion can't allow named arguments.")); + BOOST_THROW_EXCEPTION(createTypeError("Type conversion cannot allow named arguments.")); if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType())) BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed.")); m_type = type.getActualType(); @@ -489,28 +497,29 @@ void FunctionCall::checkTypeRequirements() // and then ask if that is implicitly convertible to the struct represented by the // function parameters TypePointers const& parameterTypes = functionType->getParameterTypes(); - if (parameterTypes.size() != m_arguments.size()) + if (functionType->getLocation() != FunctionType::Location::SHA3 && parameterTypes.size() != m_arguments.size()) BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); if (m_names.empty()) { for (size_t i = 0; i < m_arguments.size(); ++i) - if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) - BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); + if (functionType->getLocation() != FunctionType::Location::SHA3 && + !m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) + BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Invalid type for argument in function call.")); } else { + if (functionType->getLocation() == FunctionType::Location::SHA3) + BOOST_THROW_EXCEPTION(createTypeError("Named arguments cannnot be used for SHA3.")); auto const& parameterNames = functionType->getParameterNames(); if (parameterNames.size() != m_names.size()) BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing.")); // check duplicate names - for (size_t i = 0; i < m_names.size(); i++) { - for (size_t j = i + 1; j < m_names.size(); j++) { + for (size_t i = 0; i < m_names.size(); i++) + for (size_t j = i + 1; j < m_names.size(); j++) if (*m_names[i] == *m_names[j]) - BOOST_THROW_EXCEPTION(createTypeError("Duplicate named argument.")); - } - } + BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Duplicate named argument.")); for (size_t i = 0; i < m_names.size(); i++) { bool found = false; @@ -525,7 +534,7 @@ void FunctionCall::checkTypeRequirements() } } if (!found) - BOOST_THROW_EXCEPTION(createTypeError("Named argument doesn't match function declaration.")); + BOOST_THROW_EXCEPTION(createTypeError("Named argument does not match function declaration.")); } } diff --git a/libsolidity/AST.h b/libsolidity/AST.h old mode 100755 new mode 100644 index 47f2a40ca..98f28afb0 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -250,7 +250,7 @@ public: /// Returns the constructor or nullptr if no constructor was specified. FunctionDefinition const* getConstructor() const; - /// Returns the fallback function or nullptr if no constructor was specified. + /// Returns the fallback function or nullptr if no fallback function was specified. FunctionDefinition const* getFallbackFunction() const; private: diff --git a/libsolidity/DeclarationContainer.cpp b/libsolidity/DeclarationContainer.cpp index c7081bc78..2e810a4cf 100644 --- a/libsolidity/DeclarationContainer.cpp +++ b/libsolidity/DeclarationContainer.cpp @@ -30,6 +30,9 @@ namespace solidity bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _update) { + if (_declaration.getName().empty()) + return true; + if (!_update && m_declarations.find(_declaration.getName()) != m_declarations.end()) return false; m_declarations[_declaration.getName()] = &_declaration; @@ -38,6 +41,7 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, Declaration const* DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const { + solAssert(!_name.empty(), "Attempt to resolve empty name."); auto result = m_declarations.find(_name); if (result != m_declarations.end()) return result->second; diff --git a/libsolidity/DeclarationContainer.h b/libsolidity/DeclarationContainer.h index e4b793259..1216fcef2 100644 --- a/libsolidity/DeclarationContainer.h +++ b/libsolidity/DeclarationContainer.h @@ -42,8 +42,8 @@ public: explicit DeclarationContainer(Declaration const* _enclosingDeclaration = nullptr, DeclarationContainer const* _enclosingContainer = nullptr): m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {} - /// Registers the declaration in the scope unless its name is already declared. - /// @returns true iff it was not yet declared. + /// Registers the declaration in the scope unless its name is already declared or the name is empty. + /// @returns false if the name was already declared. bool registerDeclaration(Declaration const& _declaration, bool _update = false); Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const; Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; } diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index f0c3af226..5561af9b3 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -206,7 +206,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) TypePointers const& parameterTypes = function.getParameterTypes(); vector> const& callArguments = _functionCall.getArguments(); vector> const& callArgumentNames = _functionCall.getNames(); - solAssert(callArguments.size() == parameterTypes.size(), ""); + if (function.getLocation() != Location::SHA3) + solAssert(callArguments.size() == parameterTypes.size(), ""); vector> arguments; if (callArgumentNames.empty()) @@ -274,7 +275,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << u256(0) << eth::Instruction::CODECOPY; unsigned length = bytecode.size(); - length += appendArgumentCopyToMemory(function.getParameterTypes(), arguments, length); + length += appendArgumentsCopyToMemory(arguments, function.getParameterTypes(), length); // size, offset, endowment m_context << u256(length) << u256(0); if (function.valueSet()) @@ -325,9 +326,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << eth::Instruction::SUICIDE; break; case Location::SHA3: - appendExpressionCopyToMemory(*function.getParameterTypes().front(), *arguments.front()); - m_context << u256(32) << u256(0) << eth::Instruction::SHA3; + { + unsigned length = appendArgumentsCopyToMemory(arguments, TypePointers(), 0, false); + m_context << u256(length) << u256(0) << eth::Instruction::SHA3; break; + } case Location::LOG0: case Location::LOG1: case Location::LOG2: @@ -797,7 +800,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio // reserve space for the function identifier unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset; - dataOffset += appendArgumentCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset); + dataOffset += appendArgumentsCopyToMemory(_arguments, _functionType.getParameterTypes(), dataOffset); //@todo only return the first return value for now Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : @@ -833,28 +836,34 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio } } -unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _types, - vector> const& _arguments, - unsigned _memoryOffset) +unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vector> const& _arguments, + TypePointers const& _types, + unsigned _memoryOffset, + bool _padToWordBoundaries) { + solAssert(_types.empty() || _types.size() == _arguments.size(), ""); unsigned length = 0; - for (unsigned i = 0; i < _arguments.size(); ++i) - length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); + for (size_t i = 0; i < _arguments.size(); ++i) + { + _arguments[i]->accept(*this); + TypePointer const& expectedType = _types.empty() ? _arguments[i]->getType()->getRealType() : _types[i]; + appendTypeConversion(*_arguments[i]->getType(), *expectedType, true); + length += appendTypeMoveToMemory(*expectedType, _arguments[i]->getLocation(), + _memoryOffset + length, _padToWordBoundaries); + } return length; } -unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, - Location const& _location, unsigned _memoryOffset) +unsigned ExpressionCompiler::appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries) { - appendTypeConversion(_type, _expectedType, true); - unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); + unsigned const c_encodedSize = _type.getCalldataEncodedSize(); + unsigned const c_numBytes = _padToWordBoundaries ? CompilerUtils::getPaddedSize(c_encodedSize) : c_encodedSize; if (c_numBytes == 0 || c_numBytes > 32) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) - << errinfo_comment("Type " + _expectedType.toString() + " not yet supported.")); - bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; - bool const c_padToWords = true; - return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords); + << errinfo_comment("Type " + _type.toString() + " not yet supported.")); + bool const c_leftAligned = _type.getCategory() == Type::Category::STRING; + return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, _padToWordBoundaries); } unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, @@ -862,7 +871,8 @@ unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedT unsigned _memoryOffset) { _expression.accept(*this); - return appendTypeConversionAndMoveToMemory(_expectedType, *_expression.getType(), _expression.getLocation(), _memoryOffset); + appendTypeConversion(*_expression.getType(), _expectedType, true); + return appendTypeMoveToMemory(_expectedType, _expression.getLocation(), _memoryOffset); } void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) @@ -870,20 +880,20 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& FunctionType accessorType(_varDecl); unsigned length = 0; - TypePointers const& params = accessorType.getParameterTypes(); + TypePointers const& paramTypes = accessorType.getParameterTypes(); // move arguments to memory - for (TypePointer const& param: boost::adaptors::reverse(params)) - length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length); + for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes)) + length += appendTypeMoveToMemory(*paramType, Location(), length); // retrieve the position of the variable m_context << m_context.getStorageLocationOfVariable(_varDecl); TypePointer returnType = _varDecl.getType(); - for (TypePointer const& param: params) + for (TypePointer const& paramType: paramTypes) { // move offset to memory CompilerUtils(m_context).storeInMemory(length); - unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize()); + unsigned argLen = CompilerUtils::getPaddedSize(paramType->getCalldataEncodedSize()); length -= argLen; m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 7de577e6c..adfe8e524 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -92,17 +92,18 @@ private: /// Appends code to call a function of the given type with the given arguments. void appendExternalFunctionCall(FunctionType const& _functionType, std::vector> const& _arguments, bool bare = false); - /// Appends code that copies the given arguments to memory (with optional offset). - /// @returns the number of bytes copied to memory - unsigned appendArgumentCopyToMemory(TypePointers const& _types, - std::vector> const& _arguments, - unsigned _memoryOffset = 0); - /// Appends code that copies a type to memory. - /// @returns the number of bytes copied to memory - unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, - Location const& _location, unsigned _memoryOffset = 0); - /// Appends code that evaluates a single expression and copies it to memory (with optional offset). - /// @returns the number of bytes copied to memory + /// Appends code that evaluates the given arguments and moves the result to memory (with optional offset). + /// @returns the number of bytes moved to memory + unsigned appendArgumentsCopyToMemory(std::vector> const& _arguments, + TypePointers const& _types = {}, + unsigned _memoryOffset = 0, + bool _padToWordBoundaries = true); + /// Appends code that moves a stack element of the given type to memory + /// @returns the number of bytes moved to memory + unsigned appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, + bool _padToWordBoundaries = true); + /// Appends code that evaluates a single expression and moves the result to memory (with optional offset). + /// @returns the number of bytes moved to memory unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, unsigned _memoryOffset = 0); diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index d8c15c36d..c4bb54829 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -180,7 +180,7 @@ ASTPointer Parser::parseInheritanceSpecifier() Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token) { - Declaration::Visibility visibility = Declaration::Visibility::DEFAULT; + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); if (_token == Token::PUBLIC) visibility = Declaration::Visibility::PUBLIC; else if (_token == Token::PROTECTED) @@ -267,20 +267,31 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp { ASTNodeFactory nodeFactory(*this); ASTPointer type = parseTypeName(_options.allowVar); + if (type != nullptr) + nodeFactory.setEndPositionFromNode(type); bool isIndexed = false; + ASTPointer identifier; Token::Value token = m_scanner->getCurrentToken(); + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); + if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) + visibility = parseVisibilitySpecifier(token); if (_options.allowIndexed && token == Token::INDEXED) { isIndexed = true; m_scanner->next(); } - Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); - if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) - visibility = parseVisibilitySpecifier(token); nodeFactory.markEndPosition(); - return nodeFactory.createNode(type, expectIdentifierToken(), - visibility, _options.isStateVariable, - isIndexed); + if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::IDENTIFIER) + { + identifier = make_shared(""); + solAssert(type != nullptr, ""); + nodeFactory.setEndPositionFromNode(type); + } + else + identifier = expectIdentifierToken(); + return nodeFactory.createNode(type, identifier, + visibility, _options.isStateVariable, + isIndexed); } ASTPointer Parser::parseModifierDefinition() @@ -402,6 +413,7 @@ ASTPointer Parser::parseParameterList(bool _allowEmpty, bool _all vector> parameters; VarDeclParserOptions options; options.allowIndexed = _allowIndexed; + options.allowEmptyName = true; expectToken(Token::LPAREN); if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN) { diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 19e0af1aa..5816fec40 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -50,6 +50,7 @@ private: bool allowVar = false; bool isStateVariable = false; bool allowIndexed = false; + bool allowEmptyName = false; }; ///@{ diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index b283ca10e..6a8ecd9dc 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -458,10 +458,7 @@ void Scanner::scanToken() // - -- -= advance(); if (m_char == '-') - { - advance(); - token = Token::DEC; - } + token = selectToken(Token::DEC); else if (m_char == '=') token = selectToken(Token::ASSIGN_SUB); else diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index e6f1e8e1c..f30085ec2 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -357,6 +357,13 @@ u256 IntegerConstantType::literalValue(Literal const*) const return value; } +TypePointer IntegerConstantType::getRealType() const +{ + auto intType = getIntegerType(); + solAssert(!!intType, "getRealType called with invalid integer constant " + toString()); + return intType; +} + shared_ptr IntegerConstantType::getIntegerType() const { bigint value = m_value; diff --git a/libsolidity/Types.h b/libsolidity/Types.h index fcc77fea9..80a777942 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -130,6 +130,8 @@ public: /// i.e. it behaves differently in lvalue context and in value context. virtual bool isValueType() const { return false; } virtual unsigned getSizeOnStack() const { return 1; } + /// @returns the real type of some types, like e.g: IntegerConstant + virtual TypePointer getRealType() const { return shared_from_this(); } /// Returns the list of all members of this type. Default implementation: no members. virtual MemberList const& getMembers() const { return EmptyMemberList; } @@ -140,7 +142,7 @@ public: virtual u256 literalValue(Literal const*) const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested " - "for type without literals.")); + "for type without literals.")); } protected: @@ -213,6 +215,7 @@ public: virtual std::string toString() const override; virtual u256 literalValue(Literal const* _literal) const override; + virtual TypePointer getRealType() const override; /// @returns the smallest integer type that can hold the value or an empty pointer if not possible. std::shared_ptr getIntegerType() const; diff --git a/libsolidity/Utils.h b/libsolidity/Utils.h old mode 100755 new mode 100644 diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index e18b23ab3..602940078 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -236,8 +236,8 @@ void ClientModel::executeSequence(std::vector const& _seque } if (!f) BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString())); - - encoder.encode(f); + if (!transaction.functionId.isEmpty()) + encoder.encode(f); for (int p = 0; p < transaction.parameterValues.size(); p++) { if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type()) @@ -247,6 +247,8 @@ void ClientModel::executeSequence(std::vector const& _seque if (transaction.functionId.isEmpty()) { + bytes param = encoder.encodedData(); + contractCode.insert(contractCode.end(), param.begin(), param.end()); Address newAddress = deployContract(contractCode, transaction); if (newAddress != m_contractAddress) { diff --git a/mix/qml/FilesSection.qml b/mix/qml/FilesSection.qml index d532fb2b1..32202f839 100644 --- a/mix/qml/FilesSection.qml +++ b/mix/qml/FilesSection.qml @@ -54,6 +54,12 @@ ColumnLayout { source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf" } + FontLoader + { + id: boldFont + source: "qrc:/qml/fonts/SourceSansPro-Bold.ttf" + } + RowLayout { anchors.top: parent.top @@ -64,12 +70,12 @@ ColumnLayout { Image { source: "qrc:/qml/img/opentriangleindicator_filesproject.png" width: 15 - sourceSize.width: 15 + sourceSize.width: 12 id: imgArrow anchors.right: section.left - anchors.rightMargin: 5 + anchors.rightMargin: 8 anchors.top: parent.top - anchors.topMargin: 8 + anchors.topMargin: 6 } Text @@ -79,10 +85,8 @@ ColumnLayout { anchors.left: parent.left anchors.leftMargin: Style.general.leftMargin color: Style.documentsList.sectionColor - font.family: fileNameFont.name - font.pointSize: Style.documentsList.fontSize - font.weight: Font.Bold - font.letterSpacing: 1 + font.family: boldFont.name + font.pointSize: Style.documentsList.sectionFontSize states: [ State { name: "hidden" @@ -154,6 +158,9 @@ ColumnLayout { rootItem.isSelected = true; else rootItem.isSelected = false; + + if (rootItem.isSelected && section.state === "hidden") + section.state = ""; } } } diff --git a/mix/qml/ProjectList.qml b/mix/qml/ProjectList.qml index 65eebcdbb..138e86fe9 100644 --- a/mix/qml/ProjectList.qml +++ b/mix/qml/ProjectList.qml @@ -15,7 +15,7 @@ Item { FontLoader { id: srcSansProLight - source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf" + source: "qrc:/qml/fonts/SourceSansPro-Light.ttf" } Rectangle @@ -54,6 +54,7 @@ Item { font.family: srcSansProLight.name font.pointSize: Style.title.pointSize anchors.verticalCenter: parent.verticalCenter + font.weight: Font.Light } } @@ -79,7 +80,7 @@ Item { spacing: 0 Repeater { - model: ["Contracts", "Javascript", "HTML", "Styles", "Images", "Misc"] + model: [qsTr("Contracts"), qsTr("Javascript"), qsTr("Web Pages"), qsTr("Styles"), qsTr("Images"), qsTr("Misc")]; signal selected(string doc, string groupName) id: sectionRepeater FilesSection @@ -127,6 +128,15 @@ Item { } } + onDocumentOpened: { + if (document.groupName === modelData) + sectionRepeater.selected(document.documentId, modelData); + } + + onNewProject: { + sectionModel.clear(); + } + onProjectLoaded: { addDocToSubModel(); if (modelData === "Contracts") @@ -141,7 +151,12 @@ Item { { var newDoc = projectModel.getDocument(documentId); if (newDoc.groupName === modelData) + { sectionModel.append(newDoc); + projectModel.openDocument(newDoc.documentId); + sectionRepeater.selected(newDoc.documentId, modelData); + } + } } } diff --git a/mix/qml/Style.qml b/mix/qml/Style.qml index 91745749f..348d8c4d1 100644 --- a/mix/qml/Style.qml +++ b/mix/qml/Style.qml @@ -12,7 +12,7 @@ QtObject { property QtObject title: QtObject { property string color: "#808080" property string background: "#f0f0f0" - property int height: 70 + property int height: 55 property int pointSize: 18 } @@ -22,8 +22,9 @@ QtObject { property string sectionColor: "#808080" property string selectedColor: "white" property string highlightColor: "#4a90e2" - property int height: 32 - property int fileNameHeight: 45 - property int fontSize: 15 + property int height: 25 + property int fileNameHeight: 30 + property int fontSize: 13 + property int sectionFontSize: 13 } } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 4d50db7b1..3e6cf0236 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -60,15 +60,39 @@ Window { else { var parameters = codeModel.code.contract.constructor.parameters; - for (var p = 0; p < parameters.length; p++) { - var pname = parameters[p].name; - paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" }); - } + for (var p = 0; p < parameters.length; p++) + loadParameter(parameters[p]); } visible = true; valueField.focus = true; } + function loadParameter(parameter) + { + var type = parameter.type; + var pname = parameter.name; + var varComponent; + + if (type.indexOf("int") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); + else if (type.indexOf("real") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); + else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); + else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + else if (type.indexOf("bool") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); + + var param = varComponent.createObject(modalTransactionDialog); + var value = itemParams[pname] !== undefined ? itemParams[pname] : ""; + + param.setValue(value); + param.setDeclaration(parameter); + qType.push({ name: pname, value: param }); + paramsModel.append({ name: pname, type: type, value: value }); + } + function loadParameters() { paramsModel.clear(); if (!paramsModel) @@ -76,30 +100,8 @@ Window { if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { var func = codeModel.code.contract.functions[functionComboBox.currentIndex]; var parameters = func.parameters; - for (var p = 0; p < parameters.length; p++) { - var pname = parameters[p].name; - var varComponent; - var type = parameters[p].type; - - if (type.indexOf("int") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); - else if (type.indexOf("real") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); - else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); - else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); - else if (type.indexOf("bool") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); - - var param = varComponent.createObject(modalTransactionDialog); - var value = itemParams[pname] !== undefined ? itemParams[pname] : ""; - - param.setValue(value); - param.setDeclaration(parameters[p]); - qType.push({ name: pname, value: param }); - paramsModel.append({ name: pname, type: parameters[p].type, value: value }); - } + for (var p = 0; p < parameters.length; p++) + loadParameter(parameters[p]); } } diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index 19a56432e..ac44dffa9 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -90,7 +90,7 @@ function addFile(fileName) { var isJs = extension === ".js"; var isImg = extension === ".png" || extension === ".gif" || extension === ".jpg" || extension === ".svg"; var syntaxMode = isContract ? "solidity" : isJs ? "javascript" : isHtml ? "htmlmixed" : isCss ? "css" : ""; - var groupName = isContract ? "Contracts" : isJs ? "Javascript" : isHtml ? "HTML" : isCss ? "Styles" : isImg ? "Images" : "Misc"; + var groupName = isContract ? qsTr("Contracts") : isJs ? qsTr("Javascript") : isHtml ? qsTr("Web Pages") : isCss ? qsTr("Styles") : isImg ? qsTr("Images") : qsTr("Misc"); var docData = { contract: false, path: p, diff --git a/test/SolidityABIJSON.cpp b/test/SolidityABIJSON.cpp index 13e65761f..d600340eb 100644 --- a/test/SolidityABIJSON.cpp +++ b/test/SolidityABIJSON.cpp @@ -409,7 +409,78 @@ BOOST_AUTO_TEST_CASE(inherited) checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) +{ + char const* sourceCode = R"( + contract test { + function f(uint, uint k) returns(uint ret_k, uint ret_g){ + uint g = 8; + ret_k = k; + ret_g = g; + } + })"; + + char const* interface = R"([ + { + "name": "f", + "constant": false, + "type": "function", + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "k", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "ret_k", + "type": "uint256" + }, + { + "name": "ret_g", + "type": "uint256" + } + ] + } + ])"; + checkInterface(sourceCode, interface); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter) +{ + char const* sourceCode = R"( + contract test { + function f(uint k) returns(uint){ + return k; + } + })"; + + char const* interface = R"([ + { + "name": "f", + "constant": false, + "type": "function", + "inputs": [ + { + "name": "k", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + } + ])"; + checkInterface(sourceCode, interface); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 301cc06ef..5bd1e8578 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -576,7 +576,7 @@ BOOST_AUTO_TEST_CASE(simple_mapping) " }\n" "}"; compileAndRun(sourceCode); - + BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00))); BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x00))); BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); @@ -933,7 +933,7 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); - BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(toBigEndian(u256(123))))); + BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(bytes({0x7b})))); BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337)))); BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); } @@ -2113,6 +2113,94 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data) BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); } +BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) +{ + char const* sourceCode = R"( + contract test { + function f(uint, uint k) returns(uint ret_k, uint ret_g){ + uint g = 8; + ret_k = k; + ret_g = g; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8)); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8)); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter) +{ + char const* sourceCode = R"( + contract test { + function f(uint k) returns(uint){ + return k; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9)); +} + +BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) +{ + char const* sourceCode = R"( + contract c { + function foo(uint a, uint b, uint c) returns (hash d) + { + d = sha3(a, b, c); + } + })"; + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( + dev::sha3( + toBigEndian(u256(10)) + + toBigEndian(u256(12)) + + toBigEndian(u256(13))))); +} + +BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals) +{ + char const* sourceCode = R"( + contract c { + function foo(uint a, uint16 b) returns (hash d) + { + d = sha3(a, b, 145); + } + })"; + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs( + dev::sha3( + toBigEndian(u256(10)) + + bytes({0x0, 0xc}) + + bytes({0x91})))); +} + +BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals) +{ + char const* sourceCode = R"( + contract c { + function foo() returns (hash d) + { + d = sha3("foo"); + } + function bar(uint a, uint16 b) returns (hash d) + { + d = sha3(a, b, 145, "foo"); + } + })"; + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::sha3("foo"))); + + BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs( + dev::sha3( + toBigEndian(u256(10)) + + bytes({0x0, 0xc}) + + bytes({0x91}) + + bytes({0x66, 0x6f, 0x6f})))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 05ce6ed66..f4be31f4b 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -904,6 +904,48 @@ BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); } +BOOST_AUTO_TEST_CASE(empty_name_input_parameter) +{ + char const* text = R"( + contract test { + function f(uint){ + } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter) +{ + char const* text = R"( + contract test { + function f() returns(bool){ + } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) +{ + char const* text = R"( + contract test { + function f(uint, uint k) returns(uint ret_k){ + return k; + } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) +{ + char const* text = R"( + contract test { + function f() returns(uint ret_k, uint){ + return 5; + } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) { char const* sourceCode = "contract c { function f() { var x = f(); } }";