diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index 910a9d394177..210a91289baa 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -1542,6 +1542,7 @@ public void visit(BLangLiteral astLiteralExpr) { @Override public void visit(BLangMapLiteral astMapLiteralExpr) { + this.env.isInArrayOrStructure++; visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList()); BIRVariableDcl tempVarDcl = new BIRVariableDcl(astMapLiteralExpr.getBType(), this.env.nextLocalVarId(names), @@ -1552,6 +1553,7 @@ public void visit(BLangMapLiteral astMapLiteralExpr) { setScopeAndEmit(new BIRNonTerminator.NewStructure(astMapLiteralExpr.pos, toVarRef, this.env.targetOperand, generateMappingConstructorEntries(astMapLiteralExpr.fields))); this.env.targetOperand = toVarRef; + this.env.isInArrayOrStructure--; } @Override @@ -1572,6 +1574,7 @@ public void visit(BLangTypeConversionExpr astTypeConversionExpr) { @Override public void visit(BLangStructLiteral astStructLiteralExpr) { + this.env.isInArrayOrStructure++; List varDcls = mapToVarDcls(astStructLiteralExpr.enclMapSymbols); BType type = astStructLiteralExpr.getBType(); visitTypedesc(astStructLiteralExpr.pos, type, varDcls); @@ -1588,6 +1591,7 @@ public void visit(BLangStructLiteral astStructLiteralExpr) { setScopeAndEmit(instruction); this.env.targetOperand = toVarRef; + this.env.isInArrayOrStructure--; } private List mapToVarDcls(TreeMap enclMapSymbols) { @@ -1838,14 +1842,17 @@ public void visit(BLangPackageVarRef astPackageVarRefExpr) { setScopeAndEmit(new Move(astPackageVarRefExpr.pos, this.env.targetOperand, varRef)); } } else { - BIRVariableDcl tempVarDcl = new BIRVariableDcl(astPackageVarRefExpr.getBType(), - this.env.nextLocalVarId(names), VarScope.FUNCTION, - VarKind.TEMP); - this.env.enclFunc.localVars.add(tempVarDcl); - BIROperand tempVarRef = new BIROperand(tempVarDcl); - BIROperand fromVarRef = new BIROperand(getVarRef(astPackageVarRefExpr)); - setScopeAndEmit(new Move(astPackageVarRefExpr.pos, fromVarRef, tempVarRef)); - this.env.targetOperand = tempVarRef; + if (this.env.isInArrayOrStructure > 0) { + BIRVariableDcl tempVarDcl = new BIRVariableDcl(astPackageVarRefExpr.getBType(), + this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); + this.env.enclFunc.localVars.add(tempVarDcl); + BIROperand tempVarRef = new BIROperand(tempVarDcl); + BIROperand fromVarRef = new BIROperand(getVarRef(astPackageVarRefExpr)); + setScopeAndEmit(new Move(astPackageVarRefExpr.pos, fromVarRef, tempVarRef)); + this.env.targetOperand = tempVarRef; + } else { + this.env.targetOperand = new BIROperand(getVarRef(astPackageVarRefExpr)); + } } this.varAssignment = variableStore; } @@ -1942,6 +1949,7 @@ public void visit(BLangWaitExpr waitExpr) { @Override public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { + this.env.isInArrayOrStructure++; visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList()); BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId()); addToTrapStack(thenBB); @@ -1966,6 +1974,7 @@ public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { this.env.targetOperand = toVarRef; this.env.enclFunc.basicBlocks.add(thenBB); this.env.enclBB = thenBB; + this.env.isInArrayOrStructure--; } @Override @@ -2646,6 +2655,7 @@ private InstructionKind getUnaryInstructionKind(OperatorKind opKind) { } private void generateListConstructorExpr(BLangListConstructorExpr listConstructorExpr) { + this.env.isInArrayOrStructure++; // Emit create array instruction BIRVariableDcl tempVarDcl = new BIRVariableDcl(listConstructorExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -2695,6 +2705,7 @@ private void generateListConstructorExpr(BLangListConstructorExpr listConstructo initialValues)); } this.env.targetOperand = toVarRef; + this.env.isInArrayOrStructure--; } private void generateArrayAccess(BLangIndexBasedAccess astArrayAccessExpr) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java index 03beb1cb2415..2ddf4a1b69c5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGenEnv.java @@ -73,6 +73,9 @@ class BIRGenEnv { // A function can have only one basic block that has a return instruction. BIRBasicBlock returnBB; + // This is to hold whether a NewArray or NewStructure instruction is being constructed + int isInArrayOrStructure = 0; + BIRGenEnv(BIRPackage birPkg) { this.enclPkg = birPkg; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java index edc137bd9bc8..d06c0300edf1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java @@ -34,6 +34,7 @@ import org.wso2.ballerinalang.compiler.bir.model.VarKind; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.util.CompilerContext; +import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.util.Lists; import java.util.ArrayList; @@ -475,11 +476,31 @@ public void visit(BIRNonTerminator.Move birMove) { this.env.newInstructions.add(birMove); return; } + if (isIrreplaceableVar(birMove.rhsOp.variableDcl)) { + this.env.newInstructions.add(birMove); + this.env.irreplaceableTempVars.add(birMove.lhsOp.variableDcl); + return; + } if (birMove.rhsOp.variableDcl.kind != VarKind.TEMP) { this.env.tempVars.put(birMove.lhsOp.variableDcl, birMove.rhsOp.variableDcl); } } + private boolean isIrreplaceableVar(BIRVariableDcl variableDcl) { + if (variableDcl.kind != VarKind.GLOBAL) { + return false; + } + int typeTag = variableDcl.type.tag; + switch (typeTag) { + case TypeTags.BYTE: + case TypeTags.BOOLEAN: + case TypeTags.FLOAT: + return true; + default: + return TypeTags.isIntegerTypeTag(typeTag); + } + } + @Override public void visit(BIRNonTerminator.BinaryOp birBinaryOp) { this.optimizeNode(birBinaryOp.lhsOp, this.env); @@ -741,6 +762,8 @@ public static class OptimizerEnv { // key - temp var, value - real var private final Map tempVars = new HashMap<>(); + private final Set irreplaceableTempVars = new HashSet<>(); + private List newInstructions; private final List tempVarsList = new ArrayList<>(); @@ -757,7 +780,7 @@ public static class OptimizerEnv { public void addTempBirOperand(BIROperand birOperand) { BIRVariableDcl variableDcl = birOperand.variableDcl; - if (variableDcl.kind != VarKind.TEMP) { + if (variableDcl.kind != VarKind.TEMP || irreplaceableTempVars.contains(variableDcl)) { return; } tempVarsList.add(birOperand); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/ControlFlowGraph.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/ControlFlowGraph.java deleted file mode 100644 index 2abe6b1dd805..000000000000 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/ControlFlowGraph.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you 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 org.wso2.ballerinalang.compiler.bir.optimizer; - -import org.wso2.ballerinalang.compiler.bir.model.BIRAbstractInstruction; -import org.wso2.ballerinalang.compiler.bir.model.BIRNode; -import org.wso2.ballerinalang.compiler.bir.model.BIRTerminator; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * The control flow graph that gets created from the bir. In this implementation each instruction is reflected as a node - * in the Graph including the terminator instruction. - */ -public class ControlFlowGraph { - private final BIRNode.BIRFunction function; - private final Map funcBasicBlockFirstNodeMap; - private final Map funcBasicBlockLastNodeMap; - private final List nodes; - - public ControlFlowGraph(BIRNode.BIRFunction function) { - this.function = function; - funcBasicBlockFirstNodeMap = new HashMap<>(); - funcBasicBlockLastNodeMap = new HashMap<>(); - nodes = new ArrayList<>(); - generate(); - } - - /** - * Traverses the BIR and generates a graph. Each instruction is represented as a Node and linked with an edge to the - * next instruction within the same basic block. The nodes across the basic blocks are linked based on the basic - * blocks' terminator nodes. - */ - public void generate() { - for (BIRNode.BIRBasicBlock basicBlock : function.basicBlocks) { - Node prev = null; - for (int i = 0; i < basicBlock.instructions.size(); i++) { - Node node = new Node(basicBlock.instructions.get(i)); - nodes.add(node); - if (i == 0) { - funcBasicBlockFirstNodeMap.put(basicBlock, node); - } - if (prev != null) { - addEdge(prev, node); - } - prev = node; - } - Node terminatorNode = new Node(basicBlock.terminator); - nodes.add(terminatorNode); - if (prev != null) { - addEdge(prev, terminatorNode); - } else { - funcBasicBlockFirstNodeMap.put(basicBlock, terminatorNode); - } - funcBasicBlockLastNodeMap.put(basicBlock, terminatorNode); - } - - connectNodesAcrossBasicBlocks(); - } - - private void connectNodesAcrossBasicBlocks() { - funcBasicBlockLastNodeMap.forEach((birBasicBlock, node) -> { - BIRTerminator terminator = birBasicBlock.terminator; - for (BIRNode.BIRBasicBlock basicBlock : terminator.getNextBasicBlocks()) { - Node target = funcBasicBlockFirstNodeMap.get(basicBlock); - if (target != null) { - addEdge(node, target); - } - } - }); - } - - private void addEdge(Node first, Node second) { - first.successors.add(second); - second.predecessors.add(first); - } - - public List getNodes() { - return nodes; - } - - static class Node { - List successors; - List predecessors; - BIRAbstractInstruction instruction; - - public Node(BIRAbstractInstruction instruction) { - this.instruction = instruction; - predecessors = new ArrayList<>(); - successors = new ArrayList<>(); - } - } -} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/LivenessAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/LivenessAnalyzer.java deleted file mode 100644 index 4acb74c9a10f..000000000000 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/LivenessAnalyzer.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you 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 org.wso2.ballerinalang.compiler.bir.optimizer; - -import org.wso2.ballerinalang.compiler.bir.model.BIRAbstractInstruction; -import org.wso2.ballerinalang.compiler.bir.model.BIRNode; -import org.wso2.ballerinalang.compiler.bir.model.BIROperand; -import org.wso2.ballerinalang.compiler.bir.model.VarKind; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Do liveness analysis on the control flow graph to obtain the liveOut value of each function. - *

- * Reference: Andrew W. Appel - Modern Compiler Implementation in Java, 2Ed (2002), Chapter 10 - */ -public class LivenessAnalyzer { - private final Map> liveIns; - private final Map> liveOuts; - private final List nodes; - - public LivenessAnalyzer(List nodes) { - this.liveIns = new HashMap<>(); - this.liveOuts = new HashMap<>(); - this.nodes = nodes; - init(); - } - - private void init() { - nodes.forEach(node -> { - liveIns.put(node, new HashSet<>()); - liveOuts.put(node, new HashSet<>()); - }); - analyze(); - } - - /** - * Analyzes the CFG based on the following equation till there's no change in the liveIns and liveOuts. - * - *

- * in[n] ← use[n] ∪ (out[n] − def [n]) - *

- * out[n] ← ∪(s∈succ[n]) (in[s]) - *

- * where ∪ indicates union of, in is liveIns, out is liveOuts, def is lhsOp and use is rhs operands. - */ - private void analyze() { - if (nodes.isEmpty()) { - return; - } - boolean changed = true; - while (changed) { - changed = false; - for (int i = nodes.size() - 1; i >= 0; i--) { - ControlFlowGraph.Node node = nodes.get(i); - changed |= updateLiveIns(node); - changed |= updateLiveOuts(node); - } - } - } - - /** - * If an operand is used at the current node or is liveOut at the current node, it is liveIn at the current node. - * This is except for the operand defined at the current node. - * - * @param node the current node - * @return whether the set changed - */ - private boolean updateLiveIns(ControlFlowGraph.Node node) { - boolean changed = false; - Set in = liveIns.get(node); - Set out = liveOuts.get(node); - for (BIROperand use : node.instruction.getRhsOperands()) { - changed |= in.add(use.variableDcl); - } - BIRNode.BIRVariableDcl def = getDef(node); - boolean removed = out.remove(def); - changed |= in.addAll(out); - if (removed) { - out.add(def); - } - return changed; - } - - private BIRNode.BIRVariableDcl getDef(ControlFlowGraph.Node node) { - BIRNode.BIRVariableDcl def = null; - if (node.instruction.lhsOp != null) { - BIRNode.BIRVariableDcl variableDcl = node.instruction.lhsOp.variableDcl; - if (variableDcl.kind != VarKind.GLOBAL) { - def = variableDcl; - } - } - return def; - } - - /** - * If an operand is liveIn at any of the successors it is liveOut at current node. - * - * @param node the current node - * @return whether the set changed - */ - private boolean updateLiveOuts(ControlFlowGraph.Node node) { - boolean changed = false; - for (ControlFlowGraph.Node successor : node.successors) { - changed |= liveOuts.get(node).addAll(liveIns.get(successor)); - } - return changed; - } - - /** - * Get the set of variables that are live after the execution of an instruction. - * - * @return map of BIRAbstractInstruction and the set of variables that are live after the execution of the - * instruction. - */ - public Map> getInstructionLiveOuts() { - Map> map = new HashMap<>(); - liveOuts.forEach((node, var) -> map.put(node.instruction, var)); - return map; - } -} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java index 4a85ea735e30..e02b7df1b9e7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java @@ -781,8 +781,9 @@ public void visit(BLangPackage pkgNode) { annotationDesugar.initializeAnnotationMap(pkgNode); pkgNode.constants.stream() - .filter(constant -> constant.expr.getKind() == NodeKind.LITERAL || + .filter(constant -> (constant.expr.getKind() == NodeKind.LITERAL || constant.expr.getKind() == NodeKind.NUMERIC_LITERAL) + && constant.expr.getBType().tag != TypeTags.TUPLE) .forEach(constant -> pkgNode.typeDefinitions.add(constant.associatedTypeDefinition)); BLangBlockStmt serviceAttachments = serviceDesugar.rewriteServiceVariables(pkgNode.services, env); @@ -5794,7 +5795,8 @@ public void visit(BLangForkJoin forkJoin) { @Override public void visit(BLangLiteral literalExpr) { - if (Types.getReferredType(literalExpr.getBType()).tag == TypeTags.ARRAY) { + int tag = Types.getReferredType(literalExpr.getBType()).tag; + if (tag == TypeTags.ARRAY || tag == TypeTags.TUPLE) { // this is blob literal as byte array result = rewriteBlobLiteral(literalExpr); return; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index 0bb02cf85954..274c4f9f0c83 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -944,8 +944,8 @@ public BLangNode transform(ConstantDeclarationNode constantDeclarationNode) { // Check whether the value is a literal or a unary expression and if it is not any one of the before mentioned // kinds it is an invalid case, so we don't need to consider it. - if (nodeKind == NodeKind.LITERAL || nodeKind == NodeKind.NUMERIC_LITERAL || - nodeKind == NodeKind.UNARY_EXPR) { + if ((nodeKind == NodeKind.LITERAL || nodeKind == NodeKind.NUMERIC_LITERAL || nodeKind == NodeKind.UNARY_EXPR) + && (constantNode.typeNode == null || constantNode.typeNode.getKind() != NodeKind.ARRAY_TYPE)) { // Note - If the RHS is a literal, we need to create an anonymous type definition which can later be used // in type definitions.h createAnonymousTypeDefForConstantDeclaration(constantNode, pos, identifierPos); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 45f0b0734db4..b1a1d5c0c3fc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1775,7 +1775,7 @@ private boolean isValidContextForInferredArray(BLangNode node) { private boolean isValidVariableForInferredArray(BLangNode node) { switch (node.getKind()) { case LITERAL: - if (node.getBType().tag == TypeTags.ARRAY) { + if (node.getBType().tag == TypeTags.ARRAY || node.getBType().tag == TypeTags.TUPLE) { return true; } break; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java index 20801e1c33bb..036825884ae9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/ConstantTypeChecker.java @@ -256,6 +256,10 @@ public void visit(BLangLiteral literalExpr, AnalyzerData data) { return; } + if (literalType.tag == TypeTags.BYTE_ARRAY) { + literalType = rewriteByteArrayLiteral(literalExpr, data); + } + if (literalExpr.isFiniteContext) { return; } @@ -269,6 +273,24 @@ public void visit(BLangLiteral literalExpr, AnalyzerData data) { data.resultType = finiteType; } + private BType rewriteByteArrayLiteral(BLangLiteral literalExpr, AnalyzerData data) { + byte[] values = types.convertToByteArray((String) literalExpr.value); + + List memberTypes = new ArrayList<>(); + for (byte b : values) { + memberTypes.add(getFiniteType(Byte.toUnsignedLong(b), data.constantSymbol, literalExpr.pos, + symTable.intType)); + } + + BType expType = Types.getReferredType(data.expType); + if (expType.tag == TypeTags.ARRAY && ((BArrayType) expType).state == BArrayState.INFERRED) { + ((BArrayType) expType).size = memberTypes.size(); + ((BArrayType) expType).state = BArrayState.CLOSED; + } + + return createNewTupleType(literalExpr.pos, memberTypes, data); + } + @Override public void visit(BLangSimpleVarRef varRefExpr, AnalyzerData data) { // Set error type as the actual type. @@ -1092,6 +1114,7 @@ private BType checkListConstructorCompatibility(BType expType, BLangListConstruc switch (possibleType.tag) { case TypeTags.ARRAY: + case TypeTags.BYTE_ARRAY: return checkArrayType((BArrayType) possibleType, listConstructor, data); case TypeTags.TUPLE: return checkTupleType((BTupleType) possibleType, listConstructor, data); @@ -1364,6 +1387,7 @@ private BType checkExprIncompatible(BType eType, BLangExpression expr, AnalyzerD private BType getListConstructorCompatibleNonUnionType(BType type, AnalyzerData data) { switch (type.tag) { case TypeTags.ARRAY: + case TypeTags.BYTE_ARRAY: case TypeTags.TUPLE: case TypeTags.READONLY: case TypeTags.TYPEDESC: @@ -1717,12 +1741,6 @@ private BType setLiteralValueAndGetType(BLangLiteral literalExpr, BType expType, } } - // Byte arrays are not yet supported in constants. - if (literalExpr.getBType().tag == TypeTags.BYTE_ARRAY) { - dlog.error(literalExpr.pos, DiagnosticErrorCode.EXPRESSION_IS_NOT_A_CONSTANT_EXPRESSION); - return symTable.semanticError; - } - return literalType; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java index b50335700f31..54f2a6d778b9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java @@ -1018,8 +1018,9 @@ private boolean isAssignable(BType source, BType target, Set unresolve return isFunctionTypeAssignable((BInvokableType) source, (BInvokableType) target, new HashSet<>()); } - return sourceTag == TypeTags.ARRAY && targetTag == TypeTags.ARRAY && - isArrayTypesAssignable((BArrayType) source, target, unresolvedTypes); + return (sourceTag == TypeTags.ARRAY || sourceTag == TypeTags.BYTE_ARRAY) + && targetTag == TypeTags.ARRAY + && isArrayTypesAssignable((BArrayType) source, target, unresolvedTypes); } private boolean isMutable(BType type) { @@ -1542,6 +1543,7 @@ private boolean isSelectivelyImmutableType(BType input, boolean disallowReadOnly case TypeTags.XML_COMMENT: case TypeTags.XML_ELEMENT: case TypeTags.XML_PI: + case TypeTags.BYTE_ARRAY: return true; case TypeTags.ARRAY: BArrayType arrayType = (BArrayType) type; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java index 932a6acd8d86..e39f78e4aa3a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java @@ -129,6 +129,7 @@ public class SymbolTable { public final BFutureType futureType = new BFutureType(TypeTags.FUTURE, nilType, null); public final BArrayType arrayType = new BArrayType(anyType); + public final BArrayType byteArrayType = new BArrayType(byteType); public final BArrayType arrayStringType = new BArrayType(stringType); BVarSymbol varSymbol = new BVarSymbol(0, null, null, noType, null, null, SymbolOrigin.VIRTUAL); @@ -385,6 +386,8 @@ public BType getTypeFromTag(int tag) { return charStringType; case TypeTags.REGEXP: return regExpType; + case TypeTags.BYTE_ARRAY: + return byteArrayType; default: return semanticError; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java index 2d7e41661876..efd3034ca4eb 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/util/ImmutableTypeCloner.java @@ -232,6 +232,7 @@ private static BIntersectionType setImmutableType(Location pos, Types types, return defineImmutableXMLType(pos, types, env, pkgId, owner, symTable, anonymousModelHelper, names, unresolvedTypes, (BXMLType) type); case TypeTags.ARRAY: + case TypeTags.BYTE_ARRAY: return defineImmutableArrayType(pos, types, env, pkgId, owner, symTable, anonymousModelHelper, names, unresolvedTypes, (BArrayType) type); case TypeTags.TUPLE: diff --git a/gradle.properties b/gradle.properties index 7c8b55eb71cc..6bcb24537c34 100644 --- a/gradle.properties +++ b/gradle.properties @@ -135,7 +135,7 @@ snakeyamlVersion=2.0 sonarqubeGradlePluginVersion=4.0.0.2929 sonarcloudVersion=3.4.0.2513 spullaraMustacheCompilerVersion=0.8.9 -squareupOkioVersion=2.2.2 +squareupOkioVersion=3.4.0 swaggerModelsVersion=2.1.13 swaggerParserVersion=2.0.30 swaggerParserV2Version=2.0.30 diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/CentralPackageDescriptorLoader.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/CentralPackageDescriptorLoader.java index 39235c10973b..baeec04df86b 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/CentralPackageDescriptorLoader.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/CentralPackageDescriptorLoader.java @@ -70,7 +70,7 @@ public void loadBallerinaxPackagesFromCentral(LanguageServerContext lsContext) { languageClient.createProgress(workDoneProgressCreateParams); WorkDoneProgressBegin beginNotification = new WorkDoneProgressBegin(); - beginNotification.setTitle("Loading Ballerina Central Packages"); + beginNotification.setTitle("Ballerina Central Packages"); beginNotification.setCancellable(false); beginNotification.setMessage("Loading..."); languageClient.notifyProgress(new ProgressParams(Either.forLeft(taskId), diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/command/visitors/FunctionCallExpressionTypeFinder.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/command/visitors/FunctionCallExpressionTypeFinder.java index 3009015a1de6..a46e39049002 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/command/visitors/FunctionCallExpressionTypeFinder.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/command/visitors/FunctionCallExpressionTypeFinder.java @@ -20,6 +20,7 @@ import io.ballerina.compiler.api.SemanticModel; import io.ballerina.compiler.api.TypeBuilder; import io.ballerina.compiler.api.Types; +import io.ballerina.compiler.api.symbols.ArrayTypeSymbol; import io.ballerina.compiler.api.symbols.ClassSymbol; import io.ballerina.compiler.api.symbols.ErrorTypeSymbol; import io.ballerina.compiler.api.symbols.FunctionTypeSymbol; @@ -28,6 +29,7 @@ import io.ballerina.compiler.api.symbols.ParameterSymbol; import io.ballerina.compiler.api.symbols.RecordFieldSymbol; import io.ballerina.compiler.api.symbols.RecordTypeSymbol; +import io.ballerina.compiler.api.symbols.StreamTypeSymbol; import io.ballerina.compiler.api.symbols.Symbol; import io.ballerina.compiler.api.symbols.SymbolKind; import io.ballerina.compiler.api.symbols.TypeDescKind; @@ -63,11 +65,13 @@ import io.ballerina.compiler.syntax.tree.RecordFieldWithDefaultValueNode; import io.ballerina.compiler.syntax.tree.RemoteMethodCallActionNode; import io.ballerina.compiler.syntax.tree.ReturnStatementNode; +import io.ballerina.compiler.syntax.tree.SelectClauseNode; import io.ballerina.compiler.syntax.tree.SeparatedNodeList; import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; import io.ballerina.compiler.syntax.tree.SpecificFieldNode; import io.ballerina.compiler.syntax.tree.StartActionNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; +import io.ballerina.compiler.syntax.tree.TypedBindingPatternNode; import io.ballerina.compiler.syntax.tree.UnaryExpressionNode; import io.ballerina.compiler.syntax.tree.VariableDeclarationNode; import io.ballerina.compiler.syntax.tree.WhileStatementNode; @@ -114,9 +118,7 @@ public void visit(RecordFieldWithDefaultValueNode recordFieldWithDefaultValueNod @Override public void visit(ModuleVariableDeclarationNode moduleVariableDeclarationNode) { - Symbol symbol = semanticModel.symbol(moduleVariableDeclarationNode).orElse(null); - TypeSymbol typeDescriptor = SymbolUtil.getTypeDescriptor(symbol).orElse(null); - checkAndSetTypeResult(typeDescriptor); + visitVariableDeclaration(moduleVariableDeclarationNode, moduleVariableDeclarationNode.typedBindingPattern()); } @Override @@ -134,9 +136,7 @@ public void visit(AssignmentStatementNode assignmentStatementNode) { @Override public void visit(VariableDeclarationNode variableDeclarationNode) { - Symbol symbol = semanticModel.symbol(variableDeclarationNode).orElse(null); - TypeSymbol typeDescriptor = SymbolUtil.getTypeDescriptor(symbol).orElse(null); - checkAndSetTypeResult(typeDescriptor); + visitVariableDeclaration(variableDeclarationNode, variableDeclarationNode.typedBindingPattern()); } @Override @@ -486,6 +486,19 @@ public void visit(GroupingKeyVarDeclarationNode groupingKeyVarDeclarationNode) { TypeSymbol typeDescriptor = SymbolUtil.getTypeDescriptor(symbol).orElse(null); checkAndSetTypeResult(typeDescriptor); } + + @Override + public void visit(SelectClauseNode selectClauseNode) { + selectClauseNode.parent().parent().accept(this); + if (resultFound) { + TypeDescKind kind = this.returnTypeSymbol.typeKind(); + if (kind == TypeDescKind.ARRAY) { + checkAndSetTypeResult(((ArrayTypeSymbol) returnTypeSymbol).memberTypeDescriptor()); + } else if (kind == TypeDescKind.STREAM) { + checkAndSetTypeResult(((StreamTypeSymbol) returnTypeSymbol).typeParameter()); + } + } + } @Override public void visit(PanicStatementNode panicStatementNode) { @@ -522,4 +535,19 @@ private void resetResult() { public Optional getReturnTypeSymbol() { return Optional.ofNullable(returnTypeSymbol); } + + private void visitVariableDeclaration(Node variableDeclarationNode, TypedBindingPatternNode typedBindingNode) { + Symbol symbol = semanticModel.symbol(variableDeclarationNode).orElse(null); + Optional typeDescriptor = SymbolUtil.getTypeDescriptor(symbol); + TypeSymbol ts = null; + if (typeDescriptor.isPresent()) { + ts = typeDescriptor.get(); + if (ts.typeKind() == TypeDescKind.COMPILATION_ERROR && + typedBindingNode.typeDescriptor().kind() == SyntaxKind.VAR_TYPE_DESC) { + Types types = semanticModel.types(); + ts = types.builder().UNION_TYPE.withMemberTypes(types.ANY, types.ERROR).build(); + } + } + checkAndSetTypeResult(ts); + } } diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/SymbolUtil.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/SymbolUtil.java index f8722526dded..991a4258ee3f 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/SymbolUtil.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/SymbolUtil.java @@ -462,7 +462,7 @@ public static List filterSymbolsByPrefix(List symbolList, CompletionSearchProvider completionSearchProvider = CompletionSearchProvider .getInstance(context.languageServercontext()); if (!completionSearchProvider.checkModuleIndexed(moduleId)) { - completionSearchProvider.indexModule(moduleId, symbolList.stream() + completionSearchProvider.indexModuleAndModuleSymbolNames(moduleId, symbolList.stream() .map(symbol -> symbol.getName().get()) .collect(Collectors.toList()), new ArrayList<>(symbolMapWithPrefix.keySet())); } diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/CompletionSearchProvider.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/CompletionSearchProvider.java index 50396cc6b9e7..662c50d8ecd4 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/CompletionSearchProvider.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/CompletionSearchProvider.java @@ -70,10 +70,11 @@ public List getSuggestions(String prefix) { * @param moduleName module name. * @param stringList list of words. */ - public void indexModule(ModuleID moduleName, List stringList, List namesWithModulePrefix) { + public void indexModuleAndModuleSymbolNames(ModuleID moduleName, List stringList, + List namesWithModulePrefix) { indexedModules.add(moduleName); - stringList.forEach(s -> trie.root.insert(s.toLowerCase(Locale.ENGLISH))); - namesWithModulePrefix.forEach((s -> trie.root.insert(s.toLowerCase(Locale.ENGLISH)))); + indexNames(stringList); + indexNames(namesWithModulePrefix); } /** @@ -85,4 +86,13 @@ public void indexModule(ModuleID moduleName, List stringList, List names) { + names.forEach(s -> trie.root.insert(s.toLowerCase(Locale.ENGLISH))); + } } diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/providers/context/ImportDeclarationNodeContext.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/providers/context/ImportDeclarationNodeContext.java index b111ccc32eb3..4c9895d52108 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/providers/context/ImportDeclarationNodeContext.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/completions/providers/context/ImportDeclarationNodeContext.java @@ -36,6 +36,7 @@ import org.ballerinalang.langserver.commons.BallerinaCompletionContext; import org.ballerinalang.langserver.commons.LanguageServerContext; import org.ballerinalang.langserver.commons.completion.LSCompletionItem; +import org.ballerinalang.langserver.completions.CompletionSearchProvider; import org.ballerinalang.langserver.completions.SnippetCompletionItem; import org.ballerinalang.langserver.completions.providers.AbstractCompletionProvider; import org.ballerinalang.langserver.completions.util.Snippet; @@ -318,8 +319,25 @@ private ArrayList moduleNameContextCompletions(BallerinaComple ArrayList completionItems = new ArrayList<>(); List addedPkgNames = new ArrayList<>(); LanguageServerContext serverContext = context.languageServercontext(); - List moduleList = - LSPackageLoader.getInstance(serverContext).getAllVisiblePackages(context); + List moduleList; + + if (orgName.equals("ballerinax")) { + List packageList = new ArrayList<>(); + String prefix = node.moduleName().stream().filter(identifierToken -> !identifierToken.isMissing()) + .map(IdentifierToken::text) + .collect(Collectors.joining(".")); + + moduleList = LSPackageLoader.getInstance(serverContext).getCentralPackages(serverContext); + moduleList.forEach(ballerinaPackage -> packageList.add(ballerinaPackage.packageName().value())); + List filteredPackageNames = getFilteredPackages(packageList, prefix, context); + for (String filteredPackage : filteredPackageNames) { + LSCompletionItem completionItem = getImportCompletion(context, filteredPackage, filteredPackage); + completionItem.getCompletionItem().setAdditionalTextEdits(additionalEdits); + completionItems.add(completionItem); + } + return completionItems; + } + moduleList = LSPackageLoader.getInstance(serverContext).getAllVisiblePackages(context); moduleList.forEach(ballerinaPackage -> { String packageName = ballerinaPackage.packageName().value(); String insertText; @@ -332,7 +350,7 @@ private ArrayList moduleNameContextCompletions(BallerinaComple insertText = packageName; } addedPkgNames.add(packageName); - // Do not add the semi colon at the end of the insert text since the user might type the as keyword + // Do not add the semicolon at the end of the insert text since the user might type the as keyword LSCompletionItem completionItem = getImportCompletion(context, packageName, insertText); completionItem.getCompletionItem().setAdditionalTextEdits(additionalEdits); completionItems.add(completionItem); @@ -342,6 +360,15 @@ private ArrayList moduleNameContextCompletions(BallerinaComple return completionItems; } + + private static List getFilteredPackages(List packageList, String prefix, + BallerinaCompletionContext context) { + CompletionSearchProvider completionSearchProvider = CompletionSearchProvider + .getInstance(context.languageServercontext()); + completionSearchProvider.indexNames(packageList); + return completionSearchProvider.getSuggestions(prefix); + } + private boolean onSuggestAsKeyword(BallerinaCompletionContext context, ImportDeclarationNode node) { SeparatedNodeList moduleName = node.moduleName(); diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateFunctionTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateFunctionTest.java index 97032e3eca41..642cf73c205b 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateFunctionTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateFunctionTest.java @@ -175,6 +175,14 @@ public Object[][] dataProvider() { {"create_function_in_local_var1.json"}, {"create_function_in_local_var2.json"}, {"create_function_in_start_action1.json"}, + + {"undefinedFunctionCodeAction25.json"}, + {"undefinedFunctionCodeAction26.json"}, + {"undefinedFunctionCodeAction27.json"}, + {"undefinedFunctionCodeAction28.json"}, + {"undefinedFunctionCodeAction29.json"}, + {"undefinedFunctionCodeAction30.json"}, + {"undefinedFunctionCodeAction31.json"}, }; } diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction25.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction25.json new file mode 100644 index 000000000000..b8cb0fef87b2 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction25.json @@ -0,0 +1,57 @@ +{ + "position": { + "line": 1, + "character": 52 + }, + "source": "createUndefinedFunction14.bal", + "expected": [ + { + "title": "Create function 'toUpperCase(...)'", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 1 + } + }, + "newText": "\n\nfunction toUpperCase(string letter) returns any|error {\n return ;\n}" + } + ], + "resolvable": true, + "data": { + "extName": "org.ballerinalang.langserver.codeaction.BallerinaCodeActionExtension", + "codeActionName": "Create Function", + "fileUri": "createUndefinedFunction14.bal", + "range": { + "start": { + "line": 1, + "character": 46 + }, + "end": { + "line": 1, + "character": 65 + } + }, + "actionData": { + "key": "node.range", + "value": { + "start": { + "line": 1.0, + "character": 46.0 + }, + "end": { + "line": 1.0, + "character": 65.0 + } + } + } + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction26.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction26.json new file mode 100644 index 000000000000..65e8f55b6101 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction26.json @@ -0,0 +1,57 @@ +{ + "position": { + "line": 1, + "character": 54 + }, + "source": "createUndefinedFunction15.bal", + "expected": [ + { + "title": "Create function 'toUpperCase(...)'", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 1 + } + }, + "newText": "\n\nfunction toUpperCase(string letter) returns int {\n return 0;\n}" + } + ], + "resolvable": true, + "data": { + "extName": "org.ballerinalang.langserver.codeaction.BallerinaCodeActionExtension", + "codeActionName": "Create Function", + "fileUri": "createUndefinedFunction15.bal", + "range": { + "start": { + "line": 1, + "character": 48 + }, + "end": { + "line": 1, + "character": 67 + } + }, + "actionData": { + "key": "node.range", + "value": { + "start": { + "line": 1.0, + "character": 48.0 + }, + "end": { + "line": 1.0, + "character": 67.0 + } + } + } + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction27.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction27.json new file mode 100644 index 000000000000..f1e970211618 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction27.json @@ -0,0 +1,57 @@ +{ + "position": { + "line": 1, + "character": 18 + }, + "source": "createUndefinedFunction16.bal", + "expected": [ + { + "title": "Create function 'toUpperCase(...)'", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 2, + "character": 1 + }, + "end": { + "line": 2, + "character": 1 + } + }, + "newText": "\n\nfunction toUpperCase(any a) returns any|error {\n return ;\n}" + } + ], + "resolvable": true, + "data": { + "extName": "org.ballerinalang.langserver.codeaction.BallerinaCodeActionExtension", + "codeActionName": "Create Function", + "fileUri": "createUndefinedFunction16.bal", + "range": { + "start": { + "line": 1, + "character": 11 + }, + "end": { + "line": 1, + "character": 30 + } + }, + "actionData": { + "key": "node.range", + "value": { + "start": { + "line": 1.0, + "character": 11.0 + }, + "end": { + "line": 1.0, + "character": 30.0 + } + } + } + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction28.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction28.json new file mode 100644 index 000000000000..58e5fc323303 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction28.json @@ -0,0 +1,57 @@ +{ + "position": { + "line": 0, + "character": 16 + }, + "source": "createUndefinedFunction17.bal", + "expected": [ + { + "title": "Create function 'toUpperCase(...)'", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 0, + "character": 28 + }, + "end": { + "line": 0, + "character": 28 + } + }, + "newText": "\n\nfunction toUpperCase(any a) returns any|error {\n return ;\n}" + } + ], + "resolvable": true, + "data": { + "extName": "org.ballerinalang.langserver.codeaction.BallerinaCodeActionExtension", + "codeActionName": "Create Function", + "fileUri": "createUndefinedFunction17.bal", + "range": { + "start": { + "line": 0, + "character": 8 + }, + "end": { + "line": 0, + "character": 27 + } + }, + "actionData": { + "key": "node.range", + "value": { + "start": { + "line": 0.0, + "character": 8.0 + }, + "end": { + "line": 0.0, + "character": 27.0 + } + } + } + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction29.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction29.json new file mode 100644 index 000000000000..c4a369e73a1d --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction29.json @@ -0,0 +1,57 @@ +{ + "position": { + "line": 0, + "character": 50 + }, + "source": "createUndefinedFunction18.bal", + "expected": [ + { + "title": "Create function 'toUpperCase(...)'", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 0, + "character": 64 + }, + "end": { + "line": 0, + "character": 64 + } + }, + "newText": "\n\nfunction toUpperCase(string letter) returns int {\n return 0;\n}" + } + ], + "resolvable": true, + "data": { + "extName": "org.ballerinalang.langserver.codeaction.BallerinaCodeActionExtension", + "codeActionName": "Create Function", + "fileUri": "createUndefinedFunction18.bal", + "range": { + "start": { + "line": 0, + "character": 44 + }, + "end": { + "line": 0, + "character": 63 + } + }, + "actionData": { + "key": "node.range", + "value": { + "start": { + "line": 0.0, + "character": 44.0 + }, + "end": { + "line": 0.0, + "character": 63.0 + } + } + } + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction30.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction30.json new file mode 100644 index 000000000000..ca672557e38c --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction30.json @@ -0,0 +1,57 @@ +{ + "position": { + "line": 0, + "character": 51 + }, + "source": "createUndefinedFunction19.bal", + "expected": [ + { + "title": "Create function 'toUpperCase(...)'", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 0, + "character": 62 + }, + "end": { + "line": 0, + "character": 62 + } + }, + "newText": "\n\nfunction toUpperCase(string letter) returns any|error {\n return ;\n}" + } + ], + "resolvable": true, + "data": { + "extName": "org.ballerinalang.langserver.codeaction.BallerinaCodeActionExtension", + "codeActionName": "Create Function", + "fileUri": "createUndefinedFunction19.bal", + "range": { + "start": { + "line": 0, + "character": 42 + }, + "end": { + "line": 0, + "character": 61 + } + }, + "actionData": { + "key": "node.range", + "value": { + "start": { + "line": 0.0, + "character": 42.0 + }, + "end": { + "line": 0.0, + "character": 61.0 + } + } + } + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction31.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction31.json new file mode 100644 index 000000000000..340dbc35887d --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/config/undefinedFunctionCodeAction31.json @@ -0,0 +1,57 @@ +{ + "position": { + "line": 6, + "character": 22 + }, + "source": "createUndefinedFunction20.bal", + "expected": [ + { + "title": "Create function 'foo(...)'", + "kind": "quickfix", + "edits": [ + { + "range": { + "start": { + "line": 7, + "character": 1 + }, + "end": { + "line": 7, + "character": 1 + } + }, + "newText": "\n\nfunction foo(string letter) returns MyType {\n return {value: \"\"};\n}" + } + ], + "resolvable": true, + "data": { + "extName": "org.ballerinalang.langserver.codeaction.BallerinaCodeActionExtension", + "codeActionName": "Create Function", + "fileUri": "createUndefinedFunction20.bal", + "range": { + "start": { + "line": 6, + "character": 19 + }, + "end": { + "line": 6, + "character": 30 + } + }, + "actionData": { + "key": "node.range", + "value": { + "start": { + "line": 6.0, + "character": 19.0 + }, + "end": { + "line": 6.0, + "character": 30.0 + } + } + } + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction14.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction14.bal new file mode 100644 index 000000000000..d27a2d100920 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction14.bal @@ -0,0 +1,3 @@ +function func() { + var x = from var letter in "Saman" select toUpperCase(letter); +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction15.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction15.bal new file mode 100644 index 000000000000..b897efdcbfe8 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction15.bal @@ -0,0 +1,3 @@ +function func() { + int[] x = from var letter in "Saman" select toUpperCase(letter); +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction16.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction16.bal new file mode 100644 index 000000000000..c2398b9f66a5 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction16.bal @@ -0,0 +1,3 @@ +function func() { + var x = toUpperCase(letter); +} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction17.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction17.bal new file mode 100644 index 000000000000..49d616fd023a --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction17.bal @@ -0,0 +1 @@ +var x = toUpperCase(letter); diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction18.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction18.bal new file mode 100644 index 000000000000..e887146d9100 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction18.bal @@ -0,0 +1 @@ +int[] x = from var letter in "Saman" select toUpperCase(letter); diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction19.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction19.bal new file mode 100644 index 000000000000..b78e95695c71 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction19.bal @@ -0,0 +1 @@ +var x = from var letter in "Saman" select toUpperCase(letter); diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction20.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction20.bal new file mode 100644 index 000000000000..d1dc0a649717 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-function/source/createUndefinedFunction20.bal @@ -0,0 +1,8 @@ +type MyType record {| + string value; +|}; + +function func() { + stream streamName = stream from string letter in "JohnSnow" + select foo(letter); +} \ No newline at end of file diff --git a/language-server/modules/langserver-core/src/test/resources/completion/function_body/config/config16.json b/language-server/modules/langserver-core/src/test/resources/completion/function_body/config/config16.json new file mode 100644 index 000000000000..3b8de757522c --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/function_body/config/config16.json @@ -0,0 +1,309 @@ +{ + "position": { + "line": 3, + "character": 12 + }, + "source": "function_body/source/source16.bal", + "description": "Test completions after qualified name in function body block", + "items": [ + { + "label": "TEST_INT_CONST1", + "kind": "Variable", + "detail": "1", + "documentation": { + "right": { + "kind": "markdown", + "value": "" + } + }, + "sortText": "C", + "insertText": "TEST_INT_CONST1", + "insertTextFormat": "Snippet" + }, + { + "label": "TEST_STRING_CONST1", + "kind": "Variable", + "detail": "\"HELLO WORLD\"", + "documentation": { + "right": { + "kind": "markdown", + "value": "" + } + }, + "sortText": "C", + "insertText": "TEST_STRING_CONST1", + "insertTextFormat": "Snippet" + }, + { + "label": "ENUM1_FIELD1", + "kind": "EnumMember", + "detail": "\"ENUM1_FIELD1\"", + "documentation": { + "right": { + "kind": "markdown", + "value": "" + } + }, + "sortText": "H", + "insertText": "ENUM1_FIELD1", + "insertTextFormat": "Snippet" + }, + { + "label": "AnnotationType", + "kind": "Struct", + "detail": "Record", + "sortText": "M", + "insertText": "AnnotationType", + "insertTextFormat": "Snippet" + }, + { + "label": "ResponseMessage", + "kind": "Enum", + "detail": "Union", + "documentation": { + "left": "The types of messages that are accepted by HTTP `listener` when sending out the outbound response." + }, + "sortText": "I", + "insertText": "ResponseMessage", + "insertTextFormat": "Snippet" + }, + { + "label": "RequestMessage", + "kind": "Enum", + "detail": "Union", + "documentation": { + "left": "The types of messages that are accepted by HTTP `client` when sending out the outbound request." + }, + "sortText": "I", + "insertText": "RequestMessage", + "insertTextFormat": "Snippet" + }, + { + "label": "TargetType", + "kind": "TypeParameter", + "detail": "Typedesc", + "documentation": { + "left": "The types of data values that are expected by the `client` to return after the data binding operation." + }, + "sortText": "N", + "insertText": "TargetType", + "insertTextFormat": "Snippet" + }, + { + "label": "ClientError", + "kind": "Event", + "detail": "Error", + "documentation": { + "left": "Defines the possible client error types." + }, + "sortText": "L", + "insertText": "ClientError", + "insertTextFormat": "Snippet" + }, + { + "label": "TargetType2", + "kind": "TypeParameter", + "detail": "Typedesc", + "documentation": { + "left": "The super type of all the types." + }, + "sortText": "N", + "insertText": "TargetType2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestEnum1", + "kind": "Enum", + "detail": "enum", + "sortText": "I", + "insertText": "TestEnum1", + "insertTextFormat": "Snippet" + }, + { + "label": "TestRecord1", + "kind": "Struct", + "detail": "Record", + "sortText": "M", + "insertText": "TestRecord1", + "insertTextFormat": "Snippet" + }, + { + "label": "TestRecord2", + "kind": "Struct", + "detail": "Record", + "sortText": "M", + "insertText": "TestRecord2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestMap2", + "kind": "TypeParameter", + "detail": "Map", + "sortText": "N", + "insertText": "TestMap2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestMap3", + "kind": "TypeParameter", + "detail": "Map", + "sortText": "N", + "insertText": "TestMap3", + "insertTextFormat": "Snippet" + }, + { + "label": "TestObject1", + "kind": "Interface", + "detail": "Object", + "sortText": "K", + "insertText": "TestObject1", + "insertTextFormat": "Snippet" + }, + { + "label": "ErrorOne", + "kind": "Event", + "detail": "Error", + "sortText": "L", + "insertText": "ErrorOne", + "insertTextFormat": "Snippet" + }, + { + "label": "ErrorTwo", + "kind": "Event", + "detail": "Error", + "sortText": "L", + "insertText": "ErrorTwo", + "insertTextFormat": "Snippet" + }, + { + "label": "Client", + "kind": "Interface", + "detail": "Class", + "documentation": { + "left": "The HTTP client provides the capability for initiating contact with a remote HTTP service. The API it\nprovides includes functions for the standard HTTP methods, forwarding a received request and sending requests\nusing custom HTTP verbs." + }, + "sortText": "K", + "insertText": "Client", + "insertTextFormat": "Snippet" + }, + { + "label": "Response", + "kind": "Interface", + "detail": "Class", + "documentation": { + "left": "Represents a response.\n" + }, + "sortText": "K", + "insertText": "Response", + "insertTextFormat": "Snippet" + }, + { + "label": "Listener", + "kind": "Interface", + "detail": "Class", + "sortText": "K", + "insertText": "Listener", + "insertTextFormat": "Snippet" + }, + { + "label": "TestClass1", + "kind": "Interface", + "detail": "Class", + "sortText": "K", + "insertText": "TestClass1", + "insertTextFormat": "Snippet" + }, + { + "label": "TEST_FUTURE_INT", + "kind": "Variable", + "detail": "future", + "sortText": "C", + "insertText": "TEST_FUTURE_INT", + "insertTextFormat": "Snippet" + }, + { + "label": "GLOBAL_VAR", + "kind": "Variable", + "detail": "int", + "sortText": "C", + "insertText": "GLOBAL_VAR", + "insertTextFormat": "Snippet" + }, + { + "label": "listener1", + "kind": "Variable", + "detail": "module1:Listener", + "sortText": "C", + "insertText": "listener1", + "insertTextFormat": "Snippet" + }, + { + "label": "function1()", + "kind": "Function", + "detail": "()", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \n \n" + } + }, + "sortText": "A", + "filterText": "function1", + "insertText": "function1()", + "insertTextFormat": "Snippet" + }, + { + "label": "function2()", + "kind": "Function", + "detail": "()", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \nThis is function2 \n" + } + }, + "sortText": "A", + "filterText": "function2", + "insertText": "function2()", + "insertTextFormat": "Snippet" + }, + { + "label": "function3(int param1, int param2, float... param3)", + "kind": "Function", + "detail": "int", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \nThis is function3 with input parameters\n \n**Params** \n- `int` param1: param1 Parameter Description \n- `int` param2: param2 Parameter Description \n- `float[]` param3: param3 Parameter Description \n \n**Return** `int` \n- Return Value Description \n \n" + } + }, + "sortText": "A", + "filterText": "function3", + "insertText": "function3(${1})", + "insertTextFormat": "Snippet", + "command": { + "title": "editor.action.triggerParameterHints", + "command": "editor.action.triggerParameterHints" + } + }, + { + "label": "function4(int param1, int param2, string param3, float... param4)", + "kind": "Function", + "detail": "()", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \nThis is function4 with input parameters\n \n**Params** \n- `int` param1: param1 Parameter Description \n- `int` param2: param2 Parameter Description \n- `string` param3: param3 Parameter Description(Defaultable) \n- `float[]` param4: param4 Parameter Description" + } + }, + "sortText": "A", + "filterText": "function4", + "insertText": "function4(${1})", + "insertTextFormat": "Snippet", + "command": { + "title": "editor.action.triggerParameterHints", + "command": "editor.action.triggerParameterHints" + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/function_body/config/config17.json b/language-server/modules/langserver-core/src/test/resources/completion/function_body/config/config17.json new file mode 100644 index 000000000000..262d8afe3d0f --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/function_body/config/config17.json @@ -0,0 +1,309 @@ +{ + "position": { + "line": 3, + "character": 13 + }, + "source": "function_body/source/source17.bal", + "description": "Test completions after qualified name in function body block", + "items": [ + { + "label": "TEST_INT_CONST1", + "kind": "Variable", + "detail": "1", + "documentation": { + "right": { + "kind": "markdown", + "value": "" + } + }, + "sortText": "C", + "insertText": "TEST_INT_CONST1", + "insertTextFormat": "Snippet" + }, + { + "label": "TEST_STRING_CONST1", + "kind": "Variable", + "detail": "\"HELLO WORLD\"", + "documentation": { + "right": { + "kind": "markdown", + "value": "" + } + }, + "sortText": "C", + "insertText": "TEST_STRING_CONST1", + "insertTextFormat": "Snippet" + }, + { + "label": "ENUM1_FIELD1", + "kind": "EnumMember", + "detail": "\"ENUM1_FIELD1\"", + "documentation": { + "right": { + "kind": "markdown", + "value": "" + } + }, + "sortText": "H", + "insertText": "ENUM1_FIELD1", + "insertTextFormat": "Snippet" + }, + { + "label": "AnnotationType", + "kind": "Struct", + "detail": "Record", + "sortText": "M", + "insertText": "AnnotationType", + "insertTextFormat": "Snippet" + }, + { + "label": "ResponseMessage", + "kind": "Enum", + "detail": "Union", + "documentation": { + "left": "The types of messages that are accepted by HTTP `listener` when sending out the outbound response." + }, + "sortText": "I", + "insertText": "ResponseMessage", + "insertTextFormat": "Snippet" + }, + { + "label": "RequestMessage", + "kind": "Enum", + "detail": "Union", + "documentation": { + "left": "The types of messages that are accepted by HTTP `client` when sending out the outbound request." + }, + "sortText": "I", + "insertText": "RequestMessage", + "insertTextFormat": "Snippet" + }, + { + "label": "TargetType", + "kind": "TypeParameter", + "detail": "Typedesc", + "documentation": { + "left": "The types of data values that are expected by the `client` to return after the data binding operation." + }, + "sortText": "N", + "insertText": "TargetType", + "insertTextFormat": "Snippet" + }, + { + "label": "ClientError", + "kind": "Event", + "detail": "Error", + "documentation": { + "left": "Defines the possible client error types." + }, + "sortText": "L", + "insertText": "ClientError", + "insertTextFormat": "Snippet" + }, + { + "label": "TargetType2", + "kind": "TypeParameter", + "detail": "Typedesc", + "documentation": { + "left": "The super type of all the types." + }, + "sortText": "N", + "insertText": "TargetType2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestEnum1", + "kind": "Enum", + "detail": "enum", + "sortText": "I", + "insertText": "TestEnum1", + "insertTextFormat": "Snippet" + }, + { + "label": "TestRecord1", + "kind": "Struct", + "detail": "Record", + "sortText": "M", + "insertText": "TestRecord1", + "insertTextFormat": "Snippet" + }, + { + "label": "TestRecord2", + "kind": "Struct", + "detail": "Record", + "sortText": "M", + "insertText": "TestRecord2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestMap2", + "kind": "TypeParameter", + "detail": "Map", + "sortText": "N", + "insertText": "TestMap2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestMap3", + "kind": "TypeParameter", + "detail": "Map", + "sortText": "N", + "insertText": "TestMap3", + "insertTextFormat": "Snippet" + }, + { + "label": "TestObject1", + "kind": "Interface", + "detail": "Object", + "sortText": "K", + "insertText": "TestObject1", + "insertTextFormat": "Snippet" + }, + { + "label": "ErrorOne", + "kind": "Event", + "detail": "Error", + "sortText": "L", + "insertText": "ErrorOne", + "insertTextFormat": "Snippet" + }, + { + "label": "ErrorTwo", + "kind": "Event", + "detail": "Error", + "sortText": "L", + "insertText": "ErrorTwo", + "insertTextFormat": "Snippet" + }, + { + "label": "Client", + "kind": "Interface", + "detail": "Class", + "documentation": { + "left": "The HTTP client provides the capability for initiating contact with a remote HTTP service. The API it\nprovides includes functions for the standard HTTP methods, forwarding a received request and sending requests\nusing custom HTTP verbs." + }, + "sortText": "K", + "insertText": "Client", + "insertTextFormat": "Snippet" + }, + { + "label": "Response", + "kind": "Interface", + "detail": "Class", + "documentation": { + "left": "Represents a response.\n" + }, + "sortText": "K", + "insertText": "Response", + "insertTextFormat": "Snippet" + }, + { + "label": "Listener", + "kind": "Interface", + "detail": "Class", + "sortText": "K", + "insertText": "Listener", + "insertTextFormat": "Snippet" + }, + { + "label": "TestClass1", + "kind": "Interface", + "detail": "Class", + "sortText": "K", + "insertText": "TestClass1", + "insertTextFormat": "Snippet" + }, + { + "label": "TEST_FUTURE_INT", + "kind": "Variable", + "detail": "future", + "sortText": "C", + "insertText": "TEST_FUTURE_INT", + "insertTextFormat": "Snippet" + }, + { + "label": "GLOBAL_VAR", + "kind": "Variable", + "detail": "int", + "sortText": "C", + "insertText": "GLOBAL_VAR", + "insertTextFormat": "Snippet" + }, + { + "label": "listener1", + "kind": "Variable", + "detail": "module1:Listener", + "sortText": "C", + "insertText": "listener1", + "insertTextFormat": "Snippet" + }, + { + "label": "function1()", + "kind": "Function", + "detail": "()", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \n \n" + } + }, + "sortText": "A", + "filterText": "function1", + "insertText": "function1()", + "insertTextFormat": "Snippet" + }, + { + "label": "function2()", + "kind": "Function", + "detail": "()", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \nThis is function2 \n" + } + }, + "sortText": "A", + "filterText": "function2", + "insertText": "function2()", + "insertTextFormat": "Snippet" + }, + { + "label": "function3(int param1, int param2, float... param3)", + "kind": "Function", + "detail": "int", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \nThis is function3 with input parameters\n \n**Params** \n- `int` param1: param1 Parameter Description \n- `int` param2: param2 Parameter Description \n- `float[]` param3: param3 Parameter Description \n \n**Return** `int` \n- Return Value Description \n \n" + } + }, + "sortText": "A", + "filterText": "function3", + "insertText": "function3(${1})", + "insertTextFormat": "Snippet", + "command": { + "title": "editor.action.triggerParameterHints", + "command": "editor.action.triggerParameterHints" + } + }, + { + "label": "function4(int param1, int param2, string param3, float... param4)", + "kind": "Function", + "detail": "()", + "documentation": { + "right": { + "kind": "markdown", + "value": "**Package:** _ballerina/module1:0.1.0_ \n \nThis is function4 with input parameters\n \n**Params** \n- `int` param1: param1 Parameter Description \n- `int` param2: param2 Parameter Description \n- `string` param3: param3 Parameter Description(Defaultable) \n- `float[]` param4: param4 Parameter Description" + } + }, + "sortText": "A", + "filterText": "function4", + "insertText": "function4(${1})", + "insertTextFormat": "Snippet", + "command": { + "title": "editor.action.triggerParameterHints", + "command": "editor.action.triggerParameterHints" + } + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/function_body/source/source16.bal b/language-server/modules/langserver-core/src/test/resources/completion/function_body/source/source16.bal new file mode 100644 index 000000000000..a976ed6b8699 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/function_body/source/source16.bal @@ -0,0 +1,7 @@ +import ballerina/module1; + +public function main() { + module1: + + map data = {}; +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/function_body/source/source17.bal b/language-server/modules/langserver-core/src/test/resources/completion/function_body/source/source17.bal new file mode 100644 index 000000000000..c13002e5af40 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/function_body/source/source17.bal @@ -0,0 +1,7 @@ +import ballerina/module1; + +public function main() { + module1:T + + map data = {}; +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org.json b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org.json index 7c3778bfeded..e25fe8bb39b7 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org.json @@ -4,7 +4,7 @@ "character": 18 }, "source": "import_decl/source/import_decl_with_ballerinax_org.bal", - "description": "", + "description": "Test completions for ballerinax packages", "items": [ { "label": "azure.ad", diff --git a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org2.json b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org2.json new file mode 100644 index 000000000000..1459ef4ee62f --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org2.json @@ -0,0 +1,26 @@ +{ + "position": { + "line": 0, + "character": 20 + }, + "source": "import_decl/source/import_decl_with_ballerinax_org2.bal", + "description": "Test completions for ballerinax packages", + "items": [ + { + "label": "azure.ad", + "kind": "Module", + "detail": "Module", + "sortText": "D", + "insertText": "azure.ad", + "insertTextFormat": "Snippet" + }, + { + "label": "azure.qnamaker", + "kind": "Module", + "detail": "Module", + "sortText": "D", + "insertText": "azure.qnamaker", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org3.json b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org3.json new file mode 100644 index 000000000000..51944bd5a5e1 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org3.json @@ -0,0 +1,56 @@ +{ + "position": { + "line": 0, + "character": 24 + }, + "source": "import_decl/source/import_decl_with_ballerinax_org3.bal", + "description": "Test completions for ballerinax packages", + "items": [ + { + "label": "azure.ad", + "kind": "Module", + "detail": "Module", + "sortText": "A", + "insertText": "azure.ad", + "insertTextFormat": "Snippet", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 1, + "character": 0 + } + }, + "newText": "" + } + ] + }, + { + "label": "azure.qnamaker", + "kind": "Module", + "detail": "Module", + "sortText": "A", + "insertText": "azure.qnamaker", + "insertTextFormat": "Snippet", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 1, + "character": 0 + } + }, + "newText": "" + } + ] + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org4.json b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org4.json new file mode 100644 index 000000000000..9409a3f7e94e --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/config/import_decl_with_ballerinax_org4.json @@ -0,0 +1,33 @@ +{ + "position": { + "line": 0, + "character": 25 + }, + "source": "import_decl/source/import_decl_with_ballerinax_org4.bal", + "description": "Test completions for ballerinax packages", + "items": [ + { + "label": "azure.ad", + "kind": "Module", + "detail": "Module", + "sortText": "A", + "insertText": "azure.ad", + "insertTextFormat": "Snippet", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 18 + }, + "end": { + "line": 0, + "character": 24 + } + }, + "newText": "" + } + ] + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org2.bal b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org2.bal new file mode 100644 index 000000000000..40d1eb255e73 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org2.bal @@ -0,0 +1 @@ +import ballerinax/az diff --git a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org3.bal b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org3.bal new file mode 100644 index 000000000000..79ce6f8d5512 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org3.bal @@ -0,0 +1 @@ +import ballerinax/azure. diff --git a/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org4.bal b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org4.bal new file mode 100644 index 000000000000..3187053e3f1b --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/import_decl/source/import_decl_with_ballerinax_org4.bal @@ -0,0 +1 @@ +import ballerinax/azure.a diff --git a/language-server/modules/langserver-core/src/test/resources/completion/module_part_context/config/config18.json b/language-server/modules/langserver-core/src/test/resources/completion/module_part_context/config/config18.json new file mode 100644 index 000000000000..cf924242df85 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/module_part_context/config/config18.json @@ -0,0 +1,167 @@ +{ + "position": { + "line": 2, + "character": 8 + }, + "source": "module_part_context/source/source19.bal", + "description": "Test completions after qualified name in module part node", + "items": [ + { + "label": "AnnotationType", + "kind": "Struct", + "detail": "Record", + "sortText": "CA", + "insertText": "AnnotationType", + "insertTextFormat": "Snippet" + }, + { + "label": "ResponseMessage", + "kind": "Enum", + "detail": "Union", + "documentation": { + "left": "The types of messages that are accepted by HTTP `listener` when sending out the outbound response." + }, + "sortText": "CA", + "insertText": "ResponseMessage", + "insertTextFormat": "Snippet" + }, + { + "label": "RequestMessage", + "kind": "Enum", + "detail": "Union", + "documentation": { + "left": "The types of messages that are accepted by HTTP `client` when sending out the outbound request." + }, + "sortText": "CA", + "insertText": "RequestMessage", + "insertTextFormat": "Snippet" + }, + { + "label": "TargetType", + "kind": "TypeParameter", + "detail": "Typedesc", + "documentation": { + "left": "The types of data values that are expected by the `client` to return after the data binding operation." + }, + "sortText": "CA", + "insertText": "TargetType", + "insertTextFormat": "Snippet" + }, + { + "label": "ClientError", + "kind": "Event", + "detail": "Error", + "documentation": { + "left": "Defines the possible client error types." + }, + "sortText": "CA", + "insertText": "ClientError", + "insertTextFormat": "Snippet" + }, + { + "label": "TargetType2", + "kind": "TypeParameter", + "detail": "Typedesc", + "documentation": { + "left": "The super type of all the types." + }, + "sortText": "CA", + "insertText": "TargetType2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestRecord1", + "kind": "Struct", + "detail": "Record", + "sortText": "CA", + "insertText": "TestRecord1", + "insertTextFormat": "Snippet" + }, + { + "label": "TestRecord2", + "kind": "Struct", + "detail": "Record", + "sortText": "CA", + "insertText": "TestRecord2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestMap2", + "kind": "TypeParameter", + "detail": "Map", + "sortText": "CA", + "insertText": "TestMap2", + "insertTextFormat": "Snippet" + }, + { + "label": "TestMap3", + "kind": "TypeParameter", + "detail": "Map", + "sortText": "CA", + "insertText": "TestMap3", + "insertTextFormat": "Snippet" + }, + { + "label": "TestObject1", + "kind": "Interface", + "detail": "Object", + "sortText": "CA", + "insertText": "TestObject1", + "insertTextFormat": "Snippet" + }, + { + "label": "ErrorOne", + "kind": "Event", + "detail": "Error", + "sortText": "CA", + "insertText": "ErrorOne", + "insertTextFormat": "Snippet" + }, + { + "label": "ErrorTwo", + "kind": "Event", + "detail": "Error", + "sortText": "CA", + "insertText": "ErrorTwo", + "insertTextFormat": "Snippet" + }, + { + "label": "Client", + "kind": "Interface", + "detail": "Class", + "documentation": { + "left": "The HTTP client provides the capability for initiating contact with a remote HTTP service. The API it\nprovides includes functions for the standard HTTP methods, forwarding a received request and sending requests\nusing custom HTTP verbs." + }, + "sortText": "CA", + "insertText": "Client", + "insertTextFormat": "Snippet" + }, + { + "label": "Response", + "kind": "Interface", + "detail": "Class", + "documentation": { + "left": "Represents a response.\n" + }, + "sortText": "CA", + "insertText": "Response", + "insertTextFormat": "Snippet" + }, + { + "label": "Listener", + "kind": "Interface", + "detail": "Class", + "sortText": "CA", + "insertText": "Listener", + "insertTextFormat": "Snippet" + }, + { + "label": "TestClass1", + "kind": "Interface", + "detail": "Class", + "sortText": "CA", + "insertText": "TestClass1", + "insertTextFormat": "Snippet" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/completion/module_part_context/source/source19.bal b/language-server/modules/langserver-core/src/test/resources/completion/module_part_context/source/source19.bal new file mode 100644 index 000000000000..26fcba739fae --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/completion/module_part_context/source/source19.bal @@ -0,0 +1,8 @@ +import ballerina/module1; + +module1: + +map data = {}; + +public function main() { +} diff --git a/tests/jballerina-benchmark-test/build.gradle b/tests/jballerina-benchmark-test/build.gradle index b99a573ba208..27087613bd23 100644 --- a/tests/jballerina-benchmark-test/build.gradle +++ b/tests/jballerina-benchmark-test/build.gradle @@ -115,3 +115,4 @@ test { } } +generateMetadataFileForMavenJavaPublication.dependsOn(copyToLib) diff --git a/tests/jballerina-integration-test/build.gradle b/tests/jballerina-integration-test/build.gradle index b352ecc00c69..79474e36dce9 100644 --- a/tests/jballerina-integration-test/build.gradle +++ b/tests/jballerina-integration-test/build.gradle @@ -131,3 +131,4 @@ task createLaunchListenerUtilsLib(type: Copy) { tasks.test.dependsOn(createLaunchListenerUtilsLib) tasks.compileTestJava.dependsOn(":ballerina-io-internal:copyInteropImports") +generateMetadataFileForMavenJavaPublication.dependsOn(copyToLib) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bir/BirVariableOptimizationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bir/BirVariableOptimizationTest.java index 80c7596d8ad8..e01f368f85c9 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bir/BirVariableOptimizationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bir/BirVariableOptimizationTest.java @@ -25,7 +25,7 @@ import org.testng.annotations.Test; import org.wso2.ballerinalang.compiler.bir.emit.BIREmitter; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; -import org.wso2.ballerinalang.compiler.bir.optimizer.LivenessAnalyzer; +import org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer; import org.wso2.ballerinalang.compiler.util.CompilerContext; import java.io.IOException; @@ -36,7 +36,7 @@ import java.util.stream.Stream; /** - * Test to confirm the functionality of the {@link LivenessAnalyzer}. + * Test to confirm the functionality of the {@link BIROptimizer}. */ public class BirVariableOptimizationTest { private BIREmitter birEmitter; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayInitializerExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayInitializerExprTest.java index 131a1ea2c6ae..c98288c554dc 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayInitializerExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/statements/arrays/ArrayInitializerExprTest.java @@ -159,6 +159,11 @@ public void testInferredArrayInitWithInGrpExpr() { BRunUtil.invoke(compileResult, "testInferredArrayInitWithInGrpExpr"); } + @Test + public void testArrayInitWithGlobalVars() { + BRunUtil.invoke(compileResult, "testArrayInitWithGlobalVars"); + } + @AfterClass public void tearDown() { compileResult = null; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/bytetype/BByteArrayValueNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/bytetype/BByteArrayValueNegativeTest.java index a55003901839..8735b91ec501 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/bytetype/BByteArrayValueNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/bytetype/BByteArrayValueNegativeTest.java @@ -33,44 +33,30 @@ public class BByteArrayValueNegativeTest { public void testBlobValueNegative() { CompileResult result = BCompileUtil.compile("test-src/types/byte/byte-array-value-negative.bal"); int index = 0; - BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[]', found 'other'", 2, 16); BAssertUtil.validateError(result, index++, "undefined symbol 'base1'", 2, 16); BAssertUtil.validateError(result, index++, "invalid expr in assignment lhs", 2, 22); BAssertUtil.validateError(result, index++, "missing semicolon token", 2, 22); - BAssertUtil.validateError(result, index++, "invalid literal for type 'other': raw templates can only " + - "be assigned to abstract subtypes of 'ballerina/lang.object:0.0.0:RawTemplate'", 2, 24); BAssertUtil.validateError(result, index++, "missing equal token", 2, 24); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[]', found 'other'", 3, 16); BAssertUtil.validateError(result, index++, "undefined symbol 'base'", 3, 16); BAssertUtil.validateError(result, index++, "invalid expr in assignment lhs", 3, 21); BAssertUtil.validateError(result, index++, "missing semicolon token", 3, 21); - BAssertUtil.validateError(result, index++, "invalid literal for type 'other': raw templates can only " + - "be assigned to abstract subtypes of 'ballerina/lang.object:0.0.0:RawTemplate'", 3, 24); BAssertUtil.validateError(result, index++, "missing equal token", 3, 24); BAssertUtil.validateError(result, index++, "invalid base16 content in byte array literal", 4, 24); BAssertUtil.validateError(result, index++, "invalid base16 content in byte array literal", 5, 24); BAssertUtil.validateError(result, index++, "invalid base16 content in byte array literal", 6, 24); BAssertUtil.validateError(result, index++, "invalid base16 content in byte array literal", 7, 24); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[]', found 'other'", 8, 16); BAssertUtil.validateError(result, index++, "missing byte array content", 8, 16); BAssertUtil.validateError(result, index++, "missing binary operator", 8, 23); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[]', found 'other'", 12, 16); BAssertUtil.validateError(result, index++, "undefined symbol 'base6'", 12, 16); BAssertUtil.validateError(result, index++, "invalid expr in assignment lhs", 12, 22); BAssertUtil.validateError(result, index++, "missing semicolon token", 12, 22); - BAssertUtil.validateError(result, index++, "invalid literal for type 'other': raw templates can only " + - "be assigned to abstract subtypes of 'ballerina/lang.object:0.0.0:RawTemplate'", 12, 24); BAssertUtil.validateError(result, index++, "missing equal token", 12, 24); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[]', found 'other'", 13, 16); BAssertUtil.validateError(result, index++, "undefined symbol 'base'", 13, 16); BAssertUtil.validateError(result, index++, "invalid expr in assignment lhs", 13, 21); BAssertUtil.validateError(result, index++, "missing semicolon token", 13, 21); - BAssertUtil.validateError(result, index++, "invalid literal for type 'other': raw templates can only " + - "be assigned to abstract subtypes of 'ballerina/lang.object:0.0.0:RawTemplate'", 13, 24); BAssertUtil.validateError(result, index++, "missing equal token", 13, 24); BAssertUtil.validateError(result, index++, "invalid base64 content in byte array literal", 14, 24); BAssertUtil.validateError(result, index++, "invalid base64 content in byte array literal", 15, 24); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[]', found 'other'", 16, 16); BAssertUtil.validateError(result, index++, "missing byte array content", 16, 16); BAssertUtil.validateError(result, index++, "missing binary operator", 16, 23); BAssertUtil.validateError(result, index++, "invalid base64 content in byte array literal", 17, 24); @@ -81,13 +67,11 @@ public void testBlobValueNegative() { BAssertUtil.validateError(result, index++, "incompatible types: expected 'int[2]', found 'byte[3]'", 30, 16); BAssertUtil.validateError(result, index++, "incompatible types: 'byte[2]' cannot be cast to " + "'(byte[3] & readonly)'", 33, 16); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[]', found 'other'", 33, 16); BAssertUtil.validateError(result, index++, "incompatible types: 'byte[3]' cannot be cast to " + "'(int[2] & readonly)'", 34, 15); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'int[]', found 'other'", 34, 15); + BAssertUtil.validateError(result, index++, "incompatible types: 'byte[3]' cannot be cast to " + "'(string[] & readonly)'", 35, 18); - BAssertUtil.validateError(result, index++, "incompatible types: expected 'string[]', found 'other'", 35, 18); BAssertUtil.validateError(result, index++, "incompatible types: expected 'byte[3]', found 'byte[2]'", 39, 17); Assert.assertEquals(result.getErrorCount(), index); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantAssignmentTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantAssignmentTest.java index 567169ab32a9..a10511d9496c 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantAssignmentTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantAssignmentTest.java @@ -131,6 +131,12 @@ public void testConstantAssignmentNegative() { "'record {| (record {| \"a\" a; |} & readonly) x; int i; |}'", 24, 55); BAssertUtil.validateError(negativeCompileResult, i++, "missing non-defaultable required record field 'a'", 26, 14); + BAssertUtil.validateError(negativeCompileResult, i++, + "incompatible types: expected 'string[]', found '[170,187]'", 28, 20); + BAssertUtil.validateError(negativeCompileResult, i++, + "incompatible types: expected '[string,int]', found '[170,187]'", 30, 26); + BAssertUtil.validateError(negativeCompileResult, i++, + "incompatible types: expected '[170]', found '[170,187]'", 32, 19); Assert.assertEquals(negativeCompileResult.getErrorCount(), i); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantTypeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantTypeTest.java index a3b48d7468ee..7e41702477b9 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantTypeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/constant/ConstantTypeTest.java @@ -53,7 +53,8 @@ public Object[] testFunctions() { "testTypesOfConstantMaps", "testConstTypesInline", "testInvalidRuntimeUpdateOfConstMaps", - "testResolvingConstValForConstantsOfUserDefinedTypes" + "testResolvingConstValForConstantsOfUserDefinedTypes", + "testConstByteArrLiteral" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/$lambda$_0 b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/$lambda$_0 index bfcba50a1fda..a78f1154989f 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/$lambda$_0 +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/$lambda$_0 @@ -9,8 +9,8 @@ $lambda$_0 function(map}>, i %12(TEMP) int; %14(TEMP) string; %16(TEMP) int; - %19(LOCAL) string; - %23(TEMP) string; + %18(LOCAL) string; + %21(TEMP) string; bb0 { %3 = ConstLoad 34; @@ -30,8 +30,8 @@ $lambda$_0 function(map}>, i } bb2 { %14 = ConstLoad l; - %23 = %1[%14]; - %19 = s + %23; + %21 = %1[%14]; + %18 = s + %21; %14 = ConstLoad a; %12 = %1[%14]; %0 = %3 + %12; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock index b1ddbf4699f7..26b58402ab6c 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bir/bir-dump/failLockWithinLock @@ -15,6 +15,7 @@ failLockWithinLock function() -> (int, string) { %23(TEMP) map; %24(LOCAL) error; %41(TEMP) int; + %42(TEMP) int; bb0 { lock -> bb1; @@ -102,6 +103,7 @@ failLockWithinLock function() -> (int, string) { bb19 { %19 = newType (int, string); %41 = ConstLoad 2; + %42 = lockWithinLockInt; %0 = newArray %19[%41]; GOTO bb20; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/statements/arrays/array-initializer-expr.bal b/tests/jballerina-unit-test/src/test/resources/test-src/statements/arrays/array-initializer-expr.bal index 6de7ccda129c..358c94950e63 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/statements/arrays/array-initializer-expr.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/statements/arrays/array-initializer-expr.bal @@ -1,3 +1,60 @@ +// Copyright (c) 2019, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. +// +// WSO2 LLC. licenses this file to you 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. + +import ballerina/test; + +int num = 0; +string str = "a"; + +class ArrayTest { + + int num = 0; + + function getNum() returns int { + self.num += 1; + return 2; + } + + function testArrayInitWithSelfVars() { + int[] arr = [0, 1, self.num, self.getNum(), self.num, num, getNum(), num]; + test:assertEquals(arr, [0, 1, 0, 2, 1, 1, 2, 2], "Array values are not equal"); + } +} + +function testArrayInitWithGlobalVars() { + int[] arr = [1, num, 3, getNum(), num]; + test:assertEquals(arr, [1, 0, 3, 1, 1], "Array values are not equal"); + + string[] arr2 = ["q", str, "w", getStr(), "e", str]; + test:assertEquals(arr2, ["q", "ab", "w", "ab", "e", "ab"], "Array values are not equal"); + + ArrayTest arrayTest = new ArrayTest(); + arrayTest.testArrayInitWithSelfVars(); +} + +function getNum() returns int { + num = num + 1; + return num; +} + +function getStr() returns string { + str = str + "b"; + return str; +} + function arrayInitTest() returns (int) { int[] arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; int size = 11; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-assignment-negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-assignment-negative.bal index 23d7fbadf95c..64dfac4d73a6 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-assignment-negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-assignment-negative.bal @@ -24,3 +24,9 @@ const Foo F1 = {x: {b : "a"}, i: 1, c: 2}; const record{|X x; int i;|} F2 = {x: {b : "a"}, i: 1, c: 2}; const X F3 = {b : "b"}; + +const string[] Y = base16 `aabb`; + +const [string, int] Z = base16 `aabb`; + +const [170] Z1 = base16 `aabb`; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-type.bal index 006a67d51355..3f4faf6e34ff 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/constant/constant-type.bal @@ -318,6 +318,58 @@ function testResolvingConstValForConstantsOfUserDefinedTypes() { assertEqual(q, -60); } +const byte[] data1 = base16 `55 EE 66`; +const byte[] data2 = base64 `ABCD pqrs`; + +const byte[3] data3 = base16 `55 EE 66`; +const byte[6] data4 = base64 `ABCD pqrs`; + +const data5 = base16 `55 EE 66`; +const data6 = base64 `ABCD pqrs`; + +const byte[*] data7 = base16 `55 EE 66`; +const byte[*] data8 = base64 `ABCD pqrs`; + +const [170] data9 = base16 `aa`; +const [170, 187] data10 = base16 `aabb`; + +function testConstByteArrLiteral() { + assertEqual(data1.length(), 3); + assertEqual(data2.length(), 6); + assertEqual(data1[0], 0x55); + assertEqual(data1[1], 0xEE); + assertEqual(data1[2], 0x66); + assertEqual(data2[0], 0); + assertEqual(data2[1], 16); + assertEqual(data2[2], 131); + assertEqual(data2[3], 166); + assertEqual(data2[4], 170); + assertEqual(data2[5], 236); + + assertEqual(data3.length(), 3); + assertEqual(data4.length(), 6); + assertEqual(data3[1], 0xEE); + assertEqual(data4[2], 131); + + assertEqual(data5.length(), 3); + assertEqual(data6.length(), 6); + assertEqual(data5[1], 0xEE); + assertEqual(data6[2], 131); + + assertEqual(data5.length(), 3); + assertEqual(data6.length(), 6); + assertEqual(data5[1], 0xEE); + assertEqual(data6[2], 131); + + assertEqual(data7.length(), 3); + assertEqual(data8.length(), 6); + assertEqual(data7[1], 0xEE); + assertEqual(data8[2], 131); + + assertEqual(data9[0], 170); + assertEqual(data10[1], 187); +} + function assertInvalidUpdateError(error? res, string expectedDetailMessage) { assertTrue(res is error); error err = res;