Skip to content

Commit

Permalink
[gbc] gbc should reject methods with same name
Browse files Browse the repository at this point in the history
- add test
- functions and events should have unique names
- fixes microsoft#381
  • Loading branch information
lalo committed Mar 30, 2017
1 parent 0ff6ddb commit da07a5a
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ different versioning scheme, following the Haskell community's
reader/writer protocols without having to explicitly compute the full
cross product.
* Add gbc flags to pick which C# files to generate (structs, gRPC, and comm).
* gbc ensures that method names are unique [Issue #381](https://github.com/Microsoft/bond/issues/381)

### C++ ###

Expand Down
15 changes: 11 additions & 4 deletions compiler/src/Language/Bond/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ parseBond ::
-> String -- ^ content of a schema file to parse
-> FilePath -- ^ path of the file being parsed, used to resolve relative import paths
-> ImportResolver -- ^ function to resolve and load imported files
-> IO (Either ParseError Bond) -- ^ function returns 'Bond' which represents the parsed abstract syntax tree
-> IO (Either ParseError Bond) -- ^ function returns 'Bond' which represents the parsed abstract syntax tree
-- or 'ParserError' if parsing failed
parseBond s c f r = runReaderT (runParserT bond (Symbols [] []) s c) (Environment [] [] f r)

Expand Down Expand Up @@ -240,8 +240,9 @@ struct = do
[] -> return fields'
Field {..}:_ -> fail $ "Duplicate definition of the field with ordinal " ++ show fieldOrdinal ++
" and name " ++ show fieldName
where
findDuplicatesBy accessor xs = deleteFirstsBy ((==) `on` accessor) xs (nubBy ((==) `on` accessor) xs)

findDuplicatesBy :: (Eq b) => (a -> b) -> [a] -> [a]
findDuplicatesBy accessor xs = deleteFirstsBy ((==) `on` accessor) xs (nubBy ((==) `on` accessor) xs)

manySortedBy :: (a -> a -> Ordering) -> ParsecT s u m a -> ParsecT s u m [a]
manySortedBy = manyAccum . insertBy
Expand Down Expand Up @@ -410,7 +411,13 @@ service = do
local (with params) $ Service namespaces attr name params <$> methods <* optional semi
where
with params e = e { currentParams = params }
methods = braces $ semiEnd (try event <|> try function)
methods = unique $ braces $ semiEnd (try event <|> try function)
unique p = do
methods' <- p
case findDuplicatesBy methodName methods' of
[] -> return methods'
Function {..}:_ -> fail $ "Duplicate definition of the function with name " ++ show methodName
Event {..}:_ -> fail $ "Duplicate definition of the event with name " ++ show methodName

function :: Parser Method
function = Function <$> attributes <*> payload <*> identifier <*> input
Expand Down
1 change: 1 addition & 0 deletions compiler/tests/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ tests = testGroup "Compiler tests"
, testCase "Enum no default value" $ failBadSyntax "Should fail when an enum field has no default value" "enum_no_default"
, testCase "Alias default value" $ failBadSyntax "Should fail when underlying default value is of the wrong type" "aliases_default"
, testCase "Out of range" $ failBadSyntax "Should fail, out of range for int16" "int_out_of_range"
, testCase "Duplicate method definition in service" $ failBadSyntax "Should fail, method name should be unique" "duplicate_method_service"
]
, testGroup "Codegen"
[ utilTestGroup,
Expand Down
12 changes: 12 additions & 0 deletions compiler/tests/schema/error/duplicate_method_service.bond
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace tests

struct dummy {
0: int32 count;
}

// Invalid service definition with two methods with the same name
service Foo
{
void bar(dummy);
nothing bar();
}

0 comments on commit da07a5a

Please sign in to comment.