From 98fea0c875efc31a8eb3db0acd33718a19bccf21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg-Michael=20Grassau?= Date: Mon, 9 Sep 2024 20:44:23 +0200 Subject: [PATCH] add new rule "Break before DEFINE etc." --- .../sap/adt/abapcleaner/rulebase/Rule.java | 4 +- .../sap/adt/abapcleaner/rulebase/RuleID.java | 1 + .../rulehelpers/RuleForDdlPosition.java | 2 + .../ddl/position/DdlPositionDefineRule.java | 133 ++++++ .../ddl/position/DdlPositionSelectRule.java | 56 +-- .../ddl/position/DdlPositionDefineTest.java | 400 ++++++++++++++++++ .../ddl/position/DdlPositionSelectTest.java | 241 +---------- 7 files changed, 548 insertions(+), 289 deletions(-) create mode 100644 com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineRule.java create mode 100644 test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineTest.java diff --git a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/Rule.java b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/Rule.java index 183251c..000029c 100644 --- a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/Rule.java +++ b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/Rule.java @@ -13,6 +13,7 @@ import com.sap.adt.abapcleaner.rules.ddl.position.DdlPositionAssociationRule; import com.sap.adt.abapcleaner.rules.ddl.position.DdlPositionBracesRule; import com.sap.adt.abapcleaner.rules.ddl.position.DdlPositionClausesRule; +import com.sap.adt.abapcleaner.rules.ddl.position.DdlPositionDefineRule; import com.sap.adt.abapcleaner.rules.ddl.position.DdlPositionJoinRule; import com.sap.adt.abapcleaner.rules.ddl.position.DdlPositionSelectRule; import com.sap.adt.abapcleaner.rules.ddl.annotations.DdlAnnotationLayoutRule; @@ -27,7 +28,7 @@ import java.util.*; public abstract class Rule { - public static final int RULE_COUNT = 82; + public static final int RULE_COUNT = 83; public static final int RULE_GROUP_COUNT = 9; protected static final String LINE_SEP = ABAP.LINE_SEPARATOR; @@ -160,6 +161,7 @@ static Rule[] getAllRules(Profile profile) { new DdlAnnotationNestingRule(profile), // DDL position + new DdlPositionDefineRule(profile), new DdlPositionSelectRule(profile), new DdlPositionJoinRule(profile), new DdlPositionAssociationRule(profile), diff --git a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/RuleID.java b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/RuleID.java index 311cc97..5a0aa13 100644 --- a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/RuleID.java +++ b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulebase/RuleID.java @@ -111,6 +111,7 @@ public enum RuleID { DDL_ANNO_NESTING, // DDL Positions + DDL_POSITION_DEFINE, DDL_POSITION_SELECT, DDL_POSITION_JOIN, DDL_POSITION_ASSOCIATION, diff --git a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulehelpers/RuleForDdlPosition.java b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulehelpers/RuleForDdlPosition.java index 05e61bc..e177622 100644 --- a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulehelpers/RuleForDdlPosition.java +++ b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rulehelpers/RuleForDdlPosition.java @@ -91,6 +91,8 @@ protected boolean breakBefore(Token token, DdlLineBreak lineBreak, boolean empty // adjust the indent of the supplied Token (or the attached non-annotation comments above it) int lineBreaksMin = emptyLineIfBreaking ? 2 : 1; + if (token.getPrev() == null && token.getParentCommand().isFirstCommandInCode()) // e.g. for DEFINE + lineBreaksMin = 0; int lineBreaksMax = 2; setWhitespaceInclAttachedComments(token, lineBreaksMin, lineBreaksMax, indent, false); return false; // .addRuleUse() was already called above for all involved commands diff --git a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineRule.java b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineRule.java new file mode 100644 index 0000000..a579954 --- /dev/null +++ b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineRule.java @@ -0,0 +1,133 @@ +package com.sap.adt.abapcleaner.rules.ddl.position; + +import java.time.LocalDate; + +import com.sap.adt.abapcleaner.parser.Code; +import com.sap.adt.abapcleaner.parser.Command; +import com.sap.adt.abapcleaner.parser.Token; +import com.sap.adt.abapcleaner.parser.TokenSearch; +import com.sap.adt.abapcleaner.programbase.IntegrityBrokenException; +import com.sap.adt.abapcleaner.programbase.UnexpectedSyntaxAfterChanges; +import com.sap.adt.abapcleaner.programbase.UnexpectedSyntaxBeforeChanges; +import com.sap.adt.abapcleaner.rulebase.ConfigEnumValue; +import com.sap.adt.abapcleaner.rulebase.ConfigIntValue; +import com.sap.adt.abapcleaner.rulebase.ConfigValue; +import com.sap.adt.abapcleaner.rulebase.Profile; +import com.sap.adt.abapcleaner.rulebase.RuleID; +import com.sap.adt.abapcleaner.rulebase.RuleReference; +import com.sap.adt.abapcleaner.rulebase.RuleSource; +import com.sap.adt.abapcleaner.rulehelpers.RuleForDdlPosition; + +public class DdlPositionDefineRule extends RuleForDdlPosition { + private final static RuleReference[] references = new RuleReference[] { new RuleReference(RuleSource.ABAP_CLEANER) }; + + @Override + public RuleID getID() { return RuleID.DDL_POSITION_DEFINE; } + + @Override + public String getDisplayName() { return "Break before DEFINE etc."; } + + @Override + public String getDescription() { return "Standardizes line breaks and indentation before DEFINE / EXTEND etc. keywords, entity name and WITH PARAMETERS."; } + + @Override + public LocalDate getDateCreated() { return LocalDate.of(2024, 9, 9); } + + @Override + public RuleReference[] getReferences() { return references; } + + @Override + public String getExample() { + return "" + + LINE_SEP + "@EndUserText.label: 'Any Description' define" + + LINE_SEP + " view" + + LINE_SEP + " entity" + + LINE_SEP + "C_AnyEntity with" + + LINE_SEP + "parameters" + + LINE_SEP + "// comment" + + LINE_SEP + "P_AnyParam : AnyType," + + LINE_SEP + " P_OtherParam : OtherType," + + LINE_SEP + " P_ThirdParam : ThirdType" + + LINE_SEP + "" + + LINE_SEP + " as select from I_AnyEntity as AnyAlias" + + LINE_SEP + "" + + LINE_SEP + " left outer to one join I_OtherEntity as OtherAlias" + + LINE_SEP + " on AnyAlias.IdField = OtherAlias.IdField" + + LINE_SEP + "" + + LINE_SEP + "{" + + LINE_SEP + " key AnyAlias.AnyKeyField," + + LINE_SEP + " OtherAlias.AnyNonKeyField" + + LINE_SEP + "}"; + } + + final ConfigEnumValue configBreakBeforeDefine = new ConfigEnumValue(this, "BreakBeforeDefine", "Break before DEFINE etc. keywords:", lineBreakSelectionWithoutNever, DdlLineBreakWithoutNever.values(), DdlLineBreakWithoutNever.ALWAYS); + final ConfigIntValue configDefineIndent = new ConfigIntValue(this, "DefineIndent", "Indent if breaking:", "", 0, 0, MAX_INDENT); + + final ConfigEnumValue configBreakBeforeEntityName = new ConfigEnumValue(this, "BreakBeforeEntityName", "Break before entity name:", lineBreakSelection, DdlLineBreak.values(), DdlLineBreak.NEVER); + final ConfigIntValue configEntityNameIndent = new ConfigIntValue(this, "EntityNameIndent", "Indent if breaking:", "", 0, 2, MAX_INDENT); + + final ConfigEnumValue configBreakBeforeWithParams = new ConfigEnumValue(this, "BreakBeforeWithParams", "Break before WITH PARAMETERS:", lineBreakSelection, DdlLineBreak.values(), DdlLineBreak.ALWAYS); + final ConfigIntValue configWithParamsIndent = new ConfigIntValue(this, "WithParamsIndent", "Indent if breaking:", "", 0, 2, MAX_INDENT); + final ConfigIntValue configParamsIndent = new ConfigIntValue(this, "ParamsIndent", "Indent of parameters:", "", 0, 4, MAX_INDENT); + + private final ConfigValue[] configValues = new ConfigValue[] { configBreakBeforeDefine, configDefineIndent, configBreakBeforeEntityName, configEntityNameIndent, configBreakBeforeWithParams, configWithParamsIndent, configParamsIndent }; + + @Override + public ConfigValue[] getConfigValues() { return configValues; } + + public DdlPositionDefineRule(Profile profile) { + super(profile); + initializeConfiguration(); + } + + // ------------------------------------------------------------------------- + + @Override + protected boolean executeOn(Code code, Command command) throws UnexpectedSyntaxBeforeChanges, UnexpectedSyntaxAfterChanges, IntegrityBrokenException { + boolean changed = false; + + if (command.isDdlAnnotation()) + return false; + + Token firstCode = command.getFirstCodeToken(); + if (firstCode == null) // pro forma + return false; + + DdlLineBreak breakBeforeDefine = getLineBreak(DdlLineBreakWithoutNever.forValue(configBreakBeforeDefine.getValue())); + DdlLineBreak breakBeforeEntityName = DdlLineBreak.forValue(configBreakBeforeEntityName.getValue()); + DdlLineBreak breakBeforeWithParams = DdlLineBreak.forValue(configBreakBeforeWithParams.getValue()); + + // break before DEFINE etc., condense definition keywords and (un)break before entity name + Token entityName = command.getDdlOrDclEntityNameToken(); + if (entityName != null) { + boolean emptyLine = (command.getPrev() != null); + changed |= breakBefore(firstCode, breakBeforeDefine, emptyLine, configDefineIndent.getValue()); + changed |= condense(firstCode, entityName.getPrevCodeToken()); + + changed |= breakBefore(entityName, breakBeforeEntityName, false, configEntityNameIndent.getValue()); + } + + // (un)break before "WITH PARAMETERS" + Token parametersToken = firstCode.getLastTokenOnSiblings(true, TokenSearch.ASTERISK, "WITH", "PARAMETERS"); + if (parametersToken != null) { + Token withToken = parametersToken.getPrevCodeSibling(); + changed |= breakBefore(withToken, breakBeforeWithParams, false, configWithParamsIndent.getValue()); + changed |= condense(withToken, parametersToken); + + // set indent of parameters, their annotations and comments + Command paramCommand = command.getFirstChild(); + int paramIndent = configParamsIndent.getValue(); + while (paramCommand != null) { + // do not move comments at the end of the parameter list, as they probably belong to the following Command + if (paramCommand.isCommentLine() && paramCommand.getNextNonCommentSibling() == null) + break; + paramCommand = setNewIndent(paramCommand, paramIndent); + if (paramCommand == null) // pro forma + break; + paramCommand = paramCommand.getNextSibling(); + } + } + + return changed; + } +} diff --git a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectRule.java b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectRule.java index 640af7b..c08b0a4 100644 --- a/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectRule.java +++ b/com.sap.adt.abapcleaner/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectRule.java @@ -40,12 +40,8 @@ public class DdlPositionSelectRule extends RuleForDdlPosition { @Override public String getExample() { return "" - + LINE_SEP + "define view entity C_AnyEntity with" - + LINE_SEP + "parameters" - + LINE_SEP + "// comment" - + LINE_SEP + "P_AnyParam : AnyType," - + LINE_SEP + " P_OtherParam : OtherType," - + LINE_SEP + " P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias" + + LINE_SEP + "define view entity C_AnyEntity as select" + + LINE_SEP + "from I_AnyEntity as AnyAlias" + LINE_SEP + "" + LINE_SEP + " left outer to one join I_OtherEntity as OtherAlias" + LINE_SEP + " on AnyAlias.IdField = OtherAlias.IdField" @@ -75,13 +71,6 @@ public String getExample() { + LINE_SEP + "}"; } - final ConfigEnumValue configBreakBeforeEntityName = new ConfigEnumValue(this, "BreakBeforeEntityName", "Break before entity name:", lineBreakSelection, DdlLineBreak.values(), DdlLineBreak.NEVER); - final ConfigIntValue configEntityNameIndent = new ConfigIntValue(this, "EntityNameIndent", "Indent if breaking:", "", 0, 2, MAX_INDENT); - - final ConfigEnumValue configBreakBeforeWithParams = new ConfigEnumValue(this, "BreakBeforeWithParams", "Break before WITH PARAMETERS:", lineBreakSelection, DdlLineBreak.values(), DdlLineBreak.ALWAYS); - final ConfigIntValue configWithParamsIndent = new ConfigIntValue(this, "WithParamsIndent", "Indent if breaking:", "", 0, 2, MAX_INDENT); - final ConfigIntValue configParamsIndent = new ConfigIntValue(this, "ParamsIndent", "Indent of parameters:", "", 0, 4, MAX_INDENT); - final ConfigEnumValue configBreakBeforeAsSelectFrom = new ConfigEnumValue(this, "BreakBeforeAsSelectFrom", "Break before AS SELECT FROM:", lineBreakSelection, DdlLineBreak.values(), DdlLineBreak.ALWAYS); final ConfigIntValue configAsSelectFromIndent = new ConfigIntValue(this, "AsSelectFromIndent", "Indent if breaking:", "", 0, 2, MAX_INDENT); @@ -94,14 +83,7 @@ public String getExample() { final ConfigEnumValue configBreakBeforeDataSource = new ConfigEnumValue(this, "BreakBeforeDataSource", "Break before data source:", lineBreakSelection, DdlLineBreak.values(), DdlLineBreak.NEVER); final ConfigIntValue configDataSourceIndent = new ConfigIntValue(this, "DataSourceIndent", "Indent if breaking:", "", 0, 4, MAX_INDENT); - private final ConfigValue[] configValues = new ConfigValue[] { - configBreakBeforeEntityName, configEntityNameIndent, - configBreakBeforeWithParams, configWithParamsIndent, configParamsIndent, - configBreakBeforeAsSelectFrom, configAsSelectFromIndent, - configBreakBeforeSelectFrom, configSelectFromIndent, - configBreakBeforeAsProjectionOn, configAsProjectionOnIndent, - configBreakBeforeDataSource, configDataSourceIndent - }; + private final ConfigValue[] configValues = new ConfigValue[] { configBreakBeforeAsSelectFrom, configAsSelectFromIndent, configBreakBeforeSelectFrom, configSelectFromIndent, configBreakBeforeAsProjectionOn, configAsProjectionOnIndent, configBreakBeforeDataSource, configDataSourceIndent }; @Override public ConfigValue[] getConfigValues() { return configValues; } @@ -117,45 +99,13 @@ public DdlPositionSelectRule(Profile profile) { protected boolean executeOn(Code code, Command command) throws UnexpectedSyntaxBeforeChanges, UnexpectedSyntaxAfterChanges, IntegrityBrokenException { boolean changed = false; - DdlLineBreak breakBeforeEntityName = DdlLineBreak.forValue(configBreakBeforeEntityName.getValue()); - DdlLineBreak breakBeforeWithParams = DdlLineBreak.forValue(configBreakBeforeWithParams.getValue()); DdlLineBreak breakBeforeAsSelectFrom = DdlLineBreak.forValue(configBreakBeforeAsSelectFrom.getValue()); DdlLineBreak breakBeforeSelectFrom = DdlLineBreak.forValue(configBreakBeforeSelectFrom.getValue()); DdlLineBreak breakBeforeAsProjectionOn = DdlLineBreak.forValue(configBreakBeforeAsProjectionOn.getValue()); - // condense definition keywords and (un)break before entity name - if (breakBeforeEntityName != DdlLineBreak.KEEP_AS_IS) { - Token entityName = command.getDdlOrDclEntityNameToken(); - if (entityName != null) { - changed |= condense(command.getFirstCodeToken(), entityName.getPrevCodeToken()); - changed |= breakBefore(entityName, breakBeforeEntityName, false, configEntityNameIndent.getValue()); - } - } - Token token = command.getFirstCodeToken(); while (token != null) { - // (un)break before "WITH PARAMETERS" - Token parametersToken = token.getLastTokenOnSiblings(true, "WITH", "PARAMETERS"); - if (breakBeforeWithParams != DdlLineBreak.KEEP_AS_IS && parametersToken != null) { - changed |= breakBefore(token, breakBeforeWithParams, false, configWithParamsIndent.getValue()); - changed |= condense(token, parametersToken); - - // set indent of parameters, their annotations and comments - Command paramCommand = command.getFirstChild(); - int paramIndent = configParamsIndent.getValue(); - while (paramCommand != null) { - // do not move comments at the end of the parameter list, as they probably belong to the following Command - if (paramCommand.isCommentLine() && paramCommand.getNextNonCommentSibling() == null) - break; - paramCommand = setNewIndent(paramCommand, paramIndent); - if (paramCommand == null) // pro forma - break; - paramCommand = paramCommand.getNextSibling(); - } - break; // nothing else to be expected in this Command - } - // (un)break before "AS SELECT [DISTINCT] FROM" Token fromToken = token.getLastTokenOnSiblings(true, "AS", "SELECT", TokenSearch.makeOptional("DISTINCT"), "FROM"); if (breakBeforeAsSelectFrom != DdlLineBreak.KEEP_AS_IS && fromToken != null ) { diff --git a/test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineTest.java b/test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineTest.java new file mode 100644 index 0000000..411ad48 --- /dev/null +++ b/test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionDefineTest.java @@ -0,0 +1,400 @@ +package com.sap.adt.abapcleaner.rules.ddl.position; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.sap.adt.abapcleaner.rulebase.RuleID; +import com.sap.adt.abapcleaner.rulebase.RuleTestBase; + +public class DdlPositionDefineTest extends RuleTestBase { + private DdlPositionDefineRule rule; + + DdlPositionDefineTest() { + super(RuleID.DDL_POSITION_DEFINE); + rule = (DdlPositionDefineRule)getRule(); + } + + @BeforeEach + void setUp() { + // setup default test configuration (may be modified in the individual test methods) + rule.configBreakBeforeDefine.setEnumValue(DdlLineBreakWithoutNever.ALWAYS); + rule.configDefineIndent.setValue(0); + + rule.configBreakBeforeEntityName.setEnumValue(DdlLineBreak.NEVER); + rule.configEntityNameIndent.setValue(2); + + rule.configBreakBeforeWithParams.setEnumValue(DdlLineBreak.ALWAYS); + rule.configWithParamsIndent.setValue(2); + rule.configParamsIndent.setValue(4); + } + + @Test + void testAlwaysBreakBeforeDefine() { + rule.configDefineIndent.setValue(1); + + buildSrc("@EndUserText.label: 'Any Description' define"); + buildSrc(" view"); + buildSrc(" entity"); + buildSrc("C_AnyEntity"); + buildSrc(""); + buildSrc(" as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField,"); + buildSrc(" AnyAlias.AnyNonKeyField"); + buildSrc("}"); + + buildExp("@EndUserText.label: 'Any Description'"); + buildExp(""); + buildExp(" define view entity C_AnyEntity"); + buildExp(""); + buildExp(" as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField,"); + buildExp(" AnyAlias.AnyNonKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testKeepDefineAsIs() { + rule.configBreakBeforeDefine.setEnumValue(DdlLineBreakWithoutNever.KEEP_AS_IS); + rule.configDefineIndent.setValue(4); + + buildSrc("@EndUserText.label: 'Any Description' define"); + buildSrc(" view"); + buildSrc(" entity"); + buildSrc("C_AnyEntity"); + buildSrc(""); + buildSrc(" as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField,"); + buildSrc(" AnyAlias.AnyNonKeyField"); + buildSrc("}"); + + buildExp("@EndUserText.label: 'Any Description' define view entity C_AnyEntity"); + buildExp(""); + buildExp(" as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField,"); + buildExp(" AnyAlias.AnyNonKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testNeverBreakBeforeEntityName() { + buildSrc("define"); + buildSrc("view"); + buildSrc("entity"); + buildSrc("C_AnyEntity"); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity"); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testAlwaysBreakBeforeEntityName() { + rule.configBreakBeforeEntityName.setEnumValue(DdlLineBreak.ALWAYS); + + buildSrc("define"); + buildSrc("view"); + buildSrc("entity C_AnyEntity"); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField"); + buildSrc("}"); + + buildExp("define view entity"); + buildExp(" C_AnyEntity"); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testKeepEntityName() { + rule.configBreakBeforeEntityName.setEnumValue(DdlLineBreak.KEEP_AS_IS); + + buildSrc("define"); + buildSrc("view"); + buildSrc("entity C_AnyEntity"); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity"); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testAlwaysBreakBeforeWithParameters() { + buildSrc("define view entity C_AnyEntity with"); + buildSrc("parameters"); + buildSrc("// comment"); + buildSrc("P_AnyParam : AnyType,"); + buildSrc(" @Anno.subAnno: 'value'"); + buildSrc(" P_OtherParam : OtherType,"); + buildSrc(" /* multi-"); + buildSrc(" * line"); + buildSrc(" * comment */"); + buildSrc(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity"); + buildExp(" with parameters"); + buildExp(" // comment"); + buildExp(" P_AnyParam : AnyType,"); + buildExp(" @Anno.subAnno: 'value'"); + buildExp(" P_OtherParam : OtherType,"); + buildExp(" /* multi-"); + buildExp(" * line"); + buildExp(" * comment */"); + buildExp(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testKeepWithParameters() { + rule.configBreakBeforeWithParams.setEnumValue(DdlLineBreak.KEEP_AS_IS); + + buildSrc("define view entity C_AnyEntity with"); + buildSrc("parameters"); + buildSrc("// comment"); + buildSrc("P_AnyParam : AnyType,"); + buildSrc(" @Anno.subAnno: 'value'"); + buildSrc(" P_OtherParam : OtherType,"); + buildSrc(" /* comment in correct position */"); + buildSrc(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity with parameters"); + buildExp(" // comment"); + buildExp(" P_AnyParam : AnyType,"); + buildExp(" @Anno.subAnno: 'value'"); + buildExp(" P_OtherParam : OtherType,"); + buildExp(" /* comment in correct position */"); + buildExp(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testNeverBreakBeforeWithParameters() { + rule.configBreakBeforeWithParams.setEnumValue(DdlLineBreak.NEVER); + rule.configWithParamsIndent.setValue(10); + + buildSrc("define view entity C_AnyEntity with"); + buildSrc("parameters"); + buildSrc("// comment"); + buildSrc("P_AnyParam : AnyType,"); + buildSrc(" @Anno.subAnno: 'value'"); + buildSrc(" P_OtherParam : OtherType,"); + buildSrc(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity with parameters"); + buildExp(" // comment"); + buildExp(" P_AnyParam : AnyType,"); + buildExp(" @Anno.subAnno: 'value'"); + buildExp(" P_OtherParam : OtherType,"); + buildExp(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testMoveAttachedComments() { + // ensure that the attached comments are moved along with "WITH PARAMETERS" + buildSrc("define view entity C_AnyEntity"); + buildSrc("// single-line comment"); + buildSrc("/* multi-line"); + buildSrc(" comment */"); + buildSrc("with"); + buildSrc("parameters"); + buildSrc("// comment"); + buildSrc("P_AnyParam : AnyType,"); + buildSrc(" P_OtherParam : OtherType,"); + buildSrc(" P_ThirdParam : ThirdType"); + buildSrc(" // comment on select"); + buildSrc(" as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField,"); + buildSrc(" AnyAlias.AnyNonKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity"); + buildExp(" // single-line comment"); + buildExp(" /* multi-line"); + buildExp(" comment */"); + buildExp(" with parameters"); + buildExp(" // comment"); + buildExp(" P_AnyParam : AnyType,"); + buildExp(" P_OtherParam : OtherType,"); + buildExp(" P_ThirdParam : ThirdType"); + buildExp(" // comment on select"); + buildExp(" as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField,"); + buildExp(" AnyAlias.AnyNonKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testDoNotMoveDetachedComments() { + // ensure that the detached comments are not moved along with "WITH PARAMETERS" + buildSrc("define view entity C_AnyEntity"); + buildSrc("// detached comment"); + buildSrc(""); + buildSrc("with"); + buildSrc("parameters"); + buildSrc("// comment"); + buildSrc("P_AnyParam : AnyType,"); + buildSrc(" P_OtherParam : OtherType,"); + buildSrc(" P_ThirdParam : ThirdType"); + buildSrc(""); + buildSrc(" as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField,"); + buildSrc(" AnyAlias.AnyNonKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity"); + buildExp("// detached comment"); + buildExp(""); + buildExp(" with parameters"); + buildExp(" // comment"); + buildExp(" P_AnyParam : AnyType,"); + buildExp(" P_OtherParam : OtherType,"); + buildExp(" P_ThirdParam : ThirdType"); + buildExp(""); + buildExp(" as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField,"); + buildExp(" AnyAlias.AnyNonKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testDoNotMoveCommentedOutAnnotations() { + // ensure that the commented-out annotations are not moved along with "WITH PARAMETERS" + buildSrc("define view entity C_AnyEntity"); + buildSrc("// @Anno.subAnno"); + buildSrc(" // single-line comment"); + buildSrc("with"); + buildSrc("parameters"); + buildSrc("// comment"); + buildSrc("P_AnyParam : AnyType,"); + buildSrc(" P_OtherParam : OtherType,"); + buildSrc(" P_ThirdParam : ThirdType"); + buildSrc(""); + buildSrc(" as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField,"); + buildSrc(" AnyAlias.AnyNonKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity"); + buildExp("// @Anno.subAnno"); + buildExp(" // single-line comment"); + buildExp(" with parameters"); + buildExp(" // comment"); + buildExp(" P_AnyParam : AnyType,"); + buildExp(" P_OtherParam : OtherType,"); + buildExp(" P_ThirdParam : ThirdType"); + buildExp(""); + buildExp(" as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField,"); + buildExp(" AnyAlias.AnyNonKeyField"); + buildExp("}"); + + testRule(); + } + + @Test + void testDoNotMoveComments() { + // ensure that neither the commented-out annotation nor the comment above it is being moved + buildSrc("define view entity C_AnyEntity"); + buildSrc(" // single-line comment"); + buildSrc("// @Anno.subAnno"); + buildSrc("with"); + buildSrc("parameters"); + buildSrc("// comment"); + buildSrc("P_AnyParam : AnyType,"); + buildSrc(" P_OtherParam : OtherType,"); + buildSrc(" P_ThirdParam : ThirdType"); + buildSrc(""); + buildSrc(" as select from I_AnyEntity as AnyAlias"); + buildSrc(""); + buildSrc("{"); + buildSrc(" key AnyAlias.AnyKeyField,"); + buildSrc(" AnyAlias.AnyNonKeyField"); + buildSrc("}"); + + buildExp("define view entity C_AnyEntity"); + buildExp(" // single-line comment"); + buildExp("// @Anno.subAnno"); + buildExp(" with parameters"); + buildExp(" // comment"); + buildExp(" P_AnyParam : AnyType,"); + buildExp(" P_OtherParam : OtherType,"); + buildExp(" P_ThirdParam : ThirdType"); + buildExp(""); + buildExp(" as select from I_AnyEntity as AnyAlias"); + buildExp(""); + buildExp("{"); + buildExp(" key AnyAlias.AnyKeyField,"); + buildExp(" AnyAlias.AnyNonKeyField"); + buildExp("}"); + + testRule(); + } +} \ No newline at end of file diff --git a/test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectTest.java b/test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectTest.java index 17e20a8..ad88de4 100644 --- a/test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectTest.java +++ b/test/com.sap.adt.abapcleaner.test/src/com/sap/adt/abapcleaner/rules/ddl/position/DdlPositionSelectTest.java @@ -17,13 +17,6 @@ public class DdlPositionSelectTest extends RuleTestBase { @BeforeEach void setUp() { // setup default test configuration (may be modified in the individual test methods) - rule.configBreakBeforeEntityName.setEnumValue(DdlLineBreak.NEVER); - rule.configEntityNameIndent.setValue(2); - - rule.configBreakBeforeWithParams.setEnumValue(DdlLineBreak.ALWAYS); - rule.configWithParamsIndent.setValue(2); - rule.configParamsIndent.setValue(4); - rule.configBreakBeforeAsSelectFrom.setEnumValue(DdlLineBreak.ALWAYS); rule.configAsSelectFromIndent.setValue(2); @@ -37,164 +30,6 @@ void setUp() { rule.configDataSourceIndent.setValue(4); } - @Test - void testNeverBreakBeforeEntityName() { - buildSrc("define"); - buildSrc("view"); - buildSrc("entity C_AnyEntity"); - buildSrc("{"); - buildSrc(" key AnyAlias.AnyKeyField"); - buildSrc("}"); - - buildExp("define view entity C_AnyEntity"); - buildExp("{"); - buildExp(" key AnyAlias.AnyKeyField"); - buildExp("}"); - - testRule(); - } - - @Test - void testAlwaysBreakBeforeEntityName() { - rule.configBreakBeforeEntityName.setEnumValue(DdlLineBreak.ALWAYS); - - buildSrc("define"); - buildSrc("view"); - buildSrc("entity C_AnyEntity"); - buildSrc("{"); - buildSrc(" key AnyAlias.AnyKeyField"); - buildSrc("}"); - - buildExp("define view entity"); - buildExp(" C_AnyEntity"); - buildExp("{"); - buildExp(" key AnyAlias.AnyKeyField"); - buildExp("}"); - - testRule(); - } - - @Test - void testKeepEntityName() { - rule.configBreakBeforeEntityName.setEnumValue(DdlLineBreak.KEEP_AS_IS); - - buildSrc("define"); - buildSrc("view"); - buildSrc("entity C_AnyEntity"); - buildSrc("{"); - buildSrc(" key AnyAlias.AnyKeyField"); - buildSrc("}"); - - copyExpFromSrc(); - - testRule(); - } - - @Test - void testAlwaysBreakBeforeWithParameters() { - buildSrc("define view entity C_AnyEntity with"); - buildSrc("parameters"); - buildSrc("// comment"); - buildSrc("P_AnyParam : AnyType,"); - buildSrc(" @Anno.subAnno: 'value'"); - buildSrc(" P_OtherParam : OtherType,"); - buildSrc(" /* multi-"); - buildSrc(" * line"); - buildSrc(" * comment */"); - buildSrc(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); - buildSrc(""); - buildSrc("{"); - buildSrc(" key AnyAlias.AnyKeyField"); - buildSrc("}"); - - buildExp("define view entity C_AnyEntity"); - buildExp(" with parameters"); - buildExp(" // comment"); - buildExp(" P_AnyParam : AnyType,"); - buildExp(" @Anno.subAnno: 'value'"); - buildExp(" P_OtherParam : OtherType,"); - buildExp(" /* multi-"); - buildExp(" * line"); - buildExp(" * comment */"); - buildExp(" P_ThirdParam : ThirdType"); - buildExp(""); - buildExp(" as select from I_AnyEntity as AnyAlias"); - buildExp(""); - buildExp("{"); - buildExp(" key AnyAlias.AnyKeyField"); - buildExp("}"); - - testRule(); - } - - @Test - void testKeepWithParameters() { - rule.configBreakBeforeWithParams.setEnumValue(DdlLineBreak.KEEP_AS_IS); - - buildSrc("define view entity C_AnyEntity with"); - buildSrc("parameters"); - buildSrc("// comment"); - buildSrc("P_AnyParam : AnyType,"); - buildSrc(" @Anno.subAnno: 'value'"); - buildSrc(" P_OtherParam : OtherType,"); - buildSrc(" /* comment in correct position */"); - buildSrc(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); - buildSrc(""); - buildSrc("{"); - buildSrc(" key AnyAlias.AnyKeyField"); - buildSrc("}"); - - buildExp("define view entity C_AnyEntity with"); - buildExp("parameters"); - buildExp("// comment"); - buildExp("P_AnyParam : AnyType,"); - buildExp(" @Anno.subAnno: 'value'"); - buildExp(" P_OtherParam : OtherType,"); - buildExp(" /* comment in correct position */"); - buildExp(" P_ThirdParam : ThirdType"); - buildExp(""); - buildExp(" as select from I_AnyEntity as AnyAlias"); - buildExp(""); - buildExp("{"); - buildExp(" key AnyAlias.AnyKeyField"); - buildExp("}"); - - testRule(); - } - - @Test - void testNeverBreakBeforeWithParameters() { - rule.configBreakBeforeWithParams.setEnumValue(DdlLineBreak.NEVER); - rule.configParamsIndent.setValue(10); - - buildSrc("define view entity C_AnyEntity with"); - buildSrc("parameters"); - buildSrc("// comment"); - buildSrc("P_AnyParam : AnyType,"); - buildSrc(" @Anno.subAnno: 'value'"); - buildSrc(" P_OtherParam : OtherType,"); - buildSrc(" P_ThirdParam : ThirdType as select from I_AnyEntity as AnyAlias"); - buildSrc(""); - buildSrc("{"); - buildSrc(" key AnyAlias.AnyKeyField"); - buildSrc("}"); - - buildExp("define view entity C_AnyEntity with parameters"); - buildExp(" // comment"); - buildExp(" P_AnyParam : AnyType,"); - buildExp(" @Anno.subAnno: 'value'"); - buildExp(" P_OtherParam : OtherType,"); - buildExp(" P_ThirdParam : ThirdType"); - buildExp(""); - buildExp(" as select from I_AnyEntity as AnyAlias"); - buildExp(""); - buildExp("{"); - buildExp(" key AnyAlias.AnyKeyField"); - buildExp("}"); - - testRule(); - } - @Test void testAlwaysBreakBeforeSelectFromAfterUnion() { buildSrc("define view entity C_AnyEntity as select from I_AnyEntity as AnyAlias"); @@ -510,7 +345,9 @@ void testKeepDataSource() { void testAlwaysBreakBeforeAsProjectionOn() { buildSrc("@AccessControl.authorizationCheck: #NOT_ALLOWED"); buildSrc("define transient view entity AnyView"); - buildSrc(" provider contract analytical_query with parameters p_Any : abap.cuky as projection on OtherView"); + buildSrc(" provider contract analytical_query"); + buildSrc(" with parameters"); + buildSrc(" p_Any : abap.cuky as projection on OtherView"); buildSrc("{"); buildSrc(" @AnalyticsDetails.query.axis: #FREE"); buildSrc(" AnyField"); @@ -575,18 +412,8 @@ void testKeepAsProjectionOn() { @Test void testMoveAttachedComments() { - // ensure that the attached comments are moved along with "WITH PARAMETERS" or "AS SELECT FROM" - // and that the extra line above "AS SELECT FROM" is inserted before the first attached comment + // ensure that the attached comments are moved along with "AS SELECT FROM" buildSrc("define view entity C_AnyEntity"); - buildSrc("// single-line comment"); - buildSrc("/* multi-line"); - buildSrc(" comment */"); - buildSrc("with"); - buildSrc("parameters"); - buildSrc("// comment"); - buildSrc("P_AnyParam : AnyType,"); - buildSrc(" P_OtherParam : OtherType,"); - buildSrc(" P_ThirdParam : ThirdType"); buildSrc(" /* multi-"); buildSrc(" line"); buildSrc(" comment */"); @@ -599,15 +426,6 @@ void testMoveAttachedComments() { buildSrc("}"); buildExp("define view entity C_AnyEntity"); - buildExp(" // single-line comment"); - buildExp(" /* multi-line"); - buildExp(" comment */"); - buildExp(" with parameters"); - buildExp(" // comment"); - buildExp(" P_AnyParam : AnyType,"); - buildExp(" P_OtherParam : OtherType,"); - buildExp(" P_ThirdParam : ThirdType"); - buildExp(""); buildExp(" /* multi-"); buildExp(" line"); buildExp(" comment */"); @@ -624,16 +442,8 @@ void testMoveAttachedComments() { @Test void testDoNotMoveDetachedComments() { - // ensure that the detached comments are not moved along with "WITH PARAMETERS" or "AS SELECT FROM" + // ensure that the detached comments are not moved along with "AS SELECT FROM" buildSrc("define view entity C_AnyEntity"); - buildSrc("// detached comment"); - buildSrc(""); - buildSrc("with"); - buildSrc("parameters"); - buildSrc("// comment"); - buildSrc("P_AnyParam : AnyType,"); - buildSrc(" P_OtherParam : OtherType,"); - buildSrc(" P_ThirdParam : ThirdType"); buildSrc(" /* detached multi-line"); buildSrc(" comment */"); buildSrc(""); @@ -646,13 +456,6 @@ void testDoNotMoveDetachedComments() { buildSrc("}"); buildExp("define view entity C_AnyEntity"); - buildExp("// detached comment"); - buildExp(""); - buildExp(" with parameters"); - buildExp(" // comment"); - buildExp(" P_AnyParam : AnyType,"); - buildExp(" P_OtherParam : OtherType,"); - buildExp(" P_ThirdParam : ThirdType"); buildExp(" /* detached multi-line"); buildExp(" comment */"); buildExp(""); @@ -669,18 +472,10 @@ void testDoNotMoveDetachedComments() { @Test void testDoNotMoveCommentedOutAnnotations() { - // ensure that the commented-out annotations are not moved along with "WITH PARAMETERS" or "AS SELECT FROM" + // ensure that the commented-out annotations are not moved along with "AS SELECT FROM" buildSrc("define view entity C_AnyEntity"); buildSrc("// @Anno.subAnno"); buildSrc(" // single-line comment"); - buildSrc("with"); - buildSrc("parameters"); - buildSrc("// comment"); - buildSrc("P_AnyParam : AnyType,"); - buildSrc(" P_OtherParam : OtherType,"); - buildSrc(" P_ThirdParam : ThirdType"); - buildSrc("// @Anno.subAnno"); - buildSrc(" // single-line comment"); buildSrc(" as select from I_AnyEntity as AnyAlias"); buildSrc(""); buildSrc("{"); @@ -691,14 +486,6 @@ void testDoNotMoveCommentedOutAnnotations() { buildExp("define view entity C_AnyEntity"); buildExp("// @Anno.subAnno"); buildExp(" // single-line comment"); - buildExp(" with parameters"); - buildExp(" // comment"); - buildExp(" P_AnyParam : AnyType,"); - buildExp(" P_OtherParam : OtherType,"); - buildExp(" P_ThirdParam : ThirdType"); - buildExp("// @Anno.subAnno"); - buildExp(""); - buildExp(" // single-line comment"); buildExp(" as select from I_AnyEntity as AnyAlias"); buildExp(""); buildExp("{"); @@ -715,14 +502,6 @@ void testDoNotMoveComments() { buildSrc("define view entity C_AnyEntity"); buildSrc(" // single-line comment"); buildSrc("// @Anno.subAnno"); - buildSrc("with"); - buildSrc("parameters"); - buildSrc("// comment"); - buildSrc("P_AnyParam : AnyType,"); - buildSrc(" P_OtherParam : OtherType,"); - buildSrc(" P_ThirdParam : ThirdType"); - buildSrc(" // single-line comment"); - buildSrc("// @Anno.subAnno"); buildSrc(" as select from I_AnyEntity as AnyAlias"); buildSrc(""); buildSrc("{"); @@ -733,14 +512,6 @@ void testDoNotMoveComments() { buildExp("define view entity C_AnyEntity"); buildExp(" // single-line comment"); buildExp("// @Anno.subAnno"); - buildExp(" with parameters"); - buildExp(" // comment"); - buildExp(" P_AnyParam : AnyType,"); - buildExp(" P_OtherParam : OtherType,"); - buildExp(" P_ThirdParam : ThirdType"); - buildExp(" // single-line comment"); - buildExp("// @Anno.subAnno"); - buildExp(""); buildExp(" as select from I_AnyEntity as AnyAlias"); buildExp(""); buildExp("{");