99
99
* and partially re-written to satisfy the above requirements.
100
100
*/
101
101
public abstract class DocsV3Support {
102
+ public record Param (DataType dataType , List <FunctionAppliesTo > appliesTo ) {}
103
+
102
104
private static final Logger logger = LogManager .getLogger (DocsV3Support .class );
103
105
104
106
private static final String DOCS_WARNING_JSON =
@@ -372,15 +374,15 @@ public License.OperationMode invoke(List<DataType> fieldTypes) throws Exception
372
374
protected final String category ;
373
375
protected final String name ;
374
376
protected final FunctionDefinition definition ;
375
- protected final Supplier <Map <List <DataType >, DataType >> signatures ;
377
+ protected final Supplier <Map <List <Param >, DataType >> signatures ;
376
378
protected final Callbacks callbacks ;
377
379
private final LicenseRequirementChecker licenseChecker ;
378
380
379
381
protected DocsV3Support (
380
382
String category ,
381
383
String name ,
382
384
Class <?> testClass ,
383
- Supplier <Map <List <DataType >, DataType >> signatures ,
385
+ Supplier <Map <List <Param >, DataType >> signatures ,
384
386
Callbacks callbacks
385
387
) {
386
388
this (category , name , null , testClass , signatures , callbacks );
@@ -391,7 +393,7 @@ private DocsV3Support(
391
393
String name ,
392
394
FunctionDefinition definition ,
393
395
Class <?> testClass ,
394
- Supplier <Map <List <DataType >, DataType >> signatures ,
396
+ Supplier <Map <List <Param >, DataType >> signatures ,
395
397
Callbacks callbacks
396
398
) {
397
399
this .category = category ;
@@ -571,7 +573,7 @@ private FunctionDocsSupport(String name, Class<?> testClass, Callbacks callbacks
571
573
String name ,
572
574
Class <?> testClass ,
573
575
FunctionDefinition definition ,
574
- Supplier <Map <List <DataType >, DataType >> signatures ,
576
+ Supplier <Map <List <Param >, DataType >> signatures ,
575
577
Callbacks callbacks
576
578
) {
577
579
super ("functions" , name , definition , testClass , signatures , callbacks );
@@ -662,10 +664,27 @@ private void renderFunctionNamedParams(EsqlFunctionRegistry.MapArgSignature mapA
662
664
writeToTempSnippetsDir ("functionNamedParams" , rendered .toString ());
663
665
}
664
666
665
- private String makeAppliesToText (FunctionAppliesTo [] functionAppliesTos , boolean preview ) {
667
+ /**
668
+ * Build the {@code {applies_to}} annotation for the docs to tell users which version of
669
+ * Elasticsearch first supported this function/operator/signature.
670
+ * @param functionAppliesTos The version information for stateful Elasticsearch
671
+ * @param preview Is this tech preview? Effectively just generates the
672
+ * {@code serverless: preview} annotation if true and nothing if false.
673
+ * @param oneLine Should we generate a single line variant of the {@code {applies_to}}
674
+ * annotation compatible with tables (true) or the more readable
675
+ * multi-line variant (false)?
676
+ * @return Text of the {@code {applies_to}} annotation
677
+ */
678
+ private static String makeAppliesToText (List <FunctionAppliesTo > functionAppliesTos , boolean preview , boolean oneLine ) {
666
679
StringBuilder appliesToText = new StringBuilder ();
667
- if (functionAppliesTos .length > 0 ) {
668
- appliesToText .append ("```{applies_to}\n " );
680
+ if (false == functionAppliesTos .isEmpty ()) {
681
+ if (oneLine ) {
682
+ appliesToText .append (" {applies_to}" );
683
+ appliesToText .append ("`" );
684
+ } else {
685
+ appliesToText .append ("```" );
686
+ appliesToText .append ("{applies_to}\n " );
687
+ }
669
688
StringBuilder stackEntries = new StringBuilder ();
670
689
671
690
for (FunctionAppliesTo appliesTo : functionAppliesTos ) {
@@ -680,15 +699,21 @@ private String makeAppliesToText(FunctionAppliesTo[] functionAppliesTos, boolean
680
699
681
700
// Add the stack entries
682
701
if (stackEntries .isEmpty () == false ) {
683
- appliesToText .append ("stack: " ).append (stackEntries ).append ("\n " );
702
+ appliesToText .append ("stack: " ).append (stackEntries );
703
+ if (false == oneLine ) {
704
+ appliesToText .append ('\n' );
705
+ }
684
706
}
685
707
686
708
// Only specify serverless if it's preview, using the preview boolean (GA is the default)
687
709
if (preview ) {
688
- appliesToText .append ("serverless: preview\n " );
710
+ appliesToText .append ("serverless: preview" );
711
+ if (false == oneLine ) {
712
+ appliesToText .append ('\n' );
713
+ }
689
714
}
690
715
691
- appliesToText .append ("```\n " );
716
+ appliesToText .append (oneLine ? "`" : "```\n " );
692
717
}
693
718
return appliesToText .toString ();
694
719
}
@@ -711,7 +736,7 @@ private void renderFullLayout(FunctionInfo info, boolean hasExamples, boolean ha
711
736
.replace ("$NAME$" , name )
712
737
.replace ("$CATEGORY$" , category )
713
738
.replace ("$UPPER_NAME$" , name .toUpperCase (Locale .ROOT ))
714
- .replace ("$APPLIES_TO$" , makeAppliesToText (info .appliesTo (), info .preview ()))
739
+ .replace ("$APPLIES_TO$" , makeAppliesToText (Arrays . asList ( info .appliesTo ()) , info .preview (), false ))
715
740
);
716
741
for (String section : new String [] { "parameters" , "description" , "types" }) {
717
742
rendered .append (addInclude (section ));
@@ -755,7 +780,7 @@ public OperatorsDocsSupport(
755
780
String name ,
756
781
Class <?> testClass ,
757
782
OperatorConfig op ,
758
- Supplier <Map <List <DataType >, DataType >> signatures ,
783
+ Supplier <Map <List <Param >, DataType >> signatures ,
759
784
Callbacks callbacks
760
785
) {
761
786
super ("operators" , name , testClass , signatures , callbacks );
@@ -888,7 +913,9 @@ void renderDocsForOperators(
888
913
if (mapParamInfo != null ) {
889
914
args .add (mapParam (mapParamInfo ));
890
915
} else {
891
- Param paramInfo = params [i ].getAnnotation (Param .class );
916
+ org .elasticsearch .xpack .esql .expression .function .Param paramInfo = params [i ].getAnnotation (
917
+ org .elasticsearch .xpack .esql .expression .function .Param .class
918
+ );
892
919
args .add (paramInfo != null ? param (paramInfo , false ) : paramWithoutAnnotation (params [i ].getName ()));
893
920
}
894
921
}
@@ -956,7 +983,7 @@ public CommandsDocsSupport(
956
983
Class <?> testClass ,
957
984
LogicalPlan command ,
958
985
List <EsqlFunctionRegistry .ArgSignature > args ,
959
- Supplier <Map <List <DataType >, DataType >> signatures ,
986
+ Supplier <Map <List <Param >, DataType >> signatures ,
960
987
Callbacks callbacks
961
988
) {
962
989
super ("commands" , name , testClass , signatures , callbacks );
@@ -1016,12 +1043,12 @@ void renderTypes(String name, List<EsqlFunctionRegistry.ArgSignature> args) thro
1016
1043
}
1017
1044
1018
1045
Map <String , List <String >> compactedTable = new TreeMap <>();
1019
- for (Map .Entry <List <DataType >, DataType > sig : this .signatures .get ().entrySet ()) {
1046
+ for (Map .Entry <List <DocsV3Support . Param >, DataType > sig : this .signatures .get ().entrySet ()) {
1020
1047
if (shouldHideSignature (sig .getKey (), sig .getValue ())) {
1021
1048
continue ;
1022
1049
}
1023
- String mainType = sig .getKey ().getFirst ().esNameIfPossible ();
1024
- String secondaryType = sig .getKey ().get (1 ).esNameIfPossible ();
1050
+ String mainType = sig .getKey ().getFirst ().dataType (). esNameIfPossible ();
1051
+ String secondaryType = sig .getKey ().get (1 ).dataType (). esNameIfPossible ();
1025
1052
List <String > secondaryTypes = compactedTable .computeIfAbsent (mainType , (k ) -> new ArrayList <>());
1026
1053
secondaryTypes .add (secondaryType );
1027
1054
}
@@ -1079,7 +1106,7 @@ void renderTypes(String name, List<EsqlFunctionRegistry.ArgSignature> args) thro
1079
1106
}
1080
1107
1081
1108
List <String > table = new ArrayList <>();
1082
- for (Map .Entry <List <DataType >, DataType > sig : this .signatures .get ().entrySet ()) { // TODO flip to using sortedSignatures
1109
+ for (Map .Entry <List <DocsV3Support . Param >, DataType > sig : this .signatures .get ().entrySet ()) { // TODO flip to using sortedSignatures
1083
1110
if (shouldHideSignature (sig .getKey (), sig .getValue ())) {
1084
1111
continue ;
1085
1112
}
@@ -1104,18 +1131,21 @@ void renderTypes(String name, List<EsqlFunctionRegistry.ArgSignature> args) thro
1104
1131
1105
1132
private static String getTypeRow (
1106
1133
List <EsqlFunctionRegistry .ArgSignature > args ,
1107
- Map .Entry <List <DataType >, DataType > sig ,
1134
+ Map .Entry <List <Param >, DataType > sig ,
1108
1135
List <String > argNames ,
1109
1136
boolean showResultColumn
1110
1137
) {
1111
1138
StringBuilder b = new StringBuilder ("| " );
1112
1139
for (int i = 0 ; i < sig .getKey ().size (); i ++) {
1113
- DataType argType = sig .getKey ().get (i );
1140
+ Param param = sig .getKey ().get (i );
1114
1141
EsqlFunctionRegistry .ArgSignature argSignature = args .get (i );
1115
1142
if (argSignature .mapArg ()) {
1116
1143
b .append ("named parameters" );
1117
1144
} else {
1118
- b .append (argType .esNameIfPossible ());
1145
+ b .append (param .dataType ().esNameIfPossible ());
1146
+ if (param .appliesTo () != null ) {
1147
+ b .append (FunctionDocsSupport .makeAppliesToText (param .appliesTo (), false , true ));
1148
+ }
1119
1149
}
1120
1150
b .append (" | " );
1121
1151
}
@@ -1274,7 +1304,7 @@ void renderKibanaFunctionDefinition(
1274
1304
builder .endObject ();
1275
1305
} else {
1276
1306
int minArgCount = (int ) args .stream ().filter (a -> false == a .optional ()).count ();
1277
- for (Map .Entry <List <DataType >, DataType > sig : sortedSignatures ()) {
1307
+ for (Map .Entry <List <DocsV3Support . Param >, DataType > sig : sortedSignatures ()) {
1278
1308
if (variadic && sig .getKey ().size () > args .size ()) {
1279
1309
// For variadic functions we test much longer signatures, let’s just stop at the last one
1280
1310
continue ;
@@ -1302,15 +1332,15 @@ void renderKibanaFunctionDefinition(
1302
1332
.collect (Collectors .joining (", " ))
1303
1333
);
1304
1334
} else {
1305
- builder .field ("type" , sig .getKey ().get (i ).esNameIfPossible ());
1335
+ builder .field ("type" , sig .getKey ().get (i ).dataType (). esNameIfPossible ());
1306
1336
}
1307
1337
builder .field ("optional" , arg .optional ());
1308
1338
String cleanedParamDesc = removeAppliesToBlocks (arg .description ());
1309
1339
builder .field ("description" , cleanedParamDesc );
1310
1340
builder .endObject ();
1311
1341
}
1312
1342
builder .endArray ();
1313
- license = licenseChecker .invoke (sig .getKey ());
1343
+ license = licenseChecker .invoke (sig .getKey (). stream (). map ( Param :: dataType ). toList () );
1314
1344
if (license != null && license != License .OperationMode .BASIC ) {
1315
1345
builder .field ("license" , license .toString ());
1316
1346
}
@@ -1358,8 +1388,8 @@ private static String removeAppliesToBlocks(String content) {
1358
1388
return content .replaceAll ("\\ s*\\ {applies_to\\ }`[^`]*`\\ s*" , "" );
1359
1389
}
1360
1390
1361
- private List <Map .Entry <List <DataType >, DataType >> sortedSignatures () {
1362
- List <Map .Entry <List <DataType >, DataType >> sortedSignatures = new ArrayList <>(signatures .get ().entrySet ());
1391
+ private List <Map .Entry <List <DocsV3Support . Param >, DataType >> sortedSignatures () {
1392
+ List <Map .Entry <List <DocsV3Support . Param >, DataType >> sortedSignatures = new ArrayList <>(signatures .get ().entrySet ());
1363
1393
sortedSignatures .sort ((lhs , rhs ) -> {
1364
1394
int maxlen = Math .max (lhs .getKey ().size (), rhs .getKey ().size ());
1365
1395
for (int i = 0 ; i < maxlen ; i ++) {
@@ -1369,7 +1399,7 @@ private List<Map.Entry<List<DataType>, DataType>> sortedSignatures() {
1369
1399
if (rhs .getKey ().size () <= i ) {
1370
1400
return 1 ;
1371
1401
}
1372
- int c = lhs .getKey ().get (i ).esNameIfPossible ().compareTo (rhs .getKey ().get (i ).esNameIfPossible ());
1402
+ int c = lhs .getKey ().get (i ).dataType (). esNameIfPossible ().compareTo (rhs .getKey ().get (i ). dataType ( ).esNameIfPossible ());
1373
1403
if (c != 0 ) {
1374
1404
return c ;
1375
1405
}
0 commit comments