/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.template.soy.jssrc;
import com.google.common.base.Preconditions;
/**
* Compilation options for the JS Src output target (backend).
*
*/
public final class SoyJsSrcOptions implements Cloneable {
/** Whether to allow deprecated syntax (semi backwards compatible mode). */
private boolean shouldAllowDeprecatedSyntax;
/** Whether we should generate JSDoc with type info for the Closure Compiler. */
private boolean shouldGenerateJsdoc;
/** Whether we should generate code to provide/require Soy namespaces. */
private boolean shouldProvideRequireSoyNamespaces;
/** Whether we should generate code to provide/require template JS functions. */
private boolean shouldProvideRequireJsFunctions;
/** Whether we should generate code to provide both Soy namespaces and JS functions. */
private boolean shouldProvideBothSoyNamespacesAndJsFunctions;
/** Whether we should generate code to declare the top level namespace. */
private boolean shouldDeclareTopLevelNamespaces;
/** Whether we should generate code to declare goog.modules. */
private boolean shouldGenerateGoogModules;
/** Whether we should generate Closure Library message definitions (i.e. goog.getMsg). */
private boolean shouldGenerateGoogMsgDefs;
/** Whether the Closure Library messages are external, i.e. "MSG_EXTERNAL_[soyGeneratedMsgId]". */
private boolean googMsgsAreExternal;
/**
* The bidi global directionality as a static value, 1: ltr, -1: rtl, 0: unspecified. If 0, and
* useGoogIsRtlForBidiGlobalDir is false, the bidi global directionality will actually be inferred
* from the message bundle locale. This must not be the case when shouldGenerateGoogMsgDefs is
* true, but is the recommended mode of operation otherwise.
*/
private int bidiGlobalDir;
/**
* Whether to determine the bidi global direction at template runtime by evaluating
* goog.i18n.bidi.IS_RTL. May only be true when both shouldGenerateGoogMsgDefs and either
* shouldProvideRequireSoyNamespaces or shouldProvideRequireJsFunctions is true.
*/
private boolean useGoogIsRtlForBidiGlobalDir;
public SoyJsSrcOptions() {
shouldAllowDeprecatedSyntax = false;
shouldGenerateJsdoc = false;
shouldProvideRequireSoyNamespaces = false;
shouldProvideRequireJsFunctions = false;
shouldProvideBothSoyNamespacesAndJsFunctions = false;
shouldDeclareTopLevelNamespaces = true;
shouldGenerateGoogMsgDefs = false;
shouldGenerateGoogModules = false;
googMsgsAreExternal = false;
bidiGlobalDir = 0;
useGoogIsRtlForBidiGlobalDir = false;
}
private SoyJsSrcOptions(SoyJsSrcOptions orig) {
this.shouldAllowDeprecatedSyntax = orig.shouldAllowDeprecatedSyntax;
this.shouldGenerateJsdoc = orig.shouldGenerateJsdoc;
this.shouldProvideRequireSoyNamespaces = orig.shouldProvideRequireSoyNamespaces;
this.shouldProvideRequireJsFunctions = orig.shouldProvideRequireJsFunctions;
this.shouldProvideBothSoyNamespacesAndJsFunctions =
orig.shouldProvideBothSoyNamespacesAndJsFunctions;
this.shouldDeclareTopLevelNamespaces = orig.shouldDeclareTopLevelNamespaces;
this.shouldGenerateGoogModules = orig.shouldGenerateGoogModules;
this.shouldGenerateGoogMsgDefs = orig.shouldGenerateGoogMsgDefs;
this.googMsgsAreExternal = orig.googMsgsAreExternal;
this.bidiGlobalDir = orig.bidiGlobalDir;
this.useGoogIsRtlForBidiGlobalDir = orig.useGoogIsRtlForBidiGlobalDir;
}
/**
* Sets whether to allow deprecated syntax (semi backwards compatible mode).
*
* @param shouldAllowDeprecatedSyntax The value to set.
*/
// TODO SOON: Deprecate. (Use setDeclaredSyntaxVersionName() on SoyFileSet or SoyGeneralOptions.)
public void setShouldAllowDeprecatedSyntax(boolean shouldAllowDeprecatedSyntax) {
this.shouldAllowDeprecatedSyntax = shouldAllowDeprecatedSyntax;
}
/**
* Returns whether we're set to allow deprecated syntax (semi backwards compatible mode).
*
* @deprecated Use {@code SoyGeneralOptions.getDeclaredSyntaxVersion()}.
*/
@Deprecated
public boolean shouldAllowDeprecatedSyntax() {
return shouldAllowDeprecatedSyntax;
}
/**
* Sets whether we should generate JSDoc with type info for the Closure Compiler.
*
* @param shouldGenerateJsdoc The value to set.
*/
public void setShouldGenerateJsdoc(boolean shouldGenerateJsdoc) {
this.shouldGenerateJsdoc = shouldGenerateJsdoc;
}
/** Returns whether we should generate JSDoc with type info for the Closure Compiler. */
public boolean shouldGenerateJsdoc() {
return shouldGenerateJsdoc;
}
/**
* Sets whether we should generate code to provide/require Soy namespaces.
*
* @param shouldProvideRequireSoyNamespaces The value to set.
*/
public void setShouldProvideRequireSoyNamespaces(boolean shouldProvideRequireSoyNamespaces) {
// TODO(b/24275162) Replace these variables with a single Enum
this.shouldProvideRequireSoyNamespaces = shouldProvideRequireSoyNamespaces;
Preconditions.checkState(
!(this.shouldProvideRequireSoyNamespaces && this.shouldProvideRequireJsFunctions),
"Must not enable both shouldProvideRequireSoyNamespaces and"
+ " shouldProvideRequireJsFunctions.");
Preconditions.checkState(
!(!this.shouldDeclareTopLevelNamespaces && this.shouldProvideRequireSoyNamespaces),
"Turning off shouldDeclareTopLevelNamespaces has no meaning when"
+ " shouldProvideRequireSoyNamespaces is enabled.");
}
/** Returns whether we're set to generate code to provide/require Soy namespaces. */
public boolean shouldProvideRequireSoyNamespaces() {
return shouldProvideRequireSoyNamespaces;
}
/**
* Sets whether we should generate code to provide/require template JS functions.
*
* @param shouldProvideRequireJsFunctions The value to set.
*/
public void setShouldProvideRequireJsFunctions(boolean shouldProvideRequireJsFunctions) {
// TODO(b/24275162) Replace these variables with a single Enum
this.shouldProvideRequireJsFunctions = shouldProvideRequireJsFunctions;
Preconditions.checkState(
!(this.shouldProvideRequireSoyNamespaces && this.shouldProvideRequireJsFunctions),
"Must not enable both shouldProvideRequireSoyNamespaces and"
+ " shouldProvideRequireJsFunctions.");
Preconditions.checkState(
!(!this.shouldDeclareTopLevelNamespaces && this.shouldProvideRequireJsFunctions),
"Turning off shouldDeclareTopLevelNamespaces has no meaning when"
+ " shouldProvideRequireJsFunctions is enabled.");
}
/** Returns whether we're set to generate code to provide/require template JS functions. */
public boolean shouldProvideRequireJsFunctions() {
return shouldProvideRequireJsFunctions;
}
/**
* Sets whether we should generate code to provide both Soy namespaces and JS functions.
*
* @param shouldProvideBothSoyNamespacesAndJsFunctions The value to set.
*/
public void setShouldProvideBothSoyNamespacesAndJsFunctions(
boolean shouldProvideBothSoyNamespacesAndJsFunctions) {
// TODO(b/24275162) Replace these variables with a single Enum
this.shouldProvideBothSoyNamespacesAndJsFunctions =
shouldProvideBothSoyNamespacesAndJsFunctions;
if (shouldProvideBothSoyNamespacesAndJsFunctions) {
Preconditions.checkState(
this.shouldProvideRequireSoyNamespaces || this.shouldProvideRequireJsFunctions,
"Must only enable shouldProvideBothSoyNamespacesAndJsFunctions after enabling either"
+ " shouldProvideRequireSoyNamespaces or shouldProvideRequireJsFunctions.");
}
}
/** Returns whether we should generate code to provide both Soy namespaces and JS functions. */
public boolean shouldProvideBothSoyNamespacesAndJsFunctions() {
return shouldProvideBothSoyNamespacesAndJsFunctions;
}
/**
* Sets whether we should generate code to declare the top level namespace.
*
* @param shouldDeclareTopLevelNamespaces The value to set.
*/
public void setShouldDeclareTopLevelNamespaces(boolean shouldDeclareTopLevelNamespaces) {
// TODO(b/24275162) Replace these variables with a single Enum
this.shouldDeclareTopLevelNamespaces = shouldDeclareTopLevelNamespaces;
Preconditions.checkState(
!(!this.shouldDeclareTopLevelNamespaces && this.shouldProvideRequireSoyNamespaces),
"Turning off shouldDeclareTopLevelNamespaces has no meaning when"
+ " shouldProvideRequireSoyNamespaces is enabled.");
Preconditions.checkState(
!(!this.shouldDeclareTopLevelNamespaces && this.shouldProvideRequireJsFunctions),
"Turning off shouldDeclareTopLevelNamespaces has no meaning when"
+ " shouldProvideRequireJsFunctions is enabled.");
}
/** Returns whether we should attempt to declare the top level namespace. */
public boolean shouldDeclareTopLevelNamespaces() {
return shouldDeclareTopLevelNamespaces;
}
/**
* Sets whether goog.modules should be generated.
*
* @param shouldGenerateGoogModules The value to set.
*/
public void setShouldGenerateGoogModules(boolean shouldGenerateGoogModules) {
// TODO(b/24275162) Replace these variables with a single Enum
this.shouldGenerateGoogModules = shouldGenerateGoogModules;
if (shouldGenerateGoogModules) {
Preconditions.checkState(
!shouldDeclareTopLevelNamespaces
&& !shouldProvideRequireSoyNamespaces
&& !shouldProvideRequireJsFunctions
&& !shouldProvideBothSoyNamespacesAndJsFunctions,
"If generating goog.modules, shouldDeclareTopLevelNamespaces, "
+ "shouldProvideRequireSoyNamespaces, shouldProvideRequireJsFunctions and "
+ "shouldProvideBothSoyNamespacesAndJsFunctions should not be enabled.");
}
}
/** Returns whether goog.modules should be generated. */
public boolean shouldGenerateGoogModules() {
return shouldGenerateGoogModules;
}
/**
* Sets whether we should generate Closure Library message definitions (i.e. goog.getMsg).
*
* @param shouldGenerateGoogMsgDefs The value to set.
*/
public void setShouldGenerateGoogMsgDefs(boolean shouldGenerateGoogMsgDefs) {
this.shouldGenerateGoogMsgDefs = shouldGenerateGoogMsgDefs;
}
/** Returns whether we should generate Closure Library message definitions (i.e. goog.getMsg). */
public boolean shouldGenerateGoogMsgDefs() {
return shouldGenerateGoogMsgDefs;
}
/**
* Sets whether the generated Closure Library message definitions are for external messages (only
* applicable if shouldGenerateGoogMsgDefs is true).
*
* <p>If this option is true, then we generate
*
* <pre>{@code var MSG_EXTERNAL_[soyGeneratedMsgId] = goog.getMsg(...);}</pre>
*
* <p>If this option is false, then we generate
*
* <pre>{@code var MSG_UNNAMED_[uniquefier] = goog.getMsg(...);}</pre>
*
* @param googMsgsAreExternal The value to set.
*/
public void setGoogMsgsAreExternal(boolean googMsgsAreExternal) {
this.googMsgsAreExternal = googMsgsAreExternal;
}
/**
* Returns whether the generated Closure Library message definitions are for external messages
* (only applicable if shouldGenerateGoogMsgDefs is true).
*
* <p>If this option is true, then we generate
*
* <pre>{@code var MSG_EXTERNAL_[soyGeneratedMsgId] = goog.getMsg(...);}</pre>
*
* <p>If this option is false, then we generate
*
* <pre>{@code var MSG_UNNAMED_[uniquefier] = goog.getMsg(...);}</pre>
*/
public boolean googMsgsAreExternal() {
return googMsgsAreExternal;
}
/**
* Sets the bidi global directionality to a static value, 1: ltr, -1: rtl, 0: unspecified. If 0,
* and useGoogIsRtlForBidiGlobalDir is false, the bidi global directionality will actually be
* inferred from the message bundle locale. This is the recommended mode of operation when
* shouldGenerateGoogMsgDefs is false. When shouldGenerateGoogMsgDefs is true, the bidi global
* direction can not be left unspecified, but the recommended way of doing so is via
* setUseGoogIsRtlForBidiGlobalDir(true). Thus, whether shouldGenerateGoogMsgDefs is true or not,
* THERE IS USUALLY NO NEED TO USE THIS METHOD!
*
* @param bidiGlobalDir 1: ltr, -1: rtl, 0: unspecified. Checks that no other value is used.
*/
public void setBidiGlobalDir(int bidiGlobalDir) {
Preconditions.checkArgument(
bidiGlobalDir >= -1 && bidiGlobalDir <= 1,
"bidiGlobalDir must be 1 for LTR, or -1 for RTL (or 0 to leave unspecified).");
Preconditions.checkState(
!useGoogIsRtlForBidiGlobalDir || bidiGlobalDir == 0,
"Must not specify both bidiGlobalDir and useGoogIsRtlForBidiGlobalDir.");
this.bidiGlobalDir = bidiGlobalDir;
}
/** Returns the static bidi global directionality, 1: ltr, -1: rtl, 0: unspecified. */
public int getBidiGlobalDir() {
return bidiGlobalDir;
}
/**
* Sets the Javascript code snippet that will evaluate at template runtime to a boolean value
* indicating whether the bidi global direction is rtl. Can only be used when
* shouldGenerateGoogMsgDefs is true.
*
* @param useGoogIsRtlForBidiGlobalDir Whether to determine the bidi global direction at template
* runtime by evaluating goog.i18n.bidi.IS_RTL.
*/
public void setUseGoogIsRtlForBidiGlobalDir(boolean useGoogIsRtlForBidiGlobalDir) {
Preconditions.checkState(
!useGoogIsRtlForBidiGlobalDir || shouldGenerateGoogMsgDefs,
"Do not specify useGoogIsRtlForBidiGlobalDir without shouldGenerateGoogMsgDefs.");
Preconditions.checkState(
!useGoogIsRtlForBidiGlobalDir
|| shouldProvideRequireSoyNamespaces
|| shouldProvideRequireJsFunctions
|| shouldGenerateGoogModules,
"Do not specify useGoogIsRtlForBidiGlobalDir without one of"
+ " shouldProvideRequireSoyNamespaces, shouldProvideRequireJsFunctions or "
+ " shouldGenerateGoogModules.");
Preconditions.checkState(
!useGoogIsRtlForBidiGlobalDir || bidiGlobalDir == 0,
"Must not specify both bidiGlobalDir and useGoogIsRtlForBidiGlobalDir.");
this.useGoogIsRtlForBidiGlobalDir = useGoogIsRtlForBidiGlobalDir;
}
/**
* Returns whether to determine the bidi global direction at template runtime by evaluating
* goog.i18n.bidi.IS_RTL. May only be true when shouldGenerateGoogMsgDefs is true.
*/
public boolean getUseGoogIsRtlForBidiGlobalDir() {
return useGoogIsRtlForBidiGlobalDir;
}
@Override
public final SoyJsSrcOptions clone() {
return new SoyJsSrcOptions(this);
}
}