Slice Metadata Directives
Overview
Slice has the concept of a metadata directive. For example:
["java:type:java.util.LinkedList<Integer>"] sequence<int> IntSeq;
A metadata directive can appear as a prefix to any Slice definition. Metadata directives appear in a pair of square brackets and contain one or more string literals separated by commas. For example, the following is a syntactically valid metadata directive containing two strings:
["a", "b"] interface Example {}
Metadata directives are not part of the Slice language per se: the presence of a metadata directive has no effect on the client-server contract, that is, metadata directives do not change the Slice type system in any way. Instead, metadata directives are targeted at specific back-ends, such as the code generator for a particular language mapping. In the preceding example, the java:
prefix indicates that the directive is targeted at the Slice to Java compiler.
Metadata directives permit you to provide supplementary information that does not change the Slice types being defined, but somehow influences how the compiler will generate code for these definitions. For example, a metadata directive java:type:java.util.LinkedList<T>
instructs the Slice to Java compiler to map a sequence to a linked list instead of an array (which is the default).
Metadata directives are also used to create skeletons that support Asynchronous Method Dispatch (AMD) in some languages.
Apart from metadata directives that are attached to a specific definition, there are also file metadata directives. For example:
[["cpp:dll-export:WIDGET_API"]]
Note that a file metadata directive is enclosed by double square brackets, whereas a local metadata directive (one that is attached to a specific definition) is enclosed by single square brackets. File metadata directives are used to pass instructions that affect the entire Slice file. File metadata directives must precede any definitions in a file (but can appear following any #include
directives).
We describe below the metadata directives you can use.
General Metadata Directives
amd
This directive applies to interfaces and operations. It enables code generation for asynchronous method dispatch. (See Operations for details).
deprecated[:message]
deprecate[:message]
This directive allows you to emit a deprecation warning for Slice constructs.
format
This directive defines the encoding format used for any classes or exceptions marshaled as the arguments or results of an operation. The tag can be applied to an interface, which affects all of its operations, or to individual operations. Legal values for the tag are format:sliced
, format:compact
, and format:default
. A tag specified for an operation overrides any setting applied to its enclosing interface. The Ice.Default.SlicedFormat property defines the behavior when no tag is present.
marshaled-result
This directive applies to operations and changes the return type of mapped skeleton methods in C++, C#, and Java. It has no effect on the client-side mapping.
With this directive, the mapped skeleton method returns a “marshaled result” struct or class that marshals the return value and out parameters immediately in its constructor. This allows you to perform the marshaling in a thread-safe manner, typically while holding a mutex lock.
For example:
sequence<int> IntSeq;
sequence<IntSeq> IntIntSeq;
sequence<string> StringSeq;
class Grid
{
StringSeq xLabels;
StringSeq yLabels;
IntIntSeq values;
}
interface GridIntf
{
// We want to marshal the returned Grid object within a lock,
// and return a consistent object not affected by concurrent calls to
// clearValues.
["marshaled-result"]
["cs:identifier:GetGrid"]
Grid getGrid();
void clearValues();
}
A marshaled-result instance is specific to a request. Do not cache a marshaled result and return it for another request.
suppress-warning
This file directive allows to suppress Slice compiler warnings. It applies to all definitions in the Slice file that includes this directive. If one or more categories are specified (for example "suppress-warning:invalid-metadata"
or "suppress-warning:deprecated, invalid-metadata"
) only warnings matching these categories will be suppressed, otherwise all warnings are suppressed. The categories are described in the following table:
Suppress Warning Category | Description |
---|---|
| Suppress all Slice compiler warnings. Equivalent to |
| Suppress warnings related to deprecated features. |
| Suppress warnings related to invalid doc-comments. |
Language-Specific Metadata Directives
The metadata directives for JavaScript uses the js
prefix.
js:defined-in:file-name
This directive apply to forward declarations. The Slice compiler needs to know where the forward declared type is defined in order to generate the correct JavaScript import statements, file-name must be the relative path to the file that defines the forward declared type.
js:identifier:javascript-identifier
This directive applies to all Slice constructs, and instructs the Slice compiler to use the specified javascript-identifier
.
For example:
struct CompilerInfo
{
["js:identifier:debuggerName"]
string debugger;
}
The js:identifier
directive in this example ensures that debugger
filed, a reserved JavaScript keyword, is mapped debuggerName
.
js:module:module-name
This file directive allows you to tell the Slice-to-JavaScript compiler how the generated modules should be imported by other generated code. It is mainly useful when you want to publish your generated code as an npm package, so that other projects can import your Slice definitions by package name rather than by relative path.
For example, the Slice definitions for the Ice built-in files use:
For example the Slice definitions for Ice builtin files use:
// Ice/Locator.ice
[["js:module:@zeroc/ice"]]
#include "Identity.ice"
module Ice
{
...
}
When you include Ice/Locator.ice
in your own Slice files, the generated code will import Ice
from @zeroc/ice
. Without this directive, the compiler would instead fall back on its default heuristic and generate a relative import, such as from Ice/Locator.js
.
Other files that use the same js:module directive will still import each other with relative paths, since they are assumed to be part of the same npm package.