@@ -1256,6 +1256,102 @@ public void TestPreserveCommentsEnabled_CommentInNestedSubquery()
12561256 $ "inner_q alias should appear before outer_q alias. inner_q at { innerQAliasIdx } , outer_q at { outerQAliasIdx } ") ;
12571257 }
12581258
1259+ [ TestMethod ]
1260+ [ Priority ( 0 ) ]
1261+ [ SqlStudioTestCategory ( Category . UnitTest ) ]
1262+ public void TestPreserveCommentsEnabled_SemicolonBeforeTrailingComment ( )
1263+ {
1264+ // Test that semicolons are placed BEFORE trailing single-line comments,
1265+ // not after them (which would make the semicolon part of the comment text).
1266+ // Bug fix: previously "SELECT 1 -- comment;" was generated instead of "SELECT 1; -- comment"
1267+ var sqlWithComments = "SELECT 1 -- trailing comment" ;
1268+ var parser = new TSql170Parser ( true ) ;
1269+ var fragment = parser . Parse ( new StringReader ( sqlWithComments ) , out var errors ) ;
1270+
1271+ Assert . AreEqual ( 0 , errors . Count ) ;
1272+
1273+ var generatorOptions = new SqlScriptGeneratorOptions
1274+ {
1275+ PreserveComments = true ,
1276+ IncludeSemicolons = true
1277+ } ;
1278+ var generator = new Sql170ScriptGenerator ( generatorOptions ) ;
1279+ generator . GenerateScript ( fragment , out var generatedSql ) ;
1280+
1281+ // The semicolon must appear BEFORE the trailing comment
1282+ int semicolonIndex = generatedSql . IndexOf ( ";" ) ;
1283+ int commentIndex = generatedSql . IndexOf ( "-- trailing comment" ) ;
1284+
1285+ Assert . IsTrue ( semicolonIndex >= 0 , "Semicolon should be present in output. Actual: " + generatedSql ) ;
1286+ Assert . IsTrue ( commentIndex >= 0 , "Trailing comment should be preserved. Actual: " + generatedSql ) ;
1287+ Assert . IsTrue ( semicolonIndex < commentIndex ,
1288+ $ "Semicolon should appear before trailing comment. Semicolon at { semicolonIndex } , comment at { commentIndex } . Actual: " + generatedSql ) ;
1289+ }
1290+
1291+ [ TestMethod ]
1292+ [ Priority ( 0 ) ]
1293+ [ SqlStudioTestCategory ( Category . UnitTest ) ]
1294+ public void TestPreserveCommentsEnabled_SemicolonBeforeTrailingComment_MultipleStatements ( )
1295+ {
1296+ // Test semicolon placement with multiple statements each having trailing comments
1297+ var sqlWithComments = @"SELECT 1 -- first comment
1298+ SELECT 2 -- second comment" ;
1299+ var parser = new TSql170Parser ( true ) ;
1300+ var fragment = parser . Parse ( new StringReader ( sqlWithComments ) , out var errors ) ;
1301+
1302+ Assert . AreEqual ( 0 , errors . Count ) ;
1303+
1304+ var generatorOptions = new SqlScriptGeneratorOptions
1305+ {
1306+ PreserveComments = true ,
1307+ IncludeSemicolons = true
1308+ } ;
1309+ var generator = new Sql170ScriptGenerator ( generatorOptions ) ;
1310+ generator . GenerateScript ( fragment , out var generatedSql ) ;
1311+
1312+ // Both comments should be preserved
1313+ Assert . IsTrue ( generatedSql . Contains ( "-- first comment" ) ,
1314+ "First trailing comment should be preserved. Actual: " + generatedSql ) ;
1315+ Assert . IsTrue ( generatedSql . Contains ( "-- second comment" ) ,
1316+ "Second trailing comment should be preserved. Actual: " + generatedSql ) ;
1317+
1318+ // Verify semicolons appear before their respective comments, not after
1319+ Assert . IsFalse ( generatedSql . Contains ( "-- first comment;" ) ,
1320+ "Semicolon should not appear after first comment text. Actual: " + generatedSql ) ;
1321+ Assert . IsFalse ( generatedSql . Contains ( "-- second comment;" ) ,
1322+ "Semicolon should not appear after second comment text. Actual: " + generatedSql ) ;
1323+ }
1324+
1325+ [ TestMethod ]
1326+ [ Priority ( 0 ) ]
1327+ [ SqlStudioTestCategory ( Category . UnitTest ) ]
1328+ public void TestPreserveCommentsEnabled_SemicolonBeforeTrailingBlockComment ( )
1329+ {
1330+ // Test semicolon placement with trailing block comments
1331+ var sqlWithComments = "SELECT 1 /* trailing block comment */" ;
1332+ var parser = new TSql170Parser ( true ) ;
1333+ var fragment = parser . Parse ( new StringReader ( sqlWithComments ) , out var errors ) ;
1334+
1335+ Assert . AreEqual ( 0 , errors . Count ) ;
1336+
1337+ var generatorOptions = new SqlScriptGeneratorOptions
1338+ {
1339+ PreserveComments = true ,
1340+ IncludeSemicolons = true
1341+ } ;
1342+ var generator = new Sql170ScriptGenerator ( generatorOptions ) ;
1343+ generator . GenerateScript ( fragment , out var generatedSql ) ;
1344+
1345+ // The semicolon must appear BEFORE the trailing block comment
1346+ int semicolonIndex = generatedSql . IndexOf ( ";" ) ;
1347+ int commentIndex = generatedSql . IndexOf ( "/* trailing block comment */" ) ;
1348+
1349+ Assert . IsTrue ( semicolonIndex >= 0 , "Semicolon should be present in output. Actual: " + generatedSql ) ;
1350+ Assert . IsTrue ( commentIndex >= 0 , "Trailing block comment should be preserved. Actual: " + generatedSql ) ;
1351+ Assert . IsTrue ( semicolonIndex < commentIndex ,
1352+ $ "Semicolon should appear before trailing block comment. Semicolon at { semicolonIndex } , comment at { commentIndex } . Actual: " + generatedSql ) ;
1353+ }
1354+
12591355 #endregion
12601356 }
12611357}
0 commit comments