Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 72 additions & 10 deletions packages/custom-functions-metadata/src/parseTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ const EXCLUDEFROMAUTOCOMPLETE = "excludefromautocomplete";
const HELPURL_PARAM = "helpurl";
const LINKEDENTITYLOADSERVICE = "linkedentityloadservice";
const REQUIRESADDRESS = "requiresaddress";
const REQUIRESSTREAMADDRESS = "requiresstreamaddress";
const REQUIRESPARAMETERADDRESSES = "requiresparameteraddresses";
const REQUIRESSTREAMPARAMETERADDRESSES = "requiresstreamparameteraddresses";
const STREAMING = "streaming";
const VOLATILE = "volatile";
const SUPPORT_SYNC = "supportsync";
Expand Down Expand Up @@ -688,27 +690,46 @@ function getOptions(
isInvocationFunction: boolean,
extra: IFunctionExtras
): IFunctionOptions {
const addressRequired = isAddressRequired(func);
const streamAddressRequired = isStreamAddressRequired(func);
const parameterAddressesRequired = isRequiresParameterAddresses(func);
const streamParameterAddressesRequired = isRequiresStreamParameterAddresses(func);
const hasStreamingTag = hasTag(func, STREAMING);
const streamEnabled = isStreaming(func, isStreamingFunction);

const optionsItem: IFunctionOptions = {
cancelable: isCancelableTag(func, isCancelableFunction),
requiresAddress: isAddressRequired(func) && !isStreaming(func, isStreamingFunction),
requiresStreamAddress: isAddressRequired(func) && isStreaming(func, isStreamingFunction),
stream: isStreaming(func, isStreamingFunction),
requiresAddress: addressRequired && !streamEnabled,
requiresStreamAddress: streamAddressRequired || (addressRequired && streamEnabled),
stream: streamEnabled,
volatile: isVolatile(func),
requiresParameterAddresses:
isRequiresParameterAddresses(func) && !isStreaming(func, isStreamingFunction),
requiresParameterAddresses: parameterAddressesRequired && !streamEnabled,
requiresStreamParameterAddresses:
isRequiresParameterAddresses(func) && isStreaming(func, isStreamingFunction),
streamParameterAddressesRequired || (parameterAddressesRequired && streamEnabled),
excludeFromAutoComplete: isExcludedFromAutoComplete(func),
linkedEntityLoadService: isLinkedEntityLoadService(func),
capturesCallingObject: capturesCallingObject(func),
supportSync: supportSync(func),
action: isAction(func),
};

if (isAddressRequired(func) || isRequiresParameterAddresses(func)) {
let errorParam: string = isAddressRequired(func)
? "@requiresAddress"
: "@requiresParameterAddresses";
if (
addressRequired ||
streamAddressRequired ||
parameterAddressesRequired ||
streamParameterAddressesRequired
) {
let errorParam: string = "";

if (streamAddressRequired) {
errorParam = "@requiresStreamAddress";
} else if (addressRequired) {
errorParam = "@requiresAddress";
} else if (streamParameterAddressesRequired) {
errorParam = "@requiresStreamParameterAddresses";
} else {
errorParam = "@requiresParameterAddresses";
}

if (!isStreamingFunction && !isCancelableFunction && !isInvocationFunction) {
const functionPosition = getPosition(func, func.parameters.end);
Expand All @@ -717,13 +738,28 @@ function getOptions(
}
}

if (streamAddressRequired && !hasStreamingTag) {
const functionPosition = getPosition(func, func.parameters.end);
const errorString = "@requiresStreamAddress can only be used with @streaming.";
extra.errors.push(logError(errorString, functionPosition));
}

if (streamParameterAddressesRequired && !hasStreamingTag) {
const functionPosition = getPosition(func, func.parameters.end);
const errorString =
"@requiresStreamParameterAddresses can only be used with @streaming.";
extra.errors.push(logError(errorString, functionPosition));
}

if (
optionsItem.linkedEntityLoadService &&
(optionsItem.excludeFromAutoComplete ||
optionsItem.volatile ||
optionsItem.stream ||
optionsItem.requiresAddress ||
optionsItem.requiresStreamAddress ||
optionsItem.requiresParameterAddresses ||
optionsItem.requiresStreamParameterAddresses ||
optionsItem.capturesCallingObject)
) {
let errorParam: string = "";
Expand All @@ -737,8 +773,12 @@ function getOptions(
errorParam = "@streaming";
} else if (optionsItem.requiresAddress) {
errorParam = "@requiresAddress";
} else if (optionsItem.requiresStreamAddress) {
errorParam = "@requiresStreamAddress";
} else if (optionsItem.requiresParameterAddresses) {
errorParam = "@requiresParameterAddresses";
} else if (optionsItem.requiresStreamParameterAddresses) {
errorParam = "@requiresStreamParameterAddresses";
} else if (optionsItem.capturesCallingObject) {
errorParam = "@capturesCallingObject";
}
Expand All @@ -760,7 +800,9 @@ function getOptions(
optionsItem.volatile ||
optionsItem.stream ||
optionsItem.requiresAddress ||
optionsItem.requiresStreamAddress ||
optionsItem.requiresParameterAddresses ||
optionsItem.requiresStreamParameterAddresses ||
optionsItem.capturesCallingObject ||
optionsItem.linkedEntityLoadService ||
optionsItem.supportSync)
Expand All @@ -776,8 +818,12 @@ function getOptions(
errorParam = "@streaming";
} else if (optionsItem.requiresAddress) {
errorParam = "@requiresAddress";
} else if (optionsItem.requiresStreamAddress) {
errorParam = "@requiresStreamAddress";
} else if (optionsItem.requiresParameterAddresses) {
errorParam = "@requiresParameterAddresses";
} else if (optionsItem.requiresStreamParameterAddresses) {
errorParam = "@requiresStreamParameterAddresses";
} else if (optionsItem.capturesCallingObject) {
errorParam = "@capturesCallingObject";
} else if (optionsItem.linkedEntityLoadService) {
Expand Down Expand Up @@ -1109,6 +1155,14 @@ function isAddressRequired(node: ts.Node): boolean {
return hasTag(node, REQUIRESADDRESS);
}

/**
* Returns true if requiresStreamAddress tag found in comments
* @param node jsDocs node
*/
function isStreamAddressRequired(node: ts.Node): boolean {
return hasTag(node, REQUIRESSTREAMADDRESS);
}

/**
* Returns true if RequiresParameterAddresses tag found in comments
* @param node jsDocs node
Expand All @@ -1117,6 +1171,14 @@ function isRequiresParameterAddresses(node: ts.Node): boolean {
return hasTag(node, REQUIRESPARAMETERADDRESSES);
}

/**
* Returns true if requiresStreamParameterAddresses tag found in comments
* @param node jsDocs node
*/
function isRequiresStreamParameterAddresses(node: ts.Node): boolean {
return hasTag(node, REQUIRESSTREAMPARAMETERADDRESSES);
}

/**
* Returns true if excludedFromAutoComplete tag found in comments
* @param node jsDocs node
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@requiresStreamAddress can only be used with @streaming. (10,53)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@requiresStreamAddress can only be used with @streaming. (10,98)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/**
* Test requires stream address without the @streaming tag.
* @param {CustomFunctions.StreamingInvocation<string>} invocation stream invocation
* @customfunction
* @requiresStreamAddress
*/
function streamAddressMissingStreamingTag(invocation) {
// Empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/**
* Test requires stream address without the @streaming tag.
* @param invocation stream invocation
* @customfunction
* @requiresStreamAddress
*/
function streamAddressMissingStreamingTag(invocation: CustomFunctions.StreamingInvocation<string>) {
// Empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@requiresStreamAddress can only be used with @streaming. (12,58)
@requiresStreamParameterAddresses can only be used with @streaming. (12,58)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@requiresStreamAddress can only be used with @streaming. (12,94)
@requiresStreamParameterAddresses can only be used with @streaming. (12,94)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/**
* Test requires stream addresses without streaming.
* @param {string} x string
* @param {CustomFunctions.Invocation} invocation invocation
* @customfunction
* @requiresStreamAddress
* @requiresStreamParameterAddresses
*/
function streamAddressRequiresStreamingTest(x, invocation) {
// Empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/**
* Test requires stream addresses without streaming.
* @param x string
* @param invocation invocation
* @customfunction
* @requiresStreamAddress
* @requiresStreamParameterAddresses
*/
function streamAddressRequiresStreamingTest(x: string, invocation: CustomFunctions.Invocation) {
// Empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"allowCustomDataForDataTypeAny": true,
"functions": [
{
"description": "Streams the address of the current cell.",
"id": "ADDRESSSTREAM",
"name": "ADDRESSSTREAM",
"options": {
"requiresStreamAddress": true,
"stream": true,
"requiresStreamParameterAddresses": true
},
"parameters": [],
"result": {
"type": "string"
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/**
* Streams the address of the current cell.
* @customfunction ADDRESSSTREAM
* @param {CustomFunctions.StreamingInvocation<string>} invocation stream invocation
* @streaming
* @requiresStreamAddress
* @requiresStreamParameterAddresses
*/
function addressStream(invocation) {
// Empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/**
* Streams the address of the current cell.
* @customfunction ADDRESSSTREAM
* @param invocation stream invocation
* @streaming
* @requiresStreamAddress
* @requiresStreamParameterAddresses
*/
function addressStream(invocation: CustomFunctions.StreamingInvocation<string>) {
// Empty
}
Loading