use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol in project ballerina by ballerina-lang.
the class SignatureHelpUtil method getSignatureInfoModel.
/**
* Get the required signature information filled model.
*
* @param bInvokableSymbol Invokable symbol
* @param signatureContext Signature operation context
* @return {@link SignatureInfoModel} SignatureInfoModel containing signature information
*/
private static SignatureInfoModel getSignatureInfoModel(BInvokableSymbol bInvokableSymbol, TextDocumentServiceContext signatureContext) {
Map<String, String> paramDescMap = new HashMap<>();
SignatureInfoModel signatureInfoModel = new SignatureInfoModel();
List<ParameterInfoModel> paramModels = new ArrayList<>();
String functionName = signatureContext.get(SignatureKeys.CALLABLE_ITEM_NAME);
CompilerContext compilerContext = signatureContext.get(DocumentServiceKeys.COMPILER_CONTEXT_KEY);
BLangPackage bLangPackage = signatureContext.get(DocumentServiceKeys.LS_PACKAGE_CACHE_KEY).findPackage(compilerContext, bInvokableSymbol.pkgID);
BLangFunction blangFunction = bLangPackage.getFunctions().stream().filter(bLangFunction -> bLangFunction.getName().getValue().equals(functionName)).findFirst().orElse(null);
if (!blangFunction.getDocumentationAttachments().isEmpty()) {
// Get the first documentation attachment
BLangDocumentation bLangDocumentation = blangFunction.getDocumentationAttachments().get(0);
signatureInfoModel.setSignatureDescription(bLangDocumentation.documentationText.trim());
bLangDocumentation.attributes.forEach(attribute -> {
if (attribute.docTag.equals(DocTag.PARAM)) {
paramDescMap.put(attribute.documentationField.getValue(), attribute.documentationText.trim());
}
});
} else {
// TODO: Should be deprecated in due course
// Iterate over the attachments list and extract the attachment Description Map
blangFunction.getAnnotationAttachments().forEach(annotationAttachment -> {
BLangExpression expr = annotationAttachment.expr;
if (expr instanceof BLangRecordLiteral) {
List<BLangRecordLiteral.BLangRecordKeyValue> recordKeyValues = ((BLangRecordLiteral) expr).keyValuePairs;
for (BLangRecordLiteral.BLangRecordKeyValue recordKeyValue : recordKeyValues) {
BLangExpression key = recordKeyValue.key.expr;
BLangExpression value = recordKeyValue.getValue();
if (key instanceof BLangSimpleVarRef && ((BLangSimpleVarRef) key).getVariableName().getValue().equals("value") && value instanceof BLangLiteral) {
String annotationValue = ((BLangLiteral) value).getValue().toString();
if (annotationAttachment.getAnnotationName().getValue().equals("Param")) {
String paramName = annotationValue.substring(0, annotationValue.indexOf(UtilSymbolKeys.PKG_DELIMITER_KEYWORD));
String annotationDesc = annotationValue.substring(annotationValue.indexOf(UtilSymbolKeys.PKG_DELIMITER_KEYWORD) + 1).trim();
paramDescMap.put(paramName, annotationDesc);
} else if (annotationAttachment.getAnnotationName().getValue().equals("Description")) {
signatureInfoModel.setSignatureDescription(annotationValue);
}
}
}
}
});
}
bInvokableSymbol.getParameters().forEach(bVarSymbol -> {
ParameterInfoModel parameterInfoModel = new ParameterInfoModel();
parameterInfoModel.setParamType(bVarSymbol.getType().toString());
parameterInfoModel.setParamValue(bVarSymbol.getName().getValue());
parameterInfoModel.setDescription(paramDescMap.get(bVarSymbol.getName().getValue()));
paramModels.add(parameterInfoModel);
});
signatureInfoModel.setParameterInfoModels(paramModels);
return signatureInfoModel;
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol in project ballerina by ballerina-lang.
the class SymbolEnter method defineInvokableSymbolParams.
private void defineInvokableSymbolParams(BLangInvokableNode invokableNode, BInvokableSymbol symbol, SymbolEnv invokableEnv) {
List<BVarSymbol> paramSymbols = invokableNode.requiredParams.stream().peek(varNode -> defineNode(varNode, invokableEnv)).map(varNode -> varNode.symbol).collect(Collectors.toList());
List<BVarSymbol> namedParamSymbols = invokableNode.defaultableParams.stream().peek(varDefNode -> defineNode(varDefNode.var, invokableEnv)).map(varDefNode -> varDefNode.var.symbol).collect(Collectors.toList());
List<BVarSymbol> retParamSymbols = invokableNode.retParams.stream().peek(varNode -> defineNode(varNode, invokableEnv)).filter(varNode -> varNode.symbol != null).map(varNode -> varNode.symbol).collect(Collectors.toList());
symbol.params = paramSymbols;
symbol.retParams = retParamSymbols;
symbol.defaultableParams = namedParamSymbols;
// Create function type
List<BType> paramTypes = paramSymbols.stream().map(paramSym -> paramSym.type).collect(Collectors.toList());
namedParamSymbols.forEach(paramSymbol -> paramTypes.add(paramSymbol.type));
if (invokableNode.restParam != null) {
defineNode(invokableNode.restParam, invokableEnv);
symbol.restParam = invokableNode.restParam.symbol;
paramTypes.add(symbol.restParam.type);
}
List<BType> retTypes = invokableNode.retParams.stream().map(varNode -> varNode.type != null ? varNode.type : varNode.typeNode.type).collect(Collectors.toList());
symbol.type = new BInvokableType(paramTypes, retTypes, null);
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol in project ballerina by ballerina-lang.
the class SymbolEnter method defineConnectorSymbolParams.
private void defineConnectorSymbolParams(BLangConnector connectorNode, BConnectorSymbol symbol, SymbolEnv connectorEnv) {
List<BVarSymbol> paramSymbols = connectorNode.params.stream().peek(varNode -> defineNode(varNode, connectorEnv)).map(varNode -> varNode.symbol).collect(Collectors.toList());
symbol.params = paramSymbols;
// Create connector type
List<BType> paramTypes = paramSymbols.stream().map(paramSym -> paramSym.type).collect(Collectors.toList());
symbol.type = new BConnectorType(paramTypes, symbol);
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol in project ballerina by ballerina-lang.
the class SymbolEnter method visit.
@Override
public void visit(BLangAction actionNode) {
BInvokableSymbol actionSymbol = Symbols.createActionSymbol(Flags.asMask(actionNode.flagSet), names.fromIdNode(actionNode.name), env.enclPkg.symbol.pkgID, null, env.scope.owner);
SymbolEnv invokableEnv = SymbolEnv.createResourceActionSymbolEnv(actionNode, actionSymbol.scope, env);
defineInvokableSymbol(actionNode, actionSymbol, invokableEnv);
actionNode.endpoints.forEach(ep -> defineNode(ep, invokableEnv));
// TODO check below as it create a new symbol for the connector
BVarSymbol varSymbol = new BVarSymbol(Flags.asMask(EnumSet.noneOf(Flag.class)), names.fromIdNode((BLangIdentifier) createIdentifier(Names.CONNECTOR.getValue())), env.enclPkg.symbol.pkgID, actionSymbol.owner.type, invokableEnv.scope.owner);
actionSymbol.receiverSymbol = varSymbol;
((BInvokableType) actionSymbol.type).setReceiverType(varSymbol.type);
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol in project ballerina by ballerina-lang.
the class TaintAnalyzer method analyzeInvocation.
// Private methods relevant to invocation analysis.
private void analyzeInvocation(BLangInvocation invocationExpr) {
BInvokableSymbol invokableSymbol = (BInvokableSymbol) invocationExpr.symbol;
Map<Integer, TaintRecord> taintTable = invokableSymbol.taintTable;
List<Boolean> returnTaintedStatus = new ArrayList<>();
TaintRecord allParamsUntaintedRecord = taintTable.get(ALL_UNTAINTED_TABLE_ENTRY_INDEX);
if (allParamsUntaintedRecord.taintError != null && allParamsUntaintedRecord.taintError.size() > 0) {
// This can occur when there is a error regardless of tainted status of parameters.
// Example: Tainted value returned by function is passed to another functions's sensitive parameter.
addTaintError(allParamsUntaintedRecord.taintError);
} else {
returnTaintedStatus = new ArrayList<>(taintTable.get(ALL_UNTAINTED_TABLE_ENTRY_INDEX).retParamTaintedStatus);
}
if (invocationExpr.argExprs != null) {
for (int argIndex = 0; argIndex < invocationExpr.argExprs.size(); argIndex++) {
BLangExpression argExpr = invocationExpr.argExprs.get(argIndex);
argExpr.accept(this);
// return-tainted-status when the given argument is in tainted state.
if (getObservedTaintedStatus()) {
TaintRecord taintRecord = taintTable.get(argIndex);
if (taintRecord == null) {
// This is when current parameter is "sensitive". Therefore, providing a tainted
// value to a sensitive parameter is invalid and should return a compiler error.
int requiredParamCount = invokableSymbol.params.size();
int defaultableParamCount = invokableSymbol.defaultableParams.size();
int totalParamCount = requiredParamCount + defaultableParamCount + (invokableSymbol.restParam == null ? 0 : 1);
BVarSymbol paramSymbol = getParamSymbol(invokableSymbol, argIndex, requiredParamCount, defaultableParamCount);
addTaintError(argExpr.pos, paramSymbol.name.value, DiagnosticCode.TAINTED_VALUE_PASSED_TO_SENSITIVE_PARAMETER);
} else if (taintRecord.taintError != null && taintRecord.taintError.size() > 0) {
// This is when current parameter is derived to be sensitive. The error already generated
// during taint-table generation will be used.
addTaintError(taintRecord.taintError);
} else {
// status of all returns to get accumulated tainted status of all returns for the invocation.
for (int returnIndex = 0; returnIndex < returnTaintedStatus.size(); returnIndex++) {
if (taintRecord.retParamTaintedStatus.get(returnIndex)) {
returnTaintedStatus.set(returnIndex, true);
}
}
}
if (stopAnalysis) {
break;
}
}
}
}
if (invocationExpr.expr != null) {
// When an invocation like stringValue.trim() happens, if stringValue is tainted, the result will
// also be tainted.
// TODO: TaintedIf annotation, so that it's possible to define what can taint or untaint the return.
invocationExpr.expr.accept(this);
for (int i = 0; i < returnTaintedStatus.size(); i++) {
if (getObservedTaintedStatus()) {
returnTaintedStatus.set(i, getObservedTaintedStatus());
}
}
}
taintedStatusList = returnTaintedStatus;
}
Aggregations