Skip to content

Commit

Permalink
Merge pull request #2 from Shadow-Devil/master
Browse files Browse the repository at this point in the history
  • Loading branch information
Shadow-Devil authored Oct 8, 2024
2 parents 1d42266 + f392e37 commit b2251b8
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ private static BIntersectionType setImmutableIntersectionType(Type type, Set<Typ
for (Map.Entry<String, Field> entry : originalFields.entrySet()) {
Field originalField = entry.getValue();
fields.put(entry.getKey(),
new BField(getImmutableType(originalField.getFieldType(), unresolvedTypes),
originalField.getFieldName(), originalField.getFlags()));
new BField(getImmutableType(originalField.getFieldType(), unresolvedTypes),
originalField.getFieldName(), originalField.getFlags() | SymbolFlags.READONLY));
}

BRecordType immutableRecordType = new BRecordType(
Expand Down
14 changes: 7 additions & 7 deletions bvm/ballerina-runtime/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module io.ballerina.runtime {
uses io.ballerina.runtime.api.launch.LaunchListener;
requires java.xml;
requires org.apache.commons.text;
requires axiom.api;
Expand Down Expand Up @@ -44,23 +45,22 @@
io.ballerina.lang.floatingpoint, io.ballerina.lang.internal, io.ballerina.lang.function,
io.ballerina.lang.regexp, io.ballerina.runtime.profiler;
exports io.ballerina.runtime.internal.commons to io.ballerina.lang.value;
exports io.ballerina.runtime.internal.launch to io.ballerina.testerina.runtime, io.ballerina.packerina,
ballerina.test.listener, io.ballerina.cli, org.ballerinalang.debugadapter.runtime;
exports io.ballerina.runtime.internal.scheduling to io.ballerina.cli.utils, io.ballerina.java,
exports io.ballerina.runtime.internal.launch to io.ballerina.testerina.runtime, ballerina.test.listener,
io.ballerina.cli, org.ballerinalang.debugadapter.runtime;
exports io.ballerina.runtime.internal.scheduling to io.ballerina.java,
io.ballerina.lang.array, io.ballerina.lang.error, io.ballerina.lang.internal, io.ballerina.lang.map,
io.ballerina.lang.table, io.ballerina.lang.transaction, io.ballerina.lang.value, io.ballerina.lang.xml,
io.ballerina.log.api, io.ballerina.testerina.core, io.ballerina.testerina.runtime, io.ballerina.shell,
io.ballerina.testerina.core, io.ballerina.testerina.runtime, io.ballerina.shell,
org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function, io.ballerina.runtime.profiler;
exports io.ballerina.runtime.internal.util to io.ballerina.testerina.runtime, io.ballerina.lang,
io.ballerina.lang.integer, io.ballerina.lang.floatingpoint, io.ballerina.lang.array,
io.ballerina.lang.table, io.ballerina.java, io.ballerina.lang.map, io.ballerina.lang.string,
io.ballerina.lang.xml, io.ballerina.lang.bool, io.ballerina.lang.error, io.ballerina.lang.internal,
io.ballerina.lang.value, io.ballerina.auth, io.ballerina.runtime.api, io.ballerina.cli.utils,
io.ballerina.cli;
io.ballerina.lang.value, io.ballerina.cli;
exports io.ballerina.runtime.internal.errors to io.ballerina.lang.value, io.ballerina.lang.integer,
io.ballerina.java, io.ballerina.lang.internal, io.ballerina.lang.array, io.ballerina.lang.bool,
io.ballerina.lang.floatingpoint, io.ballerina.lang.map, io.ballerina.lang.string, io.ballerina.lang.table,
io.ballerina.lang.xml, io.ballerina.testerina.core, io.ballerina.cli.utils, io.ballerina.cli,
io.ballerina.lang.xml, io.ballerina.testerina.core, io.ballerina.cli,
io.ballerina.lang.decimal, org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function,
io.ballerina.lang.regexp;
exports io.ballerina.runtime.internal.values to io.ballerina.testerina.core, io.ballerina.testerina.runtime,
Expand Down
3 changes: 3 additions & 0 deletions compiler/ballerina-lang/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
module io.ballerina.lang {
uses io.ballerina.projects.plugins.CompilerPlugin;
uses io.ballerina.projects.buildtools.CodeGeneratorTool;
uses org.ballerinalang.spi.CompilerBackendCodeGenerator;
uses org.ballerinalang.compiler.plugins.CompilerPlugin;
uses org.ballerinalang.spi.EmbeddedExecutor;
requires java.compiler;
requires com.google.gson;
requires java.xml;
Expand Down
2 changes: 1 addition & 1 deletion distribution/zip/jballerina-tools/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ tasks.register('pathingJar', Jar) {
doFirst {
manifest {
attributes "Class-Path": configurations.docerina.files.collect {
it.toURL().toString().replaceFirst("file:/", "/")
it.toURI().toString()
}.join(' ')
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
uses org.ballerinalang.langserver.eventsync.EventPublisher;
uses org.ballerinalang.langserver.commons.codeaction.spi.DiagnosticBasedCodeActionProvider;
uses org.ballerinalang.langserver.commons.codeaction.spi.RangeBasedCodeActionProvider;
uses org.ballerinalang.langserver.commons.completion.spi.BallerinaCompletionProvider;
exports org.ballerinalang.langserver;
exports org.ballerinalang.langserver.references;
exports org.ballerinalang.langserver.common.utils;
Expand All @@ -20,7 +21,7 @@
exports org.ballerinalang.langserver.extensions;
exports org.ballerinalang.langserver.config;
exports org.ballerinalang.langserver.telemetry;
exports org.ballerinalang.langserver.util to io.ballerina.language.server.simulator;
exports org.ballerinalang.langserver.util;
exports org.ballerinalang.langserver.codeaction to io.ballerina.datamapper;
requires io.ballerina.diagram.util;
requires io.ballerina.formatter.core;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class MappingConstructorExprTest {
private CompileResult inferRecordResult;
private CompileResult spreadOpFieldResult;
private CompileResult readOnlyFieldResult;
private CompileResult resultWithTupleUpdateMethod;
private CompileResult resultWithoutTupleUpdateMethod;

@BeforeClass
public void setup() {
Expand All @@ -47,6 +49,10 @@ public void setup() {
varNameFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/var_name_field.bal");
spreadOpFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/spread_op_field.bal");
readOnlyFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/readonly_field.bal");
resultWithTupleUpdateMethod =
BCompileUtil.compile("test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal");
resultWithoutTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/" +
"test_tuple_vs_array_readonly_violation_without_tuple_update_method.bal");
}

@Test(dataProvider = "mappingConstructorTests")
Expand Down Expand Up @@ -379,6 +385,16 @@ public void testReadOnlyFields(String test) {
BRunUtil.invoke(readOnlyFieldResult, test);
}

@Test
public void testReadOnlyFields2() {
BRunUtil.invoke(resultWithTupleUpdateMethod, "testFrozenAnyArrayElementUpdate");
}

@Test
public void testReadOnlyFields3() {
BRunUtil.invoke(resultWithoutTupleUpdateMethod, "testFrozenAnyArrayElementUpdate");
}

@DataProvider(name = "readOnlyFieldTests")
public Object[][] readOnlyFieldTests() {
return new Object[][] {
Expand Down Expand Up @@ -502,5 +518,7 @@ public void tearDown() {
inferRecordResult = null;
spreadOpFieldResult = null;
readOnlyFieldResult = null;
resultWithTupleUpdateMethod = null;
resultWithoutTupleUpdateMethod = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ public void testCreateRawDetails() {
}

@Test(expectedExceptions = BLangTestException.class,
expectedExceptionsMessageRegExp = ".*Invalid update of record field: modification not allowed on readonly " +
"value.*")
expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" +
"\"cannot update 'readonly' field 'name' in record of type 'Details & readonly'\".*")
public void testCreateDetails() {
BRunUtil.invoke(result, "testCreateDetails");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ function testRecordTypeAnnotationReadonlyValueEdit() {
assertEquality(true, res is error);

error resError = <error> res;
assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message());
assertEquality("Invalid update of record field: modification not allowed on readonly value",
assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message());
assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'",
resError.detail()["message"]);
}

Expand All @@ -73,8 +73,8 @@ function testAnnotationOnObjectTypeReadonlyValueEdit() {
assertEquality(true, res is error);

error resError = <error> res;
assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message());
assertEquality("Invalid update of record field: modification not allowed on readonly value",
assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message());
assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'",
resError.detail()["message"]);
}

Expand All @@ -97,8 +97,8 @@ function testAnnotationOnFunctionTypeReadonlyValueEdit() {
assertTrue(res is error);

error resError = <error> res;
assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message());
assertEquality("Invalid update of record field: modification not allowed on readonly value",
assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message());
assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'",
resError.detail()["message"]);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
//
// 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;

type Employee record {|
int id;
string name;
|};

function testFrozenAnyArrayElementUpdate() returns error? {
error? actualError = trap frozenAnyArrayElementUpdate();
test:assertTrue(actualError is error);
error e = <error>actualError;
test:assertEquals(e.message(), "{ballerina/lang.map}InherentTypeViolation");
test:assertEquals(e.detail()["message"],
"cannot update 'readonly' field 'name' in record of type '(Employee & readonly)'");
}

function frozenAnyArrayElementUpdate() returns error? {
Employee e1 = {name: "Em", id: 1000};
anydata[] i1 = [e1];
anydata[] i2 = i1.cloneReadOnly();
Employee e2 = check trap <Employee>i2[0];
e2["name"] = "Zee";
return ();
}

function frozenTupleUpdate() {
Employee e1 = {name: "Em", id: 1000};
[int, Employee] t1 = [1, e1];
[int, Employee] t2 = t1.cloneReadOnly();
Employee e2 = {name: "Zee", id: 1200};
t2[1] = e2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
//
// 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;

type Employee record {|
int id;
string name;
|};

function frozenAnyArrayElementUpdate() returns error? {
Employee e1 = {name: "Em", id: 1000};
anydata[] i1 = [e1];
anydata[] i2 = i1.cloneReadOnly();
Employee e2 = check trap <Employee>i2[0];
e2["name"] = "Zee";
return ();
}

function testFrozenAnyArrayElementUpdate() returns error? {
error? actualError = trap frozenAnyArrayElementUpdate();
test:assertTrue(actualError is error);
test:assertEquals((<error>actualError).message(), "{ballerina/lang.map}InherentTypeViolation");
test:assertEquals((<error>actualError).detail()["message"],
"cannot update 'readonly' field 'name' in record of type 'Employee & readonly'");
}

0 comments on commit b2251b8

Please sign in to comment.