Different indentation level in the same file [message #1860578] |
Fri, 18 August 2023 07:47 |
Ronan Babin Messages: 18 Registered: July 2023 |
Junior Member |
|
|
Hi,
I have a specific language where i developed a grammar and I'm working on the formatter.
Here is an example of my file:
__Mask GenericMask {
__MaskDefault = Typ;
__Spec = ProductSpec;
__Spec = genericSpec;
run_vddio = Meas;
run_vddiob = Meas;
}
I have the following grammar:
Mask:
'__Mask' name=ID '{'
('__MaskDefault' '=' default_range=Range ';')?
('__Spec' '=' spec_table_names+=ID ';')*
spec_var+=MaskElement*
'}';
MaskElement:
spec_name=ID '=' spec_range=Range ';';
Range:
'Min' | 'Typ' | 'Max' | 'Meas';
As you can see in the file example, the file is indented with 4 spaces except for the MaskElement rule where there is 8 spaces.
Initially I had issue with indentation where it was 1 tab. I managed to change it with updateing the preferences as follow:
def void setIndentation4SpacesInsteadOfTabs()
{
val preferences = getPreferences
val newMap = Maps.<String, String> newLinkedHashMap
newMap.put(FormatterPreferenceKeys.indentation.id, ' ') // $NON-NLS-1$
val result = new MapBasedPreferenceValues(preferences, newMap)
request.preferences = result
}
This apply for the entire generated file.
Here the the formatter code for those rules:
def dispatch void format(Mask mask, extension IFormattableDocument document) {
setIndentation4SpacesInsteadOfTabs()
val open = mask.regionFor.keyword("{")
open.append[setNewLines(1)]
val close = mask.regionFor.keyword("}")
close.append[setNewLines(1)]
interior(open, close)[indent]
for ( ISemanticRegion keyword : mask.regionFor.keywords( ";" ) )
{
keyword.prepend[noSpace]
keyword.append[setNewLines(1)]
}
for ( MaskElement element: mask.spec_var)
{
element.format()
}
}
def dispatch void format(MaskElement mask_var, extension IFormattableDocument document) {
for ( ISemanticRegion keyword : mask_var.regionFor.keywords( ";" ) )
{
keyword.prepend[noSpace]
keyword.append[setNewLines(1)]
}
}
My problem now, is how to solve the 8 spaces on the MaskElement rule ?
I looked into the TextReplacer but without any success
def dispatch void format(MaskElement mask_var, extension IFormattableDocument document) {
for ( ISemanticRegion keyword : mask_var.regionFor.keywords( ";" ) )
{
keyword.prepend[noSpace]
keyword.append[setNewLines(1)]
}
val region = mask_var.regionFor.feature(UnaDslPackage.Literals.MASK_ELEMENT__SPEC_NAME)
val r = new AbstractTextReplacer(document, region) {
override createReplacements(ITextReplacerContext it) {
val offset = region.offset
it.addReplacement(region.textRegionAccess.rewriter.createReplacement(offset, 0, " "))
it
}
}
addReplacer(r)
}
I removed the call to setIndentation4SpacesInsteadOfTabs() in case this was overloading everything but it's not working eithe (I'm back with the 1 tab indentation).
Any ideas please ?
Regards,
|
|
|
|
|
|
|
|
|
|
Re: Different indentation level in the same file [message #1862952 is a reply to message #1862950] |
Mon, 08 January 2024 15:52 |
|
maybe i did not understand your problem.
class MyDslParsingTest {
@Inject
FormatterTestHelper h
@Test
def void testIt() {
h.assertFormatted[
toBeFormatted = '''
__Mask GenericMask {
__MaskDefault = Typ;
__Spec = ProductSpec;
__Spec = genericSpec;
run_vddio = Meas;
run_vddiob = Meas;
}
'''
expectation = '''
__Mask GenericMask {
__MaskDefault = Typ;
__Spec = ProductSpec;
__Spec = genericSpec;
run_vddio = Meas;
run_vddiob = Meas;
}
'''
]
}
}
is green.
so do you want the duplicate indent or not?
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Day Job: https://www.everest-systems.com
|
|
|
|
|
Re: Different indentation level in the same file [message #1863038 is a reply to message #1862955] |
Fri, 12 January 2024 08:09 |
Ronan Babin Messages: 18 Registered: July 2023 |
Junior Member |
|
|
I tried your code and it's working perfectly.
I dig a little bit to understand what it was doing and how to apply it on my other cases.
What I haven't said in my original message is that for this element I needed 8 spaces instead of 4 but I also have other elements where I need 3 spaces.... (the supplier did not do a coherent job in their indentation).
At the end, I did a simpler solution (at least simpler in my mind).
On the top element of my language, in the formatter, I configure the preferences to set 1 space for indentation.
Then for each element I need to indent, it's usually between '{' and '}' so I call a function doing a for loop on the number of indentation I need.
def void setIndentation( ISemanticRegion open, ISemanticRegion close, int indentLevel, extension IFormattableDocument document )
{
for ( var index = 0; index < indentLevel; index++ )
{
interior(open, close)[indent]
}
}
Thanks for pointing me to the right direction, I really appreciate the support.
|
|
|
|
|
|
|
|
Re: Different indentation level in the same file [message #1863329 is a reply to message #1863328] |
Fri, 26 January 2024 10:46 |
Ronan Babin Messages: 18 Registered: July 2023 |
Junior Member |
|
|
I have another piece of my language that behave differently with indentation.
Unison:SyntaxRevision1709.19;
__Levels TL_Opens {
__AlwaysExec = __Expression { __String = "FALSE"; __Type = BOOLEAN; }
__Column[0] {
__LevelsColumnType = __DCTestType;
__Group = __Expression { __String = "PD_IOs_pl-pads_t5p5_pl+pads_analog_pl-boardRes_pl-USB0ID_pl-ResetN_pl"; }
__ForceValue = __Expression { __String = "-pad_i_esd_min"; }
__ForceRange = __Expression { __String = "-pad_i_esd_min*1.1"; }
__MeasureRange = __Expression { __String = "-pad_vt_esd_max*1.1"; }
__LowClamp = __Expression { __String = "max(-pad_vt_esd_max*1.3-Dx_Gx_V_Clamp_Acc_Offset,Tester_AbsoluteMaximumRatings_GX1x_V_min)"; }
__HighClamp = __Expression { __String = "0V+Dx_Gx_V_Clamp_Acc_Offset"; }
__LowLimit = __Expression { __String = "-pad_vt_esd_max"; }
}
}
Between the parenthesis of the __Columns object I'm currently generating 4 spaces of indentation. But the real indentation for just between those parenthesis should be a tabulation (\t).
For example:
- The indentation before __AlwaysExec is still 4 spaces
- The indentation before __LevelsColumnType is a tabulation
The simplified grammar to manage just this example:
UnaFile:
header=Header (una_elements+=Levels)*;
Header:
'Unison:SyntaxRevision' version=Decimal ';';
Levels:
'__Levels' name=ID '{'
('__AlwaysExec' '=' always_exec=ExpressionType)?
(columns_list+=Column)*
'}';
Column:
'__Column' '[' index=INT ']' '{'
'__LevelsColumnType' '=' column_type=('__VIType' | '__DigitalType' | '__DCTestType' | '__SeqPowerType') ';'
('__Title' '=' title=ID ';')?
statements+=LevelColumnStatement*
'}';
LevelColumnStatement:
(level_param_type=('__Group' | 'PowerSupply' | 'StepSize' | '__ForceValue' | '__ForceRange' | '__LowClamp' | '__HighClamp' | '__MeasureRange' | '__LowLimit' | '__HighLimit' |
'ExecSeq' | 'Delay' | 'Vil' | 'Vih' | 'Vol' | 'Voh' | 'Iol' | 'Ioh' | 'Vref' | 'Rlv' | 'ClampLo' | 'ClampHi'
) '=' level_param_value=ExpressionType);
ExpressionType:{ExpressionType}
'__Expression' '{' ('__String' '=' expr=STRING ';')? ('__Type' '=' type=ExpressionTypeValue ';')? ('__Mode' '=' dir=Direction ';')?
'}';
ExpressionTypeValue:
'ANY_REAL' | 'PIN' | 's' | 'BOOLEAN' | 'INTEGER' | 'SyncType:';
my formatter is like this:
def void setIndentationPreferences( )
{
val preferences = getPreferences
val newMap = Maps.<String, String> newLinkedHashMap
newMap.put(FormatterPreferenceKeys.indentation.id, ' ') // $NON-NLS-1$
val result = new MapBasedPreferenceValues(preferences, newMap)
request.preferences = result
}
def void setIndentation( ISemanticRegion open, ISemanticRegion close, int indentLevel, extension IFormattableDocument document )
{
for ( var index = 0; index < indentLevel; index++ )
{
interior(open, close)[indent]
}
}
def void setIndentationWith4Spaces( ISemanticRegion open, ISemanticRegion close, extension IFormattableDocument document )
{
setIndentation(open, close, FOUR_SPACES, document )
}
def dispatch void format(UnaFile unaFile, extension IFormattableDocument document) {
setIndentationPreferences( )
unaFile.header.format
for (UnaElement unaElements : unaFile.una_elements) {
unaElements.format;
}
}
def dispatch void format(Header header, extension IFormattableDocument document) {
header.append[setNewLines(1)]
header.regionFor.keyword( "Unison:SyntaxRevision" ).append[noSpace]
header.regionFor.keyword( ";" ).prepend[noSpace]
}
def dispatch void format(Levels level, extension IFormattableDocument document) {
level.append[setNewLines(1)]
val open = level.regionFor.keyword("{")
val close = level.regionFor.keyword("}")
open.append[setNewLines(1)]
setIndentationWith4Spaces(open, close, document)
level.always_exec.format()
for ( Column column: level.columns_list)
{
column.format()
}
}
def dispatch void format(Column col, extension IFormattableDocument document) {
col.append[setNewLines(1)]
val open = col.regionFor.keyword("{")
val close = col.regionFor.keyword("}")
open.append[setNewLines(1)]
setIndentationWith4Spaces(open, close, document)
for ( ISemanticRegion keyword : col.regionFor.keywords( ";" ) )
{
keyword.prepend[noSpace]
keyword.append[setNewLines(1)]
}
col.regionFor.keyword( "[" ).prepend[noSpace]
col.regionFor.keyword( "[" ).append[noSpace]
col.regionFor.keyword( "]" ).prepend[noSpace]
for ( LevelColumnStatement col_statement: col.statements)
{
col_statement.format()
}
}
def dispatch void format(LevelColumnStatement col_statement, extension IFormattableDocument document) {
col_statement.level_param_value.format()
}
def dispatch void format(ExpressionType expression, extension IFormattableDocument document) {
for ( ISemanticRegion keyword : expression.regionFor.keywords( ";" ) )
{
keyword.prepend[noSpace]
}
expression.regionFor.keyword( "}" ).append[setNewLines(1)]
}
I don't really know what kind of unit test I can provide.
|
|
|
|
Powered by
FUDForum. Page generated in 0.08146 seconds