Code review comment: If we move this logic to a function, we can improve the readability of the code. WDYT?

Code under review:
public void visit(BLangListConstructorExpr listConstructor) {
        
        
        BType actualType = symTable.semanticError;
        resultType = symTable.semanticError;

        int expTypeTag = expType.tag;
        if ((expTypeTag == TypeTags.ANY || expTypeTag == TypeTags.ANYDATA || expTypeTag == TypeTags.NONE)
                && listConstructor.exprs.isEmpty()) {
            dlog.error(listConstructor.pos, DiagnosticCode.INVALID_LIST_CONSTRUCTOR, expType);
            return;
        }

        if (expTypeTag == TypeTags.JSON) {
            checkExprs(listConstructor.exprs, this.env, expType);
            actualType = expType;
        } else if (expTypeTag == TypeTags.ARRAY) {
            BArrayType arrayType = (BArrayType) expType;
            if (arrayType.state == BArrayState.OPEN_SEALED) {
                arrayType.size = listConstructor.exprs.size();
                arrayType.state = BArrayState.CLOSED_SEALED;
            } else if ((arrayType.state != BArrayState.UNSEALED) && (arrayType.size != listConstructor.exprs.size())) {
                if (arrayType.size < listConstructor.exprs.size()) {
                    dlog.error(listConstructor.pos,
                               DiagnosticCode.MISMATCHING_ARRAY_LITERAL_VALUES, arrayType.size,
                               listConstructor.exprs.size());
                    return;
                }
                if (!types.hasFillerValue(arrayType.eType)) {
                    dlog.error(listConstructor.pos, DiagnosticCode.INVALID_LIST_CONSTRUCTOR, expType);
                    return;
                }
                arrayType.state = BArrayState.CLOSED_SEALED;
            }
            checkExprs(listConstructor.exprs, this.env, arrayType.eType);
            actualType = arrayType;
        } else if (expTypeTag == TypeTags.UNION) {
            Set<BType> expTypes = ((BUnionType) expType).getMemberTypes();
            List<BType> matchedTypeList = expTypes.stream()
                    .filter(type -> type.tag == TypeTags.ARRAY || type.tag == TypeTags.TUPLE)
                    .collect(Collectors.toList());
            if (matchedTypeList.isEmpty()) {
                dlog.error(listConstructor.pos, DiagnosticCode.INCOMPATIBLE_TYPES, expType, actualType);
            } else if (matchedTypeList.size() == 1) {
                
                actualType = matchedTypeList.get(0);
                if (actualType.tag == TypeTags.ARRAY) {
                    checkExprs(listConstructor.exprs, this.env, ((BArrayType) actualType).eType);
                } else {
                    BTupleType tupleType = (BTupleType) actualType;
                    List<BType> results = new ArrayList<>();
                    BType restType = null;
                    for (int i = 0; i < listConstructor.exprs.size(); i++) {
                        BType expType, actType;
                        if (i < tupleType.tupleTypes.size()) {
                            expType = tupleType.tupleTypes.get(i);
                            actType = checkExpr(listConstructor.exprs.get(i), env, expType);
                            results.add(expType.tag != TypeTags.NONE ? expType : actType);
                        } else {
                            if (tupleType.restType != null) {
                                restType = checkExpr(listConstructor.exprs.get(i), env, tupleType.restType);
                            } else {
                                
                                dlog.error(listConstructor.pos, DiagnosticCode.SYNTAX_ERROR,
                                        "tuple and expression size does not match");
                                return;
                            }
                        }
                    }
                    actualType = new BTupleType(results);
                    ((BTupleType) actualType).restType = restType;
                }
            } else {
                
                
                actualType = checkArrayLiteralExpr(listConstructor);
            }
        } else if (expTypeTag == TypeTags.TYPEDESC) {
            
            List<BType> results = new ArrayList<>();
            listConstructor.isTypedescExpr = true;
            for (int i = 0; i < listConstructor.exprs.size(); i++) {
                results.add(checkExpr(listConstructor.exprs.get(i), env, symTable.noType));
            }
            List<BType> actualTypes = new ArrayList<>();
            for (int i = 0; i < listConstructor.exprs.size(); i++) {
                final BLangExpression expr = listConstructor.exprs.get(i);
                if (expr.getKind() == NodeKind.TYPEDESC_EXPRESSION) {
                    actualTypes.add(((BLangTypedescExpr) expr).resolvedType);
                } else if (expr.getKind() == NodeKind.SIMPLE_VARIABLE_REF) {
                    actualTypes.add(((BLangSimpleVarRef) expr).symbol.type);
                } else {
                    actualTypes.add(results.get(i));
                }
            }
            if (actualTypes.size() == 1) {
                listConstructor.typedescType = actualTypes.get(0);
            } else {
                listConstructor.typedescType = new BTupleType(actualTypes);
            }
            resultType = new BTypedescType(listConstructor.typedescType, null);
            return;
        } else if (expTypeTag == TypeTags.TUPLE) {
            BTupleType tupleType = (BTupleType) this.expType;
            if ((tupleType.restType != null && (tupleType.tupleTypes.size() > listConstructor.exprs.size()))
                    || (tupleType.restType == null && tupleType.tupleTypes.size() != listConstructor.exprs.size())) {
                dlog.error(listConstructor.pos, DiagnosticCode.SYNTAX_ERROR,
                        "tuple and expression size does not match");
                return;
            }
            List<BType> expTypes = tupleType.tupleTypes;
            List<BType> results = new ArrayList<>();
            BType restType = null;

            
            if (tupleType.restType != null && listConstructor.exprs.size() < expTypes.size() + 1) {
                restType = tupleType.restType;
            }

            for (int i = 0; i < listConstructor.exprs.size(); i++) {
                
                
                BType expType, actType;
                if (i < expTypes.size()) {
                    expType = expTypes.get(i);
                    actType = checkExpr(listConstructor.exprs.get(i), env, expType);
                    results.add(expType.tag != TypeTags.NONE ? expType : actType);
                } else {
                    restType = checkExpr(listConstructor.exprs.get(i), env, tupleType.restType);
                }
            }
            actualType = new BTupleType(results);
            ((BTupleType) actualType).restType = restType;
        } else if (listConstructor.exprs.size() > 1) {
            
            LinkedHashSet<BType> narrowTypes = new LinkedHashSet<>();
            LinkedHashSet<BType> broadTypesSet = new LinkedHashSet<>();
            BType[] inferredTypes = checkArrayExpr(listConstructor, env);
            for (BType type : inferredTypes) {
                if (narrowTypes.stream().noneMatch(nType -> types.isSameType(type, nType))) {
                    narrowTypes.add(type);
                }
            }
            BType broadType;
            for (BType t1 : narrowTypes) {
                broadType = t1;
                for (BType t2 : narrowTypes) {
                    if (types.isAssignable(t2, t1)) {
                        broadType = t1;
                    } else if (types.isAssignable(t1, t2)) {
                        broadType = t2;
                    }
                }
                broadTypesSet.add(broadType);
            }
            BType eType;
            if (broadTypesSet.size() > 1) {
                
                eType = BUnionType.create(null, broadTypesSet);
            } else {
                eType = broadTypesSet.toArray(new BType[0])[0];
            }
            BArrayType arrayType = new BArrayType(eType);
            checkExprs(listConstructor.exprs, this.env, arrayType.eType);
            actualType = arrayType;
        } else if (expTypeTag != TypeTags.SEMANTIC_ERROR) {
            actualType = checkArrayLiteralExpr(listConstructor);
        }
        resultType = types.checkType(listConstructor, actualType, expType);
    }

