Skip to content

Commit 1c737e1

Browse files
committed
Try harder to preserve whitespace
This fixes #3551, where a whitespace between identifier and annotation keyword was sometimes lost.
1 parent ab2a526 commit 1c737e1

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

Compiler/Lexers/LexerModelicaDiff.mo

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,11 @@ algorithm
14461446
// Do not delete whitespace in-between two tokens
14471447
case (e1 as (Diff.Equal,_))::(Diff.Delete,t1 as TOKEN(id=TokenId.NEWLINE))::(Diff.Delete,t2 as TOKEN(id=TokenId.WHITESPACE))::(e2 as (Diff.Equal,_))::rest then (false,e1::(Diff.Equal,t1)::(Diff.Equal,t2)::e2::rest,tmp);
14481448
case (e1 as (Diff.Equal,_))::(Diff.Delete,t as TOKEN(id=TokenId.WHITESPACE))::(e2 as (Diff.Equal,_))::rest then (false,e1::(Diff.Equal,t)::e2::rest,tmp);
1449+
case (e1 as (Diff.Equal,TOKEN(id=t3)))::rest
1450+
guard t3<>TokenId.WHITESPACE and t3<>TokenId.NEWLINE and deleteWhitespaceFollowedByEqualNonWhitespace(rest)
1451+
algorithm
1452+
(_,rest) := deleteWhitespaceFollowedByEqualNonWhitespace(rest);
1453+
then (false,e1::rest,tmp);
14491454

14501455
// Do not delete+add the same token just because there is whitespace added
14511456
case (d1,t1)::(Diff.Add,TOKEN(id=t3))::(Diff.Add,TOKEN(id=t4))::(Diff.Add,TOKEN(id=t5))::(d2,t2)::rest
@@ -1573,6 +1578,60 @@ algorithm
15731578
lines := list(System.trim(s) for s in System.strtok(tokenContent(t),"\n"));
15741579
end blockCommentCanonical;
15751580

1581+
function deleteWhitespaceFollowedByEqualNonWhitespace
1582+
import LexerModelicaDiff.{Token,TokenId,TOKEN,tokenContent};
1583+
import DiffAlgorithm.Diff;
1584+
input list<tuple<Diff, Token>> inRest;
1585+
output Boolean b;
1586+
output list<tuple<Diff, Token>> result;
1587+
protected
1588+
tuple<Diff, Token> head;
1589+
Diff diff;
1590+
Token t;
1591+
TokenId id;
1592+
list<tuple<Diff, Token>> rest;
1593+
Boolean foundWS=false, foundNL=false;
1594+
algorithm
1595+
rest := inRest;
1596+
result := {};
1597+
while not listEmpty(rest) loop
1598+
(head as (diff,t as TOKEN(id=id))) := listHead(rest);
1599+
if diff <> Diff.Delete then
1600+
break;
1601+
end if;
1602+
rest := listRest(rest);
1603+
if id==TokenId.WHITESPACE and not foundWS then
1604+
foundWS := true;
1605+
result := (Diff.Equal,t)::result;
1606+
elseif id==TokenId.NEWLINE then
1607+
foundNL := true;
1608+
break;
1609+
else
1610+
result := head :: result;
1611+
end if;
1612+
end while;
1613+
if (not foundWS) or foundNL then
1614+
// If we find a newline, we probably went too far.
1615+
b := false;
1616+
result := {};
1617+
return;
1618+
end if;
1619+
_ := match rest
1620+
case (Diff.Equal,t)::_ then ();
1621+
else
1622+
algorithm
1623+
b := false;
1624+
result := {};
1625+
return;
1626+
then fail();
1627+
end match;
1628+
b := true;
1629+
for i in result loop
1630+
rest := i::rest;
1631+
end for;
1632+
result := rest;
1633+
end deleteWhitespaceFollowedByEqualNonWhitespace;
1634+
15761635
annotation(__OpenModelica_Interface="backend");
15771636

15781637

Compiler/Lexers/lexerModelicaDiff.l

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ algorithm
280280
// Do not delete whitespace in-between two tokens
281281
case (e1 as (Diff.Equal,_))::(Diff.Delete,t1 as TOKEN(id=TokenId.NEWLINE))::(Diff.Delete,t2 as TOKEN(id=TokenId.WHITESPACE))::(e2 as (Diff.Equal,_))::rest then (false,e1::(Diff.Equal,t1)::(Diff.Equal,t2)::e2::rest,tmp);
282282
case (e1 as (Diff.Equal,_))::(Diff.Delete,t as TOKEN(id=TokenId.WHITESPACE))::(e2 as (Diff.Equal,_))::rest then (false,e1::(Diff.Equal,t)::e2::rest,tmp);
283+
case (e1 as (Diff.Equal,TOKEN(id=t3)))::rest
284+
guard t3<>TokenId.WHITESPACE and t3<>TokenId.NEWLINE and deleteWhitespaceFollowedByEqualNonWhitespace(rest)
285+
algorithm
286+
(_,rest) := deleteWhitespaceFollowedByEqualNonWhitespace(rest);
287+
then (false,e1::rest,tmp);
283288

284289
// Do not delete+add the same token just because there is whitespace added
285290
case (d1,t1)::(Diff.Add,TOKEN(id=t3))::(Diff.Add,TOKEN(id=t4))::(Diff.Add,TOKEN(id=t5))::(d2,t2)::rest
@@ -407,4 +412,58 @@ algorithm
407412
lines := list(System.trim(s) for s in System.strtok(tokenContent(t),"\n"));
408413
end blockCommentCanonical;
409414

415+
function deleteWhitespaceFollowedByEqualNonWhitespace
416+
import LexerModelicaDiff.{Token,TokenId,TOKEN,tokenContent};
417+
import DiffAlgorithm.Diff;
418+
input list<tuple<Diff, Token>> inRest;
419+
output Boolean b;
420+
output list<tuple<Diff, Token>> result;
421+
protected
422+
tuple<Diff, Token> head;
423+
Diff diff;
424+
Token t;
425+
TokenId id;
426+
list<tuple<Diff, Token>> rest;
427+
Boolean foundWS=false, foundNL=false;
428+
algorithm
429+
rest := inRest;
430+
result := {};
431+
while not listEmpty(rest) loop
432+
(head as (diff,t as TOKEN(id=id))) := listHead(rest);
433+
if diff <> Diff.Delete then
434+
break;
435+
end if;
436+
rest := listRest(rest);
437+
if id==TokenId.WHITESPACE and not foundWS then
438+
foundWS := true;
439+
result := (Diff.Equal,t)::result;
440+
elseif id==TokenId.NEWLINE then
441+
foundNL := true;
442+
break;
443+
else
444+
result := head :: result;
445+
end if;
446+
end while;
447+
if (not foundWS) or foundNL then
448+
// If we find a newline, we probably went too far.
449+
b := false;
450+
result := {};
451+
return;
452+
end if;
453+
_ := match rest
454+
case (Diff.Equal,t)::_ then ();
455+
else
456+
algorithm
457+
b := false;
458+
result := {};
459+
return;
460+
then fail();
461+
end match;
462+
b := true;
463+
for i in result loop
464+
rest := i::rest;
465+
end for;
466+
result := rest;
467+
end deleteWhitespaceFollowedByEqualNonWhitespace;
468+
410469
annotation(__OpenModelica_Interface="backend");

0 commit comments

Comments
 (0)