TypeCobol
TypeCobol copied to clipboard
Replace inside PictureCharacterString must match the whole token
Describe the bug
We currently consider a token to be the target of a replacement even if it only partially matches.
This happens for PartialCobolWord
and PictureCharacterString
.
This issue only focus on PictureCharacterString
.
To Reproduce (Type)Cobol code that cause the bug : (if any)
IDENTIFICATION DIVISION.
PROGRAM-ID. DVZF0OSM.
DATA DIVISION.
REPLACE
==C-N== BY ==xxx==
==C-NbX== BY ==3==
.
WORKING-STORAGE SECTION.
01 Var1 PIC X(C-NbX).
end program DVZF0OSM.
The parser currently match C-N
because we use IndexOf
instead of an Equals between C-NbX
inside the picture and C-N
.
The second replace C-NbX
is then ignored.
Expected behavior
Apply the replace inside a PictureCharacterString
only if token fully match what's inside parenthesis.
Technical
Short but incomplete solution:
In TypeCobol.Compiler.Scanner.Token.CompareForReplace
, when TokenType == TokenType.PictureCharacterString
, the comparisonToken.NormalizedText
must be Equals to what's inside the parenthesis.
Source code sample:
if(TokenType == TokenType.PictureCharacterString && comparisonToken.NormalizedText.Length > 0)
{
//Fast test to avoid creating a new string
if (NormalizedText.IndexOf(comparisonToken.NormalizedText, StringComparison.OrdinalIgnoreCase) >= 0)
{
return NormalizedText.IndexOf((comparisonToken.NormalizedText[0] == '(' ? "": "(")
+ comparisonToken.NormalizedText
+ (comparisonToken.NormalizedText[comparisonToken.NormalizedText.Length-1] == ')' ? "" : ")"),
StringComparison.OrdinalIgnoreCase) >= 0;
}
}
To optimize a little access to comparisonToken.NormalizedText
, we could cache the value in Token
:
internal string NormalizedText => _normalizedText ?? (_normalizedText = Regex.Replace(Text, @"\s*", string.Empty));
Long and complete solution: See #2077.
How to test automatically Standard unit test.