Line commented on: return;

Revised code:
public void visit(BLangListConstructorExpr listConstructor) {
        
        
        BType actualType = symTable.semanticError;
        resultType = symTable.semanticError;

        int expTypeTag = expType.tag;
        if ((expTypeTag == TypeTags.ANY || expTypeTag == TypeTags.ANYDATA || expTypeTag == TypeTags.NONE)
                && listConstructor.exprs.isEmpty()) {
            dlog.error(listConstructor.pos, DiagnosticCode.INVALID_LIST_CONSTRUCTOR, expType);
            return;
        }

        if (expTypeTag == TypeTags.JSON) {
            checkExprs(listConstructor.exprs, this.env, expType);
            actualType = expType;
        } else if (expTypeTag == TypeTags.ARRAY) {
            BArrayType arrayType = (BArrayType) expType;
            if (arrayType.state == BArrayState.OPEN_SEALED) {
                arrayType.size = listConstructor.exprs.size();
                arrayType.state = BArrayState.CLOSED_SEALED;
            } else if ((arrayType.state != BArrayState.UNSEALED) && (arrayType.size != listConstructor.exprs.size())) {
                if (arrayType.size < listConstructor.exprs.size()) {
                    dlog.error(listConstructor.pos,
                               DiagnosticCode.MISMATCHING_ARRAY_LITERAL_VALUES, arrayType.size,
                               listConstructor.exprs.size());
                    return;
                }
                if (!types.hasFillerValue(arrayType.eType)) {
                    dlog.error(listConstructor.pos, DiagnosticCode.INVALID_LIST_CONSTRUCTOR_ELEMENT_TYPE, expType);
                    return;
                }
            }
            checkExprs(listConstructor.exprs, this.env, arrayType.eType);
            actualType = arrayType;
        } else if (expTypeTag == TypeTags.UNION) {
            Set<BType> expTypes = ((BUnionType) expType).getMemberTypes();
            List<BType> matchedTypeList = expTypes.stream()
                    .filter(type -> type.tag == TypeTags.ARRAY || type.tag == TypeTags.TUPLE)
                    .collect(Collectors.toList());
            if (matchedTypeList.isEmpty()) {
                dlog.error(listConstructor.pos, DiagnosticCode.INCOMPATIBLE_TYPES, expType, actualType);
            } else if (matchedTypeList.size() == 1) {
                
                actualType = matchedTypeList.get(0);
                if (actualType.tag == TypeTags.ARRAY) {
                    checkExprs(listConstructor.exprs, this.env, ((BArrayType) actualType).eType);
                } else {
                    BTupleType tupleType = (BTupleType) actualType;
                    List<BType> results = new ArrayList<>();
                    BType restType = null;
                    for (int i = 0; i < listConstructor.exprs.size(); i++) {
                        BType expType, actType;
                        if (i < tupleType.tupleTypes.size()) {
                            expType = tupleType.tupleTypes.get(i);
                            actType = checkExpr(listConstructor.exprs.get(i), env, expType);
                            results.add(expType.tag != TypeTags.NONE ? expType : actType);
                        } else {
                            if (tupleType.restType != null) {
                                restType = checkExpr(listConstructor.exprs.get(i), env, tupleType.restType);
                            } else {
                                
                                dlog.error(listConstructor.pos, DiagnosticCode.SYNTAX_ERROR,
                                        "tuple and expression size does not match");
                                return;
                            }
                        }
                    }
                    actualType = new BTupleType(results);
                    ((BTupleType) actualType).restType = restType;
                }
            } else {
                
                
                actualType = checkArrayLiteralExpr(listConstructor);
            }
        } else if (expTypeTag == TypeTags.TYPEDESC) {
            
            List<BType> results = new ArrayList<>();
            listConstructor.isTypedescExpr = true;
            for (int i = 0; i < listConstructor.exprs.size(); i++) {
                results.add(checkExpr(listConstructor.exprs.get(i), env, symTable.noType));
            }
            List<BType> actualTypes = new ArrayList<>();
            for (int i = 0; i < listConstructor.exprs.size(); i++) {
                final BLangExpression expr = listConstructor.exprs.get(i);
                if (expr.getKind() == NodeKind.TYPEDESC_EXPRESSION) {
                    actualTypes.add(((BLangTypedescExpr) expr).resolvedType);
                } else if (expr.getKind() == NodeKind.SIMPLE_VARIABLE_REF) {
                    actualTypes.add(((BLangSimpleVarRef) expr).symbol.type);
                } else {
                    actualTypes.add(results.get(i));
                }
            }
            if (actualTypes.size() == 1) {
                listConstructor.typedescType = actualTypes.get(0);
            } else {
                listConstructor.typedescType = new BTupleType(actualTypes);
            }
            resultType = new BTypedescType(listConstructor.typedescType, null);
            return;
        } else if (expTypeTag == TypeTags.TUPLE) {
            BTupleType tupleType = (BTupleType) this.expType;
            if ((tupleType.restType != null && (tupleType.tupleTypes.size() > listConstructor.exprs.size()))
                    || (tupleType.restType == null && tupleType.tupleTypes.size() != listConstructor.exprs.size())) {
                dlog.error(listConstructor.pos, DiagnosticCode.SYNTAX_ERROR,
                        "tuple and expression size does not match");
                return;
            }
            List<BType> expTypes = tupleType.tupleTypes;
            List<BType> results = new ArrayList<>();
            BType restType = null;

            
            if (tupleType.restType != null && listConstructor.exprs.size() < expTypes.size() + 1) {
                restType = tupleType.restType;
            }

            for (int i = 0; i < listConstructor.exprs.size(); i++) {
                
                
                BType expType, actType;
                if (i < expTypes.size()) {
                    expType = expTypes.get(i);
                    actType = checkExpr(listConstructor.exprs.get(i), env, expType);
                    results.add(expType.tag != TypeTags.NONE ? expType : actType);
                } else {
                    restType = checkExpr(listConstructor.exprs.get(i), env, tupleType.restType);
                }
            }
            actualType = new BTupleType(results);
            ((BTupleType) actualType).restType = restType;
        } else if (listConstructor.exprs.size() > 1) {
            
            BArrayType arrayType = new BArrayType(getRepresentativeBroadType(listConstructor.exprs));
            checkExprs(listConstructor.exprs, this.env, arrayType.eType);
            actualType = arrayType;
        } else if (expTypeTag != TypeTags.SEMANTIC_ERROR) {
            actualType = checkArrayLiteralExpr(listConstructor);
        }
        resultType = types.checkType(listConstructor, actualType, expType);
    }