001package gudusoft.gsqlparser.pp2.token; 002 003import gudusoft.gsqlparser.pp.para.styleenums.TCaseOption; 004 005/** 006 * Changes to tokens or comments that the user explicitly asked a formatter to 007 * make, which the content check must therefore not count as "the output 008 * changed the SQL". 009 * 010 * <p>Each transformation is accepted only in its <b>exact expected form</b>: 011 * given the input token and the requested setting, the output token must be 012 * either unchanged or exactly the expected text. Everything a transformation 013 * does not cover is compared as before. Nothing is compared "case-insensitively" 014 * or "ignored" as a blanket rule, so a formatter that makes a different change 015 * than the one requested is still caught. 016 * 017 * <ul> 018 * <li>{@code variableCase}: variables ({@code @Total}, {@code :host}) may have 019 * the requested case applied to the part after their prefix.</li> 020 * <li>{@code quotedIdentifierCase}: delimited names ({@code "Name"}, 021 * {@code [Name]}) may have the requested case applied inside the 022 * delimiters.</li> 023 * <li>{@code compactComments}: compact mode may rewrite a line comment 024 * {@code -- x} as {@code /* -- x *}{@code /} (with or without the space 025 * before the closing delimiter), so it cannot swallow the rest of a 026 * compacted line.</li> 027 * <li>{@code removeComments}: comments may be removed, except optimizer hints 028 * ({@code /*+ ... *}{@code /}), which must stay byte-exact and in order.</li> 029 * </ul> 030 * 031 * <p>Used by {@link TokenEquivalence} for pp2's guards (through 032 * {@code Pp2FormatOptions.transformPolicy}) and by the format worker's checks, 033 * so every layer applies the same contract. 034 */ 035public final class TransformPolicy { 036 037 /** No transformation allowed: the plain content check. */ 038 public static final TransformPolicy NONE = new TransformPolicy(null, null, false, false); 039 040 private final TCaseOption variableCase; 041 private final TCaseOption quotedIdentifierCase; 042 private final boolean compactComments; 043 private final boolean removeComments; 044 045 /** 046 * @param variableCase requested variable case, or {@code null} 047 * @param quotedIdentifierCase requested delimited-name case, or {@code null} 048 * @param compactComments compact mode's line-comment rewrite allowed 049 * @param removeComments comment removal (hints kept) allowed 050 */ 051 public TransformPolicy(TCaseOption variableCase, TCaseOption quotedIdentifierCase, 052 boolean compactComments, boolean removeComments) { 053 this.variableCase = noChangeAsNull(variableCase); 054 this.quotedIdentifierCase = noChangeAsNull(quotedIdentifierCase); 055 this.compactComments = compactComments; 056 this.removeComments = removeComments; 057 } 058 059 private static TCaseOption noChangeAsNull(TCaseOption c) { 060 return c == TCaseOption.CoNoChange ? null : c; 061 } 062 063 public TCaseOption getVariableCase() { 064 return variableCase; 065 } 066 067 public TCaseOption getQuotedIdentifierCase() { 068 return quotedIdentifierCase; 069 } 070 071 public boolean isCompactComments() { 072 return compactComments; 073 } 074 075 public boolean isRemoveComments() { 076 return removeComments; 077 } 078 079 public boolean isNone() { 080 return variableCase == null && quotedIdentifierCase == null && !compactComments && !removeComments; 081 } 082 083 @Override 084 public String toString() { 085 return "TransformPolicy{variableCase=" + variableCase + ", quotedIdentifierCase=" + quotedIdentifierCase 086 + ", compactComments=" + compactComments + ", removeComments=" + removeComments + "}"; 087 } 088}