@@ -241,6 +241,65 @@ procedure TestVariableEndPosition;
241241 end ;
242242end ;
243243
244+ procedure TestAttributeOverwrite ;
245+ var
246+ Node: TSyntaxNode;
247+ begin
248+ Node := TSyntaxNode.Create(ntMethod);
249+ try
250+ Node.SetAttribute(anName, ' First' );
251+ Node.SetAttribute(anType, ' Kept' );
252+ Node.SetAttribute(anName, ' Second' );
253+ AssertEquals(' Second' , Node.GetAttribute(anName), ' Overwritten attribute.' );
254+ AssertEquals(' Kept' , Node.GetAttribute(anType), ' Other attribute.' );
255+ AssertEquals(2 , Length(Node.Attributes), ' Overwriting must not add an entry.' );
256+ finally
257+ Node.Free;
258+ end ;
259+ end ;
260+
261+ procedure TestAttributeRemove ;
262+ var
263+ Node: TSyntaxNode;
264+ begin
265+ Node := TSyntaxNode.Create(ntMethod);
266+ try
267+ Node.SetAttribute(anName, ' Name' );
268+ Node.SetAttribute(anType, ' Type' );
269+ Node.SetAttribute(anKind, ' Kind' );
270+ Node.SetAttribute(anName, ' ' );
271+ AssertFalse(Node.HasAttribute(anName), ' An empty value removes the attribute.' );
272+ AssertEquals(2 , Length(Node.Attributes), ' Removing must drop the entry.' );
273+ AssertEquals(' Type' , Node.GetAttribute(anType), ' First remaining attribute.' );
274+ AssertEquals(' Kind' , Node.GetAttribute(anKind), ' Second remaining attribute.' );
275+ Node.SetAttribute(anName, ' Again' );
276+ AssertEquals(' Again' , Node.GetAttribute(anName), ' A removed attribute can be set again.' );
277+ AssertEquals(3 , Length(Node.Attributes), ' Setting it again adds one entry.' );
278+ finally
279+ Node.Free;
280+ end ;
281+ end ;
282+
283+ procedure TestRepeatedCallingConvention ;
284+ var
285+ Root, IntfNode: TSyntaxNode;
286+ begin
287+ Root := ParseSource(' unit Example; interface ' +
288+ ' procedure Same(A: Integer); stdcall; stdcall; external '' a.dll'' index 93; ' +
289+ ' procedure Other; stdcall; cdecl; external '' a.dll'' ; implementation end.' );
290+ try
291+ IntfNode := FindDescendant(Root, ntInterface);
292+ AssertNotNil(IntfNode, ' Missing interface' );
293+ AssertEquals(2 , CountDescendants(IntfNode, ntMethod), ' Method count.' );
294+ AssertEquals(' stdcall' , IntfNode.ChildNodes[0 ].GetAttribute(anCallingConvention),
295+ ' A repeated calling convention.' );
296+ AssertEquals(' cdecl' , IntfNode.ChildNodes[1 ].GetAttribute(anCallingConvention),
297+ ' The last of two calling conventions.' );
298+ finally
299+ Root.Free;
300+ end ;
301+ end ;
302+
244303procedure TestInvalidSyntax ;
245304var
246305 Root: TSyntaxNode;
@@ -295,6 +354,9 @@ procedure RunAllTests;
295354 RunTest(' AST.SourcePositions' , TestSourcePositions);
296355 RunTest(' AST.ConstantEndPosition' , TestConstantEndPosition);
297356 RunTest(' AST.VariableEndPosition' , TestVariableEndPosition);
357+ RunTest(' Node.AttributeOverwrite' , TestAttributeOverwrite);
358+ RunTest(' Node.AttributeRemove' , TestAttributeRemove);
359+ RunTest(' AST.RepeatedCallingConvention' , TestRepeatedCallingConvention);
298360 RunTest(' Parser.InvalidSyntax' , TestInvalidSyntax);
299361 { $IFNDEF FPC}
300362 RunTest(' Serialization.BinaryRoundTrip' , TestBinarySerializationRoundTrip);
0 commit comments