From be6eb1e49f8256fd0bab49094b6c1f3b84764c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Buchowski?= Date: Fri, 13 Dec 2024 20:14:21 +0100 Subject: [PATCH 01/12] Fix sending same refreshToken as accessToken in open project request (#11862) In `open_project` request body we send `cognitoCredentials` for the project to be able to communicate with Cloud API. Currently the `refreshToken` has the same value as `accessToken` making that communication buggy. --- .prettierignore | 2 +- app/gui/src/dashboard/hooks/projectHooks.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.prettierignore b/.prettierignore index f84e714076b5..709537c7f4b2 100644 --- a/.prettierignore +++ b/.prettierignore @@ -11,7 +11,7 @@ build/build/release-body.md distribution/launcher/THIRD-PARTY distribution/engine/THIRD-PARTY distribution/project-manager/THIRD-PARTY -tools/legal-review +tools distribution/lib/Standard/*/*/manifest.yaml distribution/lib/Standard/*/*/polyglot distribution/lib/Standard/*/*/THIRD-PARTY diff --git a/app/gui/src/dashboard/hooks/projectHooks.ts b/app/gui/src/dashboard/hooks/projectHooks.ts index 8448adf02037..6f4fac4a1f9a 100644 --- a/app/gui/src/dashboard/hooks/projectHooks.ts +++ b/app/gui/src/dashboard/hooks/projectHooks.ts @@ -177,7 +177,7 @@ export function useOpenProjectMutation() { executeAsync: inBackground, cognitoCredentials: { accessToken: session.accessToken, - refreshToken: session.accessToken, + refreshToken: session.refreshToken, clientId: session.clientId, expireAt: session.expireAt, refreshUrl: session.refreshUrl, From e6bcd5e485a82abe9b0fd5364c8a1b98c926171f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Wa=C5=9Bko?= Date: Fri, 13 Dec 2024 20:28:03 +0100 Subject: [PATCH 02/12] `aggregate ..Sum` of integer column remains integer and handles overflow (#11860) - This was mentioned in #7192 but didn't get a proper ticket. - Ensuring that summing integers gives an integer and not a float. - Only in-memory, as in Database the result type is database-dependent and we want it to be like that. - Also allowing the integer sum to overflow and become a `BigInteger`, in that case the resulting column will become `Decimal`. --- .../enso/table/aggregations/Aggregator.java | 16 +- .../enso/table/aggregations/Concatenate.java | 2 +- .../org/enso/table/aggregations/Count.java | 2 +- .../table/aggregations/CountDistinct.java | 2 +- .../enso/table/aggregations/CountEmpty.java | 2 +- .../enso/table/aggregations/CountNothing.java | 2 +- .../org/enso/table/aggregations/First.java | 2 +- .../org/enso/table/aggregations/GroupBy.java | 2 +- .../aggregations/KnownTypeAggregator.java | 32 +++ .../org/enso/table/aggregations/Last.java | 2 +- .../org/enso/table/aggregations/Mean.java | 156 +++++++++++--- .../org/enso/table/aggregations/MinOrMax.java | 2 +- .../org/enso/table/aggregations/Mode.java | 2 +- .../enso/table/aggregations/Percentile.java | 2 +- .../table/aggregations/ShortestOrLongest.java | 2 +- .../table/aggregations/StandardDeviation.java | 2 +- .../java/org/enso/table/aggregations/Sum.java | 200 +++++++++++++++--- .../builder/InferredIntegerBuilder.java | 2 - .../enso/table/data/index/CrossTabIndex.java | 3 +- .../table/data/index/MultiValueIndex.java | 2 +- test/Base_Tests/src/Data/Statistics_Spec.enso | 10 +- .../Aggregate_Spec.enso | 89 +++++++- .../Table_Tests/src/In_Memory/Table_Spec.enso | 2 +- 23 files changed, 445 insertions(+), 93 deletions(-) create mode 100644 std-bits/table/src/main/java/org/enso/table/aggregations/KnownTypeAggregator.java diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Aggregator.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Aggregator.java index 077315040085..19b981a178a6 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Aggregator.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Aggregator.java @@ -1,17 +1,15 @@ package org.enso.table.aggregations; import java.util.List; -import org.enso.table.data.column.storage.type.StorageType; +import org.enso.table.data.column.builder.Builder; import org.enso.table.problems.ProblemAggregator; /** Interface used to define aggregate columns. */ public abstract class Aggregator { private final String name; - private final StorageType type; - protected Aggregator(String name, StorageType type) { + protected Aggregator(String name) { this.name = name; - this.type = type; } /** @@ -23,14 +21,8 @@ public final String getName() { return name; } - /** - * Return type of the column - * - * @return The type of the new column. - */ - public StorageType getType() { - return type; - } + /** Creates a builder that can hold results of this aggregator. */ + public abstract Builder makeBuilder(int size, ProblemAggregator problemAggregator); /** * Compute the value for a set of rows diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Concatenate.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Concatenate.java index 2a8bd0c50df3..4bf3e917946e 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Concatenate.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Concatenate.java @@ -10,7 +10,7 @@ import org.enso.table.problems.ProblemAggregator; import org.graalvm.polyglot.Context; -public class Concatenate extends Aggregator { +public class Concatenate extends KnownTypeAggregator { private final Storage storage; private final String separator; private final String prefix; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Count.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Count.java index d12d44babf01..84122d53392d 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Count.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Count.java @@ -5,7 +5,7 @@ import org.enso.table.problems.ProblemAggregator; /** Aggregate Column counting the number of entries in a group. */ -public class Count extends Aggregator { +public class Count extends KnownTypeAggregator { public Count(String name) { super(name, IntegerType.INT_64); } diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/CountDistinct.java b/std-bits/table/src/main/java/org/enso/table/aggregations/CountDistinct.java index ec7672e7410d..606c96dee1c6 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/CountDistinct.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/CountDistinct.java @@ -18,7 +18,7 @@ * Aggregate Column counting the number of distinct items in a group. If `ignoreAllNull` is true, * does count when all items are null. */ -public class CountDistinct extends Aggregator { +public class CountDistinct extends KnownTypeAggregator { private final Storage[] storage; private final List textFoldingStrategy; private final boolean ignoreAllNull; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/CountEmpty.java b/std-bits/table/src/main/java/org/enso/table/aggregations/CountEmpty.java index 735d5398f4f6..3d23f5ed7147 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/CountEmpty.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/CountEmpty.java @@ -13,7 +13,7 @@ * Aggregate Column counting the number of (non-)empty entries in a group. If `isEmpty` is true, * counts null or empty entries. If `isEmpty` is false, counts non-empty entries. */ -public class CountEmpty extends Aggregator { +public class CountEmpty extends KnownTypeAggregator { private final Storage storage; private final boolean isEmpty; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/CountNothing.java b/std-bits/table/src/main/java/org/enso/table/aggregations/CountNothing.java index d0510b5b99a4..f9c711fd84a2 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/CountNothing.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/CountNothing.java @@ -11,7 +11,7 @@ * Aggregate Column counting the number of (not-)null entries in a group. If `isNothing` is true, * counts null entries. If `isNothing` is false, counts non-null entries. */ -public class CountNothing extends Aggregator { +public class CountNothing extends KnownTypeAggregator { private final Storage storage; private final boolean isNothing; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/First.java b/std-bits/table/src/main/java/org/enso/table/aggregations/First.java index b6b138751d90..b87f498e48b2 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/First.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/First.java @@ -9,7 +9,7 @@ import org.graalvm.polyglot.Context; /** Aggregate Column finding the first value in a group. */ -public class First extends Aggregator { +public class First extends KnownTypeAggregator { private final Storage storage; private final Storage[] orderByColumns; private final int[] orderByDirections; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/GroupBy.java b/std-bits/table/src/main/java/org/enso/table/aggregations/GroupBy.java index 0d79d6207b75..6377f6f94f10 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/GroupBy.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/GroupBy.java @@ -6,7 +6,7 @@ import org.enso.table.problems.ProblemAggregator; /** Aggregate Column getting the grouping key. */ -public class GroupBy extends Aggregator { +public class GroupBy extends KnownTypeAggregator { private final Storage storage; public GroupBy(String name, Column column) { diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/KnownTypeAggregator.java b/std-bits/table/src/main/java/org/enso/table/aggregations/KnownTypeAggregator.java new file mode 100644 index 000000000000..1b415a67c5cf --- /dev/null +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/KnownTypeAggregator.java @@ -0,0 +1,32 @@ +package org.enso.table.aggregations; + +import org.enso.table.data.column.builder.Builder; +import org.enso.table.data.column.storage.type.StorageType; +import org.enso.table.problems.ProblemAggregator; + +/** + * A common subclass for aggregators that know their type on construction and use a standard + * builder. + */ +public abstract class KnownTypeAggregator extends Aggregator { + private final StorageType type; + + protected KnownTypeAggregator(String name, StorageType type) { + super(name); + this.type = type; + } + + @Override + public Builder makeBuilder(int size, ProblemAggregator problemAggregator) { + return Builder.getForType(type, size, problemAggregator); + } + + /** + * Return type of the column + * + * @return The type of the new column. + */ + public StorageType getType() { + return type; + } +} diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Last.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Last.java index a522a1da707b..a69d99031043 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Last.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Last.java @@ -8,7 +8,7 @@ import org.enso.table.problems.ProblemAggregator; import org.graalvm.polyglot.Context; -public class Last extends Aggregator { +public class Last extends KnownTypeAggregator { private final Storage storage; private final Storage[] orderByColumns; private final int[] orderByDirections; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Mean.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Mean.java index aecfadef301f..e5cea57fcca5 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Mean.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Mean.java @@ -1,9 +1,18 @@ package org.enso.table.aggregations; +import java.math.BigDecimal; +import java.math.MathContext; import java.util.List; import org.enso.base.polyglot.NumericConverter; import org.enso.table.data.column.storage.Storage; +import org.enso.table.data.column.storage.numeric.AbstractLongStorage; +import org.enso.table.data.column.storage.numeric.DoubleStorage; +import org.enso.table.data.column.storage.type.AnyObjectType; +import org.enso.table.data.column.storage.type.BigDecimalType; +import org.enso.table.data.column.storage.type.BigIntegerType; import org.enso.table.data.column.storage.type.FloatType; +import org.enso.table.data.column.storage.type.IntegerType; +import org.enso.table.data.column.storage.type.StorageType; import org.enso.table.data.table.Column; import org.enso.table.data.table.problems.InvalidAggregation; import org.enso.table.problems.ColumnAggregatedProblemAggregator; @@ -11,50 +20,139 @@ import org.graalvm.polyglot.Context; /** Aggregate Column computing the mean value in a group. */ -public class Mean extends Aggregator { - private static class Calculation { - public long count; - public double total; - - public Calculation(double value) { - count = 1; - total = value; - } - } - +public class Mean extends KnownTypeAggregator { private final Storage storage; + private final String columnName; public Mean(String name, Column column) { - super(name, FloatType.FLOAT_64); + super(name, resultTypeFromInput(column.getStorage())); this.storage = column.getStorage(); + this.columnName = column.getName(); + } + + private static StorageType resultTypeFromInput(Storage inputStorage) { + StorageType inputType = inputStorage.getType(); + if (inputType instanceof AnyObjectType) { + inputType = inputStorage.inferPreciseType(); + } + + return switch (inputType) { + case FloatType floatType -> FloatType.FLOAT_64; + case IntegerType integerType -> FloatType.FLOAT_64; + case BigIntegerType bigIntegerType -> BigDecimalType.INSTANCE; + case BigDecimalType bigDecimalType -> BigDecimalType.INSTANCE; + default -> throw new IllegalStateException( + "Unexpected input type for Mean aggregate: " + inputType); + }; } @Override public Object aggregate(List indexes, ProblemAggregator problemAggregator) { ColumnAggregatedProblemAggregator innerAggregator = new ColumnAggregatedProblemAggregator(problemAggregator); - Context context = Context.getCurrent(); - Calculation current = null; - for (int row : indexes) { - Object value = storage.getItemBoxed(row); - if (value != null) { - Double dValue = NumericConverter.tryConvertingToDouble(value); - if (dValue == null) { - innerAggregator.reportColumnAggregatedProblem( - new InvalidAggregation(this.getName(), row, "Cannot convert to a number.")); - return null; + MeanAccumulator accumulator = makeAccumulator(); + accumulator.accumulate(indexes, storage, innerAggregator); + return accumulator.summarize(); + } + + private MeanAccumulator makeAccumulator() { + return switch (getType()) { + case FloatType floatType -> new FloatMeanAccumulator(); + case BigDecimalType bigDecimalType -> new BigDecimalMeanAccumulator(); + default -> throw new IllegalStateException( + "Unexpected output type in Mean aggregate: " + getType()); + }; + } + + private abstract static class MeanAccumulator { + abstract void accumulate( + List indexes, Storage storage, ProblemAggregator problemAggregator); + + abstract Object summarize(); + } + + private final class FloatMeanAccumulator extends MeanAccumulator { + private double total = 0; + private long count = 0; + + @Override + void accumulate( + List indexes, Storage storage, ProblemAggregator problemAggregator) { + Context context = Context.getCurrent(); + if (storage instanceof DoubleStorage doubleStorage) { + for (int i : indexes) { + if (!doubleStorage.isNothing(i)) { + total += doubleStorage.getItemAsDouble(i); + count++; + } + context.safepoint(); + } + } else if (storage instanceof AbstractLongStorage longStorage) { + for (int i : indexes) { + if (!longStorage.isNothing(i)) { + total += longStorage.getItem(i); + count++; + } + context.safepoint(); } + } else { + ColumnAggregatedProblemAggregator innerAggregator = + new ColumnAggregatedProblemAggregator(problemAggregator); + for (int i : indexes) { + Object value = storage.getItemBoxed(i); + if (value != null) { + Double dValue = NumericConverter.tryConvertingToDouble(value); + if (dValue == null) { + innerAggregator.reportColumnAggregatedProblem( + new InvalidAggregation(columnName, i, "Cannot convert to a Float.")); + continue; + } + + total += dValue; + count++; + } + context.safepoint(); + } + } + } + + @Override + Object summarize() { + return count == 0 ? null : total / count; + } + } + + private final class BigDecimalMeanAccumulator extends MeanAccumulator { + private BigDecimal total = BigDecimal.ZERO; + private long count = 0; - if (current == null) { - current = new Calculation(dValue); - } else { - current.count++; - current.total += dValue; + @Override + void accumulate( + List indexes, Storage storage, ProblemAggregator problemAggregator) { + ColumnAggregatedProblemAggregator innerAggregator = + new ColumnAggregatedProblemAggregator(problemAggregator); + Context context = Context.getCurrent(); + for (int i : indexes) { + Object value = storage.getItemBoxed(i); + if (value != null) { + try { + BigDecimal valueAsBigDecimal = NumericConverter.coerceToBigDecimal(value); + total = total.add(valueAsBigDecimal); + count++; + } catch (UnsupportedOperationException error) { + innerAggregator.reportColumnAggregatedProblem( + new InvalidAggregation( + columnName, i, "Cannot convert to a BigDecimal: " + error.getMessage())); + continue; + } } + context.safepoint(); } + } - context.safepoint(); + @Override + Object summarize() { + return count == 0 ? null : total.divide(BigDecimal.valueOf(count), MathContext.DECIMAL128); } - return current == null ? null : current.total / current.count; } } diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/MinOrMax.java b/std-bits/table/src/main/java/org/enso/table/aggregations/MinOrMax.java index cbc4dd565cbb..4f3aa776bcda 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/MinOrMax.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/MinOrMax.java @@ -13,7 +13,7 @@ /** * Aggregate Column finding the minimum (minOrMax = -1) or maximum (minOrMax = 1) entry in a group. */ -public class MinOrMax extends Aggregator { +public class MinOrMax extends KnownTypeAggregator { public static final int MIN = -1; public static final int MAX = 1; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Mode.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Mode.java index 55961865a0f1..1e09d8762245 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Mode.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Mode.java @@ -12,7 +12,7 @@ import org.graalvm.polyglot.Context; /** Aggregate Column computing the most common value in a group (ignoring Nothing). */ -public class Mode extends Aggregator { +public class Mode extends KnownTypeAggregator { private final Storage storage; public Mode(String name, Column column) { diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Percentile.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Percentile.java index 3f6b5ab6683b..9b25f45e6596 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Percentile.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Percentile.java @@ -14,7 +14,7 @@ import org.graalvm.polyglot.Context; /** Aggregate Column computing a percentile value in a group. */ -public class Percentile extends Aggregator { +public class Percentile extends KnownTypeAggregator { private final Storage storage; private final double percentile; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/ShortestOrLongest.java b/std-bits/table/src/main/java/org/enso/table/aggregations/ShortestOrLongest.java index 08d3052b0d59..833e2c5d0814 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/ShortestOrLongest.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/ShortestOrLongest.java @@ -11,7 +11,7 @@ import org.graalvm.polyglot.Context; /** Aggregate Column finding the longest or shortest string in a group. */ -public class ShortestOrLongest extends Aggregator { +public class ShortestOrLongest extends KnownTypeAggregator { public static final int SHORTEST = -1; public static final int LONGEST = 1; private final Storage storage; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/StandardDeviation.java b/std-bits/table/src/main/java/org/enso/table/aggregations/StandardDeviation.java index 52fec69d897f..197c54312ef0 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/StandardDeviation.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/StandardDeviation.java @@ -11,7 +11,7 @@ import org.graalvm.polyglot.Context; /** Aggregate Column computing the standard deviation of a group. */ -public class StandardDeviation extends Aggregator { +public class StandardDeviation extends KnownTypeAggregator { private static class Calculation { public long count; public double total; diff --git a/std-bits/table/src/main/java/org/enso/table/aggregations/Sum.java b/std-bits/table/src/main/java/org/enso/table/aggregations/Sum.java index 2dc342e52273..116d75ec1cc8 100644 --- a/std-bits/table/src/main/java/org/enso/table/aggregations/Sum.java +++ b/std-bits/table/src/main/java/org/enso/table/aggregations/Sum.java @@ -1,62 +1,202 @@ package org.enso.table.aggregations; +import java.math.BigInteger; import java.util.List; import org.enso.base.polyglot.NumericConverter; +import org.enso.table.data.column.builder.BigIntegerBuilder; +import org.enso.table.data.column.builder.Builder; +import org.enso.table.data.column.builder.DoubleBuilder; +import org.enso.table.data.column.builder.InferredIntegerBuilder; import org.enso.table.data.column.operation.map.MapOperationProblemAggregator; import org.enso.table.data.column.storage.Storage; +import org.enso.table.data.column.storage.numeric.AbstractLongStorage; +import org.enso.table.data.column.storage.numeric.BigIntegerStorage; +import org.enso.table.data.column.storage.numeric.DoubleStorage; +import org.enso.table.data.column.storage.type.BigIntegerType; import org.enso.table.data.column.storage.type.FloatType; import org.enso.table.data.column.storage.type.IntegerType; +import org.enso.table.data.column.storage.type.StorageType; import org.enso.table.data.table.Column; -import org.enso.table.data.table.problems.InvalidAggregation; import org.enso.table.problems.ProblemAggregator; import org.graalvm.polyglot.Context; /** Aggregate Column computing the total value in a group. */ public class Sum extends Aggregator { - private final Storage storage; + private final Storage inputStorage; + private final StorageType inputType; public Sum(String name, Column column) { - super(name, FloatType.FLOAT_64); - this.storage = column.getStorage(); + super(name); + this.inputStorage = column.getStorage(); + inputType = inputStorage.inferPreciseType(); + } + + @Override + public Builder makeBuilder(int size, ProblemAggregator problemAggregator) { + return switch (inputType) { + case IntegerType integerType -> new InferredIntegerBuilder(size, problemAggregator); + case BigIntegerType bigIntegerType -> new BigIntegerBuilder(size, problemAggregator); + case FloatType floatType -> DoubleBuilder.createDoubleBuilder(size, problemAggregator); + default -> throw new IllegalStateException( + "Unexpected input type for Sum aggregate: " + inputType); + }; } @Override public Object aggregate(List indexes, ProblemAggregator problemAggregator) { MapOperationProblemAggregator innerAggregator = new MapOperationProblemAggregator(problemAggregator, getName()); - Context context = Context.getCurrent(); - Object current = null; - for (int row : indexes) { - Object value = storage.getItemBoxed(row); - if (value != null) { - if (current == null) { - current = 0L; - } - - Long lCurrent = NumericConverter.tryConvertingToLong(current); - Long lValue = NumericConverter.tryConvertingToLong(value); - if (lCurrent != null && lValue != null) { + SumAccumulator accumulator = makeAccumulator(); + accumulator.accumulate(indexes, inputStorage); + return accumulator.summarize(); + } + + private SumAccumulator makeAccumulator() { + return switch (inputType) { + case IntegerType integerType -> new IntegerSumAccumulator(); + case BigIntegerType bigIntegerType -> new IntegerSumAccumulator(); + case FloatType floatType -> new FloatSumAccumulator(); + default -> throw new IllegalStateException( + "Unexpected input type for Sum aggregate: " + inputType); + }; + } + + private abstract static class SumAccumulator { + abstract void accumulate(List indexes, Storage storage); + + abstract Object summarize(); + } + + private static final class IntegerSumAccumulator extends SumAccumulator { + private Object accumulator = null; + + void add(Object value) { + if (value == null) { + return; + } + + Long valueAsLong = NumericConverter.tryConvertingToLong(value); + if (valueAsLong != null) { + addLong(valueAsLong); + } else if (value instanceof BigInteger) { + addBigInteger((BigInteger) value); + } else { + throw new IllegalStateException("Unexpected value type: " + value.getClass()); + } + } + + @Override + void accumulate(List indexes, Storage storage) { + Context context = Context.getCurrent(); + if (storage instanceof AbstractLongStorage longStorage) { + for (int row : indexes) { + if (!longStorage.isNothing(row)) { + addLong(longStorage.getItem(row)); + } + context.safepoint(); + } + } else if (storage instanceof BigIntegerStorage bigIntegerStorage) { + for (int row : indexes) { + BigInteger value = bigIntegerStorage.getItem(row); + if (value != null) { + addBigInteger(value); + } + context.safepoint(); + } + } else { + for (int row : indexes) { + add(storage.getItemBoxed(row)); + context.safepoint(); + } + } + } + + private void addLong(long value) { + switch (accumulator) { + case Long accumulatorAsLong -> { try { - current = Math.addExact(lCurrent, lValue); + accumulator = Math.addExact(accumulatorAsLong, value); } catch (ArithmeticException exception) { - innerAggregator.reportOverflow(IntegerType.INT_64, "Sum"); - return null; + accumulator = BigInteger.valueOf(accumulatorAsLong).add(BigInteger.valueOf(value)); } - } else { - Double dCurrent = NumericConverter.tryConvertingToDouble(current); - Double dValue = NumericConverter.tryConvertingToDouble(value); - if (dCurrent != null && dValue != null) { - current = dCurrent + dValue; - } else { - innerAggregator.reportColumnAggregatedProblem( - new InvalidAggregation(this.getName(), row, "Cannot convert to a number.")); - return null; + } + case BigInteger accumulatorAsBigInteger -> { + accumulator = accumulatorAsBigInteger.add(BigInteger.valueOf(value)); + } + case null -> { + accumulator = value; + } + default -> throw new IllegalStateException( + "Unexpected accumulator type: " + accumulator.getClass()); + } + } + + private void addBigInteger(BigInteger value) { + assert value != null; + switch (accumulator) { + case Long accumulatorAsLong -> { + accumulator = BigInteger.valueOf(accumulatorAsLong).add(value); + } + case BigInteger accumulatorAsBigInteger -> { + accumulator = accumulatorAsBigInteger.add(value); + } + case null -> { + accumulator = value; + } + default -> throw new IllegalStateException( + "Unexpected accumulator type: " + accumulator.getClass()); + } + } + + Object summarize() { + return accumulator; + } + } + + private static final class FloatSumAccumulator extends SumAccumulator { + private Double accumulator = null; + + void add(Object value) { + if (value == null) { + return; + } + + Double valueAsDouble = NumericConverter.tryConvertingToDouble(value); + if (valueAsDouble != null) { + addDouble(valueAsDouble); + } else { + throw new IllegalStateException("Unexpected value type: " + value.getClass()); + } + } + + @Override + void accumulate(List indexes, Storage storage) { + Context context = Context.getCurrent(); + if (storage instanceof DoubleStorage doubleStorage) { + for (int row : indexes) { + if (!doubleStorage.isNothing(row)) { + addDouble(doubleStorage.getItem(row)); } + context.safepoint(); + } + } else { + for (int row : indexes) { + add(storage.getItemBoxed(row)); + context.safepoint(); } } + } + + private void addDouble(double value) { + if (accumulator == null) { + accumulator = value; + } else { + accumulator += value; + } + } - context.safepoint(); + Double summarize() { + return accumulator; } - return current; } } diff --git a/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredIntegerBuilder.java b/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredIntegerBuilder.java index f89a6bf38975..5ec3d1e3c8f7 100644 --- a/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredIntegerBuilder.java +++ b/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredIntegerBuilder.java @@ -19,12 +19,10 @@ public class InferredIntegerBuilder extends Builder { private TypedBuilder bigIntegerBuilder = null; private int currentSize = 0; private final int initialSize; - private final ProblemAggregator problemAggregator; /** Creates a new instance of this builder, with the given known result length. */ public InferredIntegerBuilder(int initialSize, ProblemAggregator problemAggregator) { this.initialSize = initialSize; - this.problemAggregator = problemAggregator; longBuilder = NumericBuilder.createLongBuilder(this.initialSize, IntegerType.INT_64, problemAggregator); diff --git a/std-bits/table/src/main/java/org/enso/table/data/index/CrossTabIndex.java b/std-bits/table/src/main/java/org/enso/table/data/index/CrossTabIndex.java index 68234a58c2c8..2cb43bf564d9 100644 --- a/std-bits/table/src/main/java/org/enso/table/data/index/CrossTabIndex.java +++ b/std-bits/table/src/main/java/org/enso/table/data/index/CrossTabIndex.java @@ -140,8 +140,7 @@ public Table makeCrossTabTable(Aggregator[] aggregates, String[] aggregateNames) for (int i = 0; i < xKeysCount(); i++) { int offset = yColumns.length + i * aggregates.length; for (int j = 0; j < aggregates.length; j++) { - storage[offset + j] = - Builder.getForType(aggregates[j].getType(), yKeysCount(), problemAggregator); + storage[offset + j] = aggregates[j].makeBuilder(yKeysCount(), problemAggregator); context.safepoint(); } } diff --git a/std-bits/table/src/main/java/org/enso/table/data/index/MultiValueIndex.java b/std-bits/table/src/main/java/org/enso/table/data/index/MultiValueIndex.java index 827726cdab5e..d3ffe3d79ac2 100644 --- a/std-bits/table/src/main/java/org/enso/table/data/index/MultiValueIndex.java +++ b/std-bits/table/src/main/java/org/enso/table/data/index/MultiValueIndex.java @@ -115,7 +115,7 @@ public Table makeTable(Aggregator[] columns) { boolean emptyScenario = size == 0 && keyColumns.length == 0; Builder[] storage = Arrays.stream(columns) - .map(c -> Builder.getForType(c.getType(), emptyScenario ? 1 : size, problemAggregator)) + .map(c -> c.makeBuilder(emptyScenario ? 1 : size, problemAggregator)) .toArray(Builder[]::new); if (emptyScenario) { diff --git a/test/Base_Tests/src/Data/Statistics_Spec.enso b/test/Base_Tests/src/Data/Statistics_Spec.enso index fd47e90a4691..781c698cecdd 100644 --- a/test/Base_Tests/src/Data/Statistics_Spec.enso +++ b/test/Base_Tests/src/Data/Statistics_Spec.enso @@ -83,11 +83,18 @@ add_specs suite_builder = text_set.compute Statistic.Maximum . should_equal "D" group_builder.specify "should be able to get sum of values" <| - simple_set.compute Statistic.Sum . should_equal 15 epsilon=double_error + int_sum = simple_set.compute Statistic.Sum + int_sum.should_equal 15 + int_sum.should_be_a Integer number_set.compute Statistic.Sum . should_equal -101.28 epsilon=double_error missing_set.compute Statistic.Sum . should_equal -81.8 epsilon=double_error with_nans_set.compute Statistic.Sum . should_equal -81.8 epsilon=double_error + group_builder.specify "should be able to get a sum of big integer values" <| + r1 = [2^62, 2^62, 2^62, 2^62, 2^62].compute ..Sum + r1.should_equal (5 * 2^62) + r1.should_be_a Integer + group_builder.specify "should be able to get product of values" <| simple_set.compute Statistic.Product . should_equal 120 epsilon=double_error number_set.compute Statistic.Product . should_equal -5.311643150197863*(10^22) epsilon=double_error @@ -371,4 +378,3 @@ main filter=Nothing = suite = Test.build suite_builder-> add_specs suite_builder suite.run_with_filter filter - diff --git a/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso b/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso index af05b092afeb..9dca091a8e6e 100644 --- a/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso +++ b/test/Table_Tests/src/Common_Table_Operations/Aggregate_Spec.enso @@ -1,7 +1,7 @@ from Standard.Base import all import Standard.Base.Errors.Common.Floating_Point_Equality -from Standard.Table import Table, Sort_Column, expr +from Standard.Table import Table, Sort_Column, Value_Type, expr from Standard.Table.Aggregate_Column.Aggregate_Column import all import Standard.Table.Expression.Expression_Error from Standard.Table.Errors import all @@ -934,6 +934,93 @@ add_aggregate_specs suite_builder setup = materialized.columns.at 1 . name . should_equal "Shortest B" materialized.columns.at 1 . to_vector . should_equal ["f"] + suite_builder.group prefix+"Table.aggregate Sum" group_builder-> + # The types of aggregates are only tested in-memory, in DB they will depend on each backend + if setup.is_database.not then group_builder.specify "should return an Integer column when summing an Integer input" <| + table = table_builder [["int_column", [1, 2, 3, 4, 5, 6, 7]]] + table.at "int_column" . value_type . should_equal Value_Type.Integer + + result = table.aggregate [] [Sum "int_column"] + within_table result <| + result.row_count . should_equal 1 + materialized = materialize result + Problems.assume_no_problems materialized + materialized.column_count . should_equal 1 + materialized.columns.at 0 . name . should_equal "Sum int_column" + materialized.columns.at 0 . to_vector . should_equal [28] + materialized.columns.at 0 . value_type . should_equal Value_Type.Integer + + table2 = table_builder [["int_column", [31000, 31000, 31000, 31000, 31000]]] + . cast "int_column" (Value_Type.Integer ..Bits_16) + table2.at "int_column" . value_type . should_equal (Value_Type.Integer ..Bits_16) + + result2 = table2.aggregate [] [Sum "int_column"] + within_table result2 <| + result2.row_count . should_equal 1 + materialized2 = materialize result2 + Problems.assume_no_problems materialized2 + materialized2.column_count . should_equal 1 + materialized2.columns.at 0 . name . should_equal "Sum int_column" + materialized2.columns.at 0 . to_vector . should_equal [5*31000] + materialized2.columns.at 0 . value_type . should_be_a (Value_Type.Integer ...) + + if setup.is_database.not then group_builder.specify "should return a Decimal column when the sum overflows 64-bit Integers" <| + table = table_builder [["int_column", [2^62, 2^62, 2^62, 2^62, 2^62, 2^62, 2^62, 1, 2, 4]], ["group", ["big", "big", "big", "big", "big", "big", "big", "small", "small", "small"]]] + table.at "int_column" . value_type . should_equal Value_Type.Integer + + result = table.aggregate [] [Sum "int_column"] + within_table result <| + result.row_count . should_equal 1 + materialized = materialize result + Problems.assume_no_problems materialized + materialized.column_count . should_equal 1 + materialized.columns.at 0 . name . should_equal "Sum int_column" + materialized.columns.at 0 . to_vector . should_equal [((2^62) * 7) + 7] + materialized.columns.at 0 . value_type . should_be_a (Value_Type.Decimal ...) + + result2 = table.aggregate ["group"] [Sum "int_column"] . sort "group" + within_table result2 <| + result2.row_count . should_equal 2 + materialized2 = materialize result2 + Problems.assume_no_problems materialized2 + materialized2.column_count . should_equal 2 + materialized2.columns.at 0 . name . should_equal "group" + materialized2.columns.at 0 . to_vector . should_equal ["big", "small"] + materialized2.columns.at 1 . name . should_equal "Sum int_column" + materialized2.columns.at 1 . to_vector . should_equal [(2^62) * 7, 7] + materialized2.columns.at 1 . value_type . should_be_a (Value_Type.Decimal ...) + + if setup.is_database.not then group_builder.specify "should allow to sum big-integer column" <| + table = table_builder [["big_column", [2^100, 2^70]]] + table.at "big_column" . value_type . should_be_a (Value_Type.Decimal ...) + result = table.aggregate [] [Sum "big_column"] + within_table result <| + result.row_count . should_equal 1 + materialized = materialize result + Problems.assume_no_problems materialized + materialized.column_count . should_equal 1 + materialized.columns.at 0 . name . should_equal "Sum big_column" + materialized.columns.at 0 . to_vector . should_equal [2^100 + 2^70] + materialized.columns.at 0 . value_type . should_be_a (Value_Type.Decimal ...) + + suite_builder.group prefix+"Table.aggregate Average" group_builder-> + # The types of aggregates are only tested in-memory, in DB they will depend on each backend + if setup.is_database.not then group_builder.specify "should return a Decimal column when input is Decimal" <| + table = table_builder [["X", [2^62, 2^62, 2^62, 2^62]]] + . cast "X" (Value_Type.Decimal scale=0) + table.at "X" . value_type . should_be_a (Value_Type.Decimal ...) + result = table.aggregate [] [Average "X"] + within_table result <| + result.row_count . should_equal 1 + materialized = materialize result + Problems.assume_no_problems materialized + materialized.column_count . should_equal 1 + materialized.columns.at 0 . name . should_equal "Average X" + materialized.columns.at 0 . to_vector . should_equal [2^62] + materialized.columns.at 0 . value_type . should_be_a (Value_Type.Decimal ...) + + # Map to text to ensure that the equality is _exact_ and does not rely on Float rounding + materialized.columns.at 0 . to_vector . map .to_text . should_equal [(2^62).to_text] # Special case for Snowflake until the https://github.com/enso-org/enso/issues/10412 ticket is resolved. if setup.prefix.contains "Snowflake" then diff --git a/test/Table_Tests/src/In_Memory/Table_Spec.enso b/test/Table_Tests/src/In_Memory/Table_Spec.enso index 505257ce1e10..f3eb5a657f5a 100644 --- a/test/Table_Tests/src/In_Memory/Table_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Table_Spec.enso @@ -764,7 +764,7 @@ add_specs suite_builder = t4 = table.aggregate ["mixed"] [Aggregate_Column.Sum "ints", Aggregate_Column.Sum "floats"] t4.column_info.at "Column" . to_vector . should_equal ["mixed", "Sum ints", "Sum floats"] - t4.column_info.at "Value Type" . to_vector . should_equal [Value_Type.Mixed, Value_Type.Float, Value_Type.Float] + t4.column_info.at "Value Type" . to_vector . should_equal [Value_Type.Mixed, Value_Type.Integer, Value_Type.Float] group_builder.specify "should take Unicode normalization into account when grouping by Text" <| texts = ["texts", ['ściana', 'ściana', 'łąka', 's\u0301ciana', 'ła\u0328ka', 'sciana']] From 63ed62921012f57b7a5cf169351e8872c2fde59a Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Fri, 13 Dec 2024 21:01:16 +0000 Subject: [PATCH 03/12] Excel Reading (XLSX) using SAX Default Handler (#10877) - Implement Excel reading as a SAXMLParser. --- .../0.0.0-dev/src/Excel/Excel_Workbook.enso | 12 +- .../enso/table/excel/ExcelConnectionPool.java | 18 +- .../org/enso/table/excel/ExcelFileFormat.java | 3 +- .../org/enso/table/excel/ExcelHeaders.java | 2 +- .../java/org/enso/table/excel/ExcelRange.java | 12 +- .../java/org/enso/table/excel/ExcelRow.java | 300 ++++++++++-------- .../java/org/enso/table/excel/ExcelSheet.java | 94 ++++-- .../java/org/enso/table/excel/ExcelUtils.java | 6 +- .../org/enso/table/excel/ExcelWorkbook.java | 123 +++++++ .../table/excel/ReadOnlyExcelConnection.java | 3 +- .../excel/xssfreader/XSSFReaderFormats.java | 29 ++ .../table/excel/xssfreader/XSSFReaderRow.java | 125 ++++++++ .../excel/xssfreader/XSSFReaderSheet.java | 150 +++++++++ .../xssfreader/XSSFReaderSheetXMLHandler.java | 259 +++++++++++++++ .../excel/xssfreader/XSSFReaderWorkbook.java | 284 +++++++++++++++++ .../java/org/enso/table/read/ExcelReader.java | 46 +-- .../org/enso/table/write/ExcelWriter.java | 8 +- test/Table_Tests/src/IO/Excel_Spec.enso | 2 +- 18 files changed, 1257 insertions(+), 219 deletions(-) create mode 100644 std-bits/table/src/main/java/org/enso/table/excel/ExcelWorkbook.java create mode 100644 std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderFormats.java create mode 100644 std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderRow.java create mode 100644 std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheet.java create mode 100644 std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheetXMLHandler.java create mode 100644 std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderWorkbook.java diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Workbook.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Workbook.enso index a41dc5f58c0e..469ca8961f6b 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Workbook.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Excel/Excel_Workbook.enso @@ -49,7 +49,7 @@ type Excel_Workbook - file: The file to load. - xls_format: Whether to use the old XLS format (default is XLSX). new : File | Temporary_File -> Boolean -> Excel_Workbook - new file:(File | Temporary_File) xls_format=False = + new file:(File | Temporary_File) xls_format:Boolean=False = file_for_errors = if file.is_a Temporary_File then Nothing else file continuation raw_file = @@ -73,7 +73,7 @@ type Excel_Workbook - xls_format: Whether to use the old XLS format (default is XLSX). - file: Optional file reference. from_stream : Input_Stream -> Boolean -> File | Nothing -> Excel_Workbook - from_stream stream xls_format=False file=Nothing = Excel_Reader.handle_bad_format file <| + from_stream stream xls_format:Boolean=False file=Nothing = Excel_Reader.handle_bad_format file <| temp_file = Temporary_File.from_stream_light stream Excel_Workbook.new temp_file xls_format @@ -89,8 +89,8 @@ type Excel_Workbook ## PRIVATE ICON metadata Returns the list of databases (or catalogs) for the connection. - databases : Nothing - databases self = Nothing + databases : Vector (Text | Nothing) + databases self = [Nothing] ## PRIVATE ICON metadata @@ -109,7 +109,7 @@ type Excel_Workbook Arguments: - database: The target file to open as an Excel_Workbook. set_database : Text | File -> Excel_Workbook ! Illegal_Argument - set_database self database = + set_database self database:(Text | File) = if database == self.database then self else file = File.new database if file.exists && file.is_directory.not then Excel_Workbook.new file self.xls_format else @@ -163,7 +163,7 @@ type Excel_Workbook Gets the names of all the named ranges. named_ranges : Vector Text named_ranges self = self.with_java_workbook java_workbook-> - Vector.from_polyglot_array (ExcelReader.readRangeNames java_workbook) + Vector.from_polyglot_array java_workbook.getRangeNames ## PRIVATE ICON metadata diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelConnectionPool.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelConnectionPool.java index d790c570d5e7..92f4db31721a 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ExcelConnectionPool.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelConnectionPool.java @@ -20,6 +20,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.enso.table.excel.xssfreader.XSSFReaderWorkbook; public class ExcelConnectionPool { public static final ExcelConnectionPool INSTANCE = new ExcelConnectionPool(); @@ -64,7 +65,7 @@ public ReadOnlyExcelConnection openReadOnlyConnection(File file, ExcelFileFormat record.refCount = 1; record.file = file; record.format = format; - record.workbook = openWorkbook(file, format, false); + record.reopen(true); records.put(key, record); return new ReadOnlyExcelConnection(this, key, record); } @@ -212,10 +213,10 @@ static class ConnectionRecord { private int refCount; private File file; private ExcelFileFormat format; - private Workbook workbook; + private ExcelWorkbook workbook; private IOException initializationException = null; - T withWorkbook(Function action) throws IOException { + T withWorkbook(Function action) throws IOException { synchronized (this) { return action.apply(accessCurrentWorkbook()); } @@ -238,7 +239,10 @@ void reopen(boolean throwOnFailure) throws IOException { } try { - workbook = openWorkbook(file, format, false); + workbook = + format == ExcelFileFormat.XLSX + ? new XSSFReaderWorkbook(file.getAbsolutePath()) + : ExcelWorkbook.forPOIUserModel(openWorkbook(file, format, false)); } catch (IOException e) { initializationException = e; if (throwOnFailure) { @@ -248,7 +252,7 @@ void reopen(boolean throwOnFailure) throws IOException { } } - private Workbook accessCurrentWorkbook() throws IOException { + private ExcelWorkbook accessCurrentWorkbook() throws IOException { synchronized (this) { if (workbook == null) { if (initializationException != null) { @@ -278,7 +282,7 @@ private static Workbook openWorkbook(File file, ExcelFileFormat format, boolean throw e; } } - case XLSX -> { + case XLSX, XLSX_FALLBACK -> { try { PackageAccess access = writeAccess ? PackageAccess.READ_WRITE : PackageAccess.READ; OPCPackage pkg = OPCPackage.open(file, access); @@ -300,7 +304,7 @@ private static Workbook openWorkbook(File file, ExcelFileFormat format, boolean private static Workbook createEmptyWorkbook(ExcelFileFormat format) { return switch (format) { case XLS -> new HSSFWorkbook(); - case XLSX -> new XSSFWorkbook(); + case XLSX, XLSX_FALLBACK -> new XSSFWorkbook(); }; } diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelFileFormat.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelFileFormat.java index b5681c258e80..811d1d13f344 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ExcelFileFormat.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelFileFormat.java @@ -2,5 +2,6 @@ public enum ExcelFileFormat { XLS, - XLSX + XLSX, + XLSX_FALLBACK } diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelHeaders.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelHeaders.java index 056f62e54137..b7f4ca4cda62 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ExcelHeaders.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelHeaders.java @@ -57,7 +57,7 @@ private static String[] readRowAsHeaders( String[] output = new String[currentEndCol - startCol + 1]; for (int col = startCol; col <= currentEndCol; col++) { - String cellText = row.getFormattedCell(col); + String cellText = row.getCellText(col); String name = cellText.isEmpty() ? "" : deduplicator.makeUnique(cellText); output[col - startCol] = name; diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelRange.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelRange.java index 7c2f85f82d9e..552f3385fd27 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ExcelRange.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelRange.java @@ -197,7 +197,7 @@ public static ExcelRange expandSingleCell(ExcelRange excelRange, ExcelSheet shee Context context = Context.getCurrent(); while (currentRow != null && !currentRow.isEmpty(excelRange.getLeftColumn(), rightColumn)) { - rightColumn = currentRow.findEndRight(rightColumn); + rightColumn = findEndRight(currentRow, rightColumn); bottomRow++; currentRow = sheet.get(bottomRow); @@ -212,6 +212,16 @@ public static ExcelRange expandSingleCell(ExcelRange excelRange, ExcelSheet shee bottomRow - 1); } + private static int findEndRight(ExcelRow row, int start) { + Context context = Context.getCurrent(); + int column = start; + while (!row.isEmpty(column + 1)) { + column++; + context.safepoint(); + } + return column; + } + /** * @param index The index to the next character after the parsed value * @param value Parsed integer value or 0 if not valid diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelRow.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelRow.java index 4713213b33e0..f77c2eae533e 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ExcelRow.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelRow.java @@ -10,114 +10,51 @@ import org.apache.poi.ss.usermodel.ExcelNumberFormat; import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; import org.graalvm.polyglot.Context; /** Wrapper class to handle Excel rows. */ -public class ExcelRow { - private static final DataFormatter formatter = new DataFormatter(); - - private final Row row; - private final int firstColumn; - private final int lastColumn; - private final boolean use1904Format; - - public ExcelRow(Row row, boolean use1904Format) { - this.row = row; - this.firstColumn = row.getFirstCellNum() + 1; - this.lastColumn = row.getLastCellNum(); - this.use1904Format = use1904Format; - } +public interface ExcelRow { + /** Gets the initial column index within the row (1-based). */ + int getFirstColumn(); - public int getFirstColumn() { - return firstColumn; - } + /** Gets the final column index within the row (1-based). */ + int getLastColumn(); - public int getLastColumn() { - return lastColumn; - } + /** Gets the cell at the given index within the row (1-based). */ + Object getCellValue(int column); - public Cell get(int column) { - return (column < firstColumn || column > lastColumn) ? null : row.getCell(column - 1); - } + /** Gets the text of a cell at the given index within the row (1-based). */ + String getCellText(int column); - public Object getCellValue(int column) { - Cell cell = get(column); - CellType cellType = getCellType(cell); - switch (cellType) { - case NUMERIC: - double dblValue = cell.getNumericCellValue(); - var nf = ExcelNumberFormat.from(cell, null); - if (nf != null && DateUtil.isADateFormat(nf.getIdx(), nf.getFormat())) { - var temporal = - use1904Format - ? ExcelUtils.fromExcelDateTime1904(dblValue) - : ExcelUtils.fromExcelDateTime(dblValue); - - if (temporal == null) { - return null; - } - - return switch (temporal) { - case LocalDate date -> { - var dateFormat = cell.getCellStyle().getDataFormatString(); - yield (dateFormat.contains("h") || dateFormat.contains("H")) - ? date.atStartOfDay(ZoneId.systemDefault()) - : date; - } - case ZonedDateTime zdt -> { - if (!use1904Format || zdt.getYear() != 1904 || zdt.getDayOfYear() != 1) { - yield temporal; - } - var dateFormat = cell.getCellStyle().getDataFormatString(); - yield (dateFormat.contains("y") - || dateFormat.contains("M") - || dateFormat.contains("d")) - ? zdt - : zdt.toLocalTime(); - } - default -> temporal; - }; - } else { - if (dblValue == (long) dblValue) { - return (long) dblValue; - } else { - return dblValue; - } - } - case STRING: - return cell.getStringCellValue(); - case BOOLEAN: - return cell.getBooleanCellValue(); - default: - return null; - } - } + /** Gets the cell at the given index within the row (1-based). */ + Cell get(int column); - public static CellType getCellType(Cell cell) { - if (cell == null) { - return CellType._NONE; - } + /** Checks if the specified cell is empty. */ + boolean isEmpty(int column); - CellType cellType = cell.getCellType(); - if (cellType == CellType.FORMULA) { - cellType = cell.getCachedFormulaResultType(); - } + /** Checks if the specified set of cells are empty. */ + boolean isEmpty(int start, int end); - return cellType; - } + /** Gets the cells as text. */ + String[] getCellsAsText(int startCol, int endCol); - public boolean isEmpty(int column) { - CellType cellType = getCellType(get(column)); - return (cellType == CellType._NONE) || (cellType == CellType.BLANK); + /** Gets the underlying Apache POI Sheet object. */ + static ExcelRow forPOIUserModel(Sheet sheet, int rowIndex, boolean use1904Format) { + var row = sheet.getRow(rowIndex - 1); + return row == null + ? null + : new ExcelRowFromPOIUserModel( + row, row.getFirstCellNum() + 1, row.getLastCellNum(), use1904Format); } - public boolean isEmpty(int start, int end) { + static boolean isEmptyHelper(ExcelRow row, int start, int end) { Context context = Context.getCurrent(); - int currentEnd = end == -1 ? getLastColumn() : end; - for (int column = Math.max(getFirstColumn(), start); - column <= Math.min(getLastColumn(), currentEnd); + int currentEnd = end == -1 ? row.getLastColumn() : end; + for (int column = Math.max(row.getFirstColumn(), start); + column <= Math.min(row.getLastColumn(), currentEnd); column++) { - if (!isEmpty(column)) { + if (!row.isEmpty(column)) { return false; } @@ -126,63 +63,144 @@ public boolean isEmpty(int start, int end) { return true; } - public int findEndRight(int start) { - Context context = Context.getCurrent(); - int column = start; - while (!isEmpty(column + 1)) { - column++; - context.safepoint(); + record ExcelRowFromPOIUserModel(Row row, int firstColumn, int lastColumn, boolean use1904Format) + implements ExcelRow { + private static final DataFormatter formatter = new DataFormatter(); + + public int getFirstColumn() { + return firstColumn; + } + + public int getLastColumn() { + return lastColumn; } - return column; - } - /** Returns the formatted cell value. */ - public String getFormattedCell(int col) { - var cell = get(col); - if (cell == null) { - return ""; + public Cell get(int column) { + return (column < firstColumn || column > lastColumn) ? null : row.getCell(column - 1); } - var rawCellType = cell.getCellType(); - var cellType = - rawCellType == CellType.FORMULA ? cell.getCachedFormulaResultType() : rawCellType; - - return switch (cellType) { - case ERROR -> - // Want to show the error message rather than empty. - FormulaError.forInt(cell.getErrorCellValue()).getString(); - case NUMERIC -> { - // Special handling for Number or Date cells as want to keep formatting. - var format = ExcelNumberFormat.from(cell, null); - var value = cell.getNumericCellValue(); - yield format == null - ? Double.toString(value) - : formatter.formatRawCellContents(value, format.getIdx(), format.getFormat()); + public Object getCellValue(int column) { + Cell cell = get(column); + CellType cellType = getCellType(cell); + switch (cellType) { + case NUMERIC: + double dblValue = cell.getNumericCellValue(); + var nf = ExcelNumberFormat.from(cell, null); + if (nf != null && DateUtil.isADateFormat(nf.getIdx(), nf.getFormat())) { + var temporal = + use1904Format + ? ExcelUtils.fromExcelDateTime1904(dblValue) + : ExcelUtils.fromExcelDateTime(dblValue); + + if (temporal == null) { + return null; + } + + return switch (temporal) { + case LocalDate date -> { + var dateFormat = cell.getCellStyle().getDataFormatString(); + yield (dateFormat.contains("h") || dateFormat.contains("H")) + ? date.atStartOfDay(ZoneId.systemDefault()) + : date; + } + case ZonedDateTime zdt -> { + if (!use1904Format || zdt.getYear() != 1904 || zdt.getDayOfYear() != 1) { + yield temporal; + } + var dateFormat = cell.getCellStyle().getDataFormatString(); + yield (dateFormat.contains("y") + || dateFormat.contains("M") + || dateFormat.contains("d")) + ? zdt + : zdt.toLocalTime(); + } + default -> temporal; + }; + } else { + if (dblValue == (long) dblValue) { + return (long) dblValue; + } else { + return dblValue; + } + } + case STRING: + return cell.getStringCellValue(); + case BOOLEAN: + return cell.getBooleanCellValue(); + default: + return null; } - default -> { - // Use the default read and then toString. - var value = getCellValue(col); - yield value == null ? "" : value.toString(); + } + + public String getCellText(int column) { + var cell = get(column); + if (cell == null) { + return ""; } - }; - } - public String[] getCellsAsText(int startCol, int endCol) { - Context context = Context.getCurrent(); - int currentEndCol = endCol == -1 ? getLastColumn() : endCol; - - String[] output = new String[currentEndCol - startCol + 1]; - for (int col = startCol; col <= currentEndCol; col++) { - Cell cell = get(col); - CellType type = ExcelRow.getCellType(cell); - if (type != CellType._NONE && type != CellType.BLANK && type != CellType.STRING) { - return null; + var rawCellType = cell.getCellType(); + var cellType = + rawCellType == CellType.FORMULA ? cell.getCachedFormulaResultType() : rawCellType; + + return switch (cellType) { + case ERROR -> + // Want to show the error message rather than empty. + FormulaError.forInt(cell.getErrorCellValue()).getString(); + case NUMERIC -> { + // Special handling for Number or Date cells as want to keep formatting. + var format = ExcelNumberFormat.from(cell, null); + var value = cell.getNumericCellValue(); + yield format == null + ? Double.toString(value) + : formatter.formatRawCellContents(value, format.getIdx(), format.getFormat()); + } + default -> { + // Use the default read and then toString. + var value = getCellValue(column); + yield value == null ? "" : value.toString(); + } + }; + } + + public boolean isEmpty(int column) { + CellType cellType = getCellType(get(column)); + return (cellType == CellType._NONE) || (cellType == CellType.BLANK); + } + + public boolean isEmpty(int start, int end) { + return isEmptyHelper(this, start, end); + } + + public String[] getCellsAsText(int startCol, int endCol) { + Context context = Context.getCurrent(); + int currentEndCol = endCol == -1 ? getLastColumn() : endCol; + + String[] output = new String[currentEndCol - startCol + 1]; + for (int col = startCol; col <= currentEndCol; col++) { + Cell cell = get(col); + CellType type = getCellType(cell); + if (type != CellType._NONE && type != CellType.BLANK && type != CellType.STRING) { + return null; + } + output[col - startCol] = + type == CellType.STRING && cell != null ? cell.getStringCellValue() : ""; + context.safepoint(); } - output[col - startCol] = - type == CellType.STRING && cell != null ? cell.getStringCellValue() : ""; - context.safepoint(); + + return output; } - return output; + private static CellType getCellType(Cell cell) { + if (cell == null) { + return CellType._NONE; + } + + CellType cellType = cell.getCellType(); + if (cellType == CellType.FORMULA) { + cellType = cell.getCachedFormulaResultType(); + } + + return cellType; + } } } diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelSheet.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelSheet.java index 6b2d70245e4c..4d2dd42a2a32 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ExcelSheet.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelSheet.java @@ -1,37 +1,83 @@ package org.enso.table.excel; -import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; /** Wrapper class to handle Excel sheets. */ -public class ExcelSheet { - private final Sheet sheet; - private final int firstRow; - private final int lastRow; - private final boolean use1904Format; - - public ExcelSheet(Workbook workbook, int sheetIndex) { - this.sheet = workbook.getSheetAt(sheetIndex); - this.firstRow = sheet.getFirstRowNum() + 1; - this.lastRow = sheet.getLastRowNum() + 1; - this.use1904Format = ExcelUtils.is1904DateSystem(workbook); - } +public interface ExcelSheet { + /** Gets the index of the sheet within the workbook (0-based). */ + int getSheetIndex(); - public int getLastRow() { - return lastRow; - } + /** Gets the name of the sheet. */ + String getName(); - public int getFirstRow() { - return firstRow; - } + /** Gets the initial row index within the sheet (1-based). */ + int getFirstRow(); + + /** Gets the final row index within the sheet (1-based). */ + int getLastRow(); + + /** + * Gets the row at the given index within the sheet (1-based) + * + * @param row the row index (1-based)/ + * @return the row object or null if the row index is out of range or doesn't exist. + */ + ExcelRow get(int row); + + /** Gets the underlying Apache POI Sheet object - may be null. Provided for Writer use only. */ + Sheet getSheet(); - public ExcelRow get(int row) { - Row underlyingRow = row < firstRow || row > lastRow ? null : sheet.getRow(row - 1); - return underlyingRow == null ? null : new ExcelRow(underlyingRow, use1904Format); + /** Gets the underlying Apache POI Sheet object. */ + static ExcelSheet forPOIUserModel(Workbook workbook, int sheetIndex) { + var sheet = workbook.getSheetAt(sheetIndex); + return new ExcelSheetFromPOIUserModel( + sheet, + sheetIndex, + sheet.getSheetName(), + sheet.getFirstRowNum() + 1, + sheet.getLastRowNum() + 1, + ExcelUtils.is1904DateSystem(workbook)); } - public Sheet getSheet() { - return sheet; + record ExcelSheetFromPOIUserModel( + Sheet sheet, + int sheetIndex, + String sheetName, + int firstRow, + int lastRow, + boolean use1904Format) + implements ExcelSheet { + @Override + public int getSheetIndex() { + return sheetIndex; + } + + @Override + public String getName() { + return sheetName; + } + + @Override + public int getFirstRow() { + return firstRow; + } + + @Override + public int getLastRow() { + return lastRow; + } + + @Override + public ExcelRow get(int row) { + return row < firstRow || row > lastRow + ? null + : ExcelRow.forPOIUserModel(sheet, row, use1904Format); + } + + @Override + public Sheet getSheet() { + return sheet; + } } } diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelUtils.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelUtils.java index f30bbdbde434..851fee7aeb63 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ExcelUtils.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelUtils.java @@ -1,6 +1,10 @@ package org.enso.table.excel; -import java.time.*; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import org.apache.poi.ss.usermodel.Workbook; diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ExcelWorkbook.java b/std-bits/table/src/main/java/org/enso/table/excel/ExcelWorkbook.java new file mode 100644 index 000000000000..91b86fd31f7b --- /dev/null +++ b/std-bits/table/src/main/java/org/enso/table/excel/ExcelWorkbook.java @@ -0,0 +1,123 @@ +package org.enso.table.excel; + +import java.io.IOException; +import org.apache.poi.ss.usermodel.Name; + +/** Represents an Excel workbook. Wraps the underlying Apache POI Workbook object. */ +public interface ExcelWorkbook { + /** + * Get the number of spreadsheets in the workbook + * + * @return the number of sheets + */ + int getNumberOfSheets(); + + /** + * Returns the index of the sheet by its name + * + * @param name the sheet name + * @return index of the sheet (0 based) + */ + int getSheetIndex(String name); + + /** + * Get the sheet name + * + * @param sheet sheet number (0 based) + * @return Sheet name + */ + String getSheetName(int sheet); + + /** + * @return the total number of defined names in this workbook + */ + int getNumberOfNames(); + + /** + * Get all the range names in the workbook + * + * @return an array of range names + */ + String[] getRangeNames(); + + /** + * Get the formula for a named range. + * + * @param name the name of the range. + * @return the formula for the range or null if not found. + */ + String getNameFormula(String name); + + /** + * Get a sheet by its index + * + * @param sheetIndex the index of the sheet (0 based) + * @return the sheet as an ExcelSheet object + * @throws IllegalArgumentException if the sheet index is out of range. + */ + ExcelSheet getSheetAt(int sheetIndex); + + /** + * Close the underlying input resource (File or Stream), from which the Workbook was read. + * + *

Once this has been called, no further operations, updates or reads should be performed on + * the Workbook. + */ + void close() throws IOException; + + /** + * Create an ExcelWorkbook object from an Apache POI Workbook object + * + * @param workbook the Apache POI Workbook object + * @return the ExcelWorkbook object + */ + static ExcelWorkbook forPOIUserModel(org.apache.poi.ss.usermodel.Workbook workbook) { + return new ExcelWorkbookFromPOIUserModel(workbook); + } + + // ** Wrap a Workbook object in the interface. */ + record ExcelWorkbookFromPOIUserModel(org.apache.poi.ss.usermodel.Workbook workbook) + implements ExcelWorkbook { + @Override + public int getNumberOfSheets() { + return workbook.getNumberOfSheets(); + } + + @Override + public int getSheetIndex(String name) { + return workbook.getSheetIndex(name); + } + + @Override + public String getSheetName(int sheet) { + return workbook.getSheetName(sheet); + } + + @Override + public int getNumberOfNames() { + return workbook.getNumberOfNames(); + } + + @Override + public String[] getRangeNames() { + var names = workbook.getAllNames(); + return names.stream().map(Name::getNameName).toArray(String[]::new); + } + + @Override + public String getNameFormula(String name) { + var namedRange = workbook.getName(name); + return namedRange == null ? null : namedRange.getRefersToFormula(); + } + + @Override + public ExcelSheet getSheetAt(int sheetIndex) { + return ExcelSheet.forPOIUserModel(workbook, sheetIndex); + } + + @Override + public void close() throws IOException { + workbook.close(); + } + } +} diff --git a/std-bits/table/src/main/java/org/enso/table/excel/ReadOnlyExcelConnection.java b/std-bits/table/src/main/java/org/enso/table/excel/ReadOnlyExcelConnection.java index 60bc80e4d73b..3cbac859648a 100644 --- a/std-bits/table/src/main/java/org/enso/table/excel/ReadOnlyExcelConnection.java +++ b/std-bits/table/src/main/java/org/enso/table/excel/ReadOnlyExcelConnection.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.util.function.Function; -import org.apache.poi.ss.usermodel.Workbook; public class ReadOnlyExcelConnection implements AutoCloseable { @@ -28,7 +27,7 @@ public synchronized void close() throws IOException { record = null; } - public synchronized T withWorkbook(Function f) throws IOException { + public synchronized T withWorkbook(Function f) throws IOException { if (record == null) { throw new IllegalStateException("ReadOnlyExcelConnection is being used after it was closed."); } diff --git a/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderFormats.java b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderFormats.java new file mode 100644 index 000000000000..c634162c449f --- /dev/null +++ b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderFormats.java @@ -0,0 +1,29 @@ +package org.enso.table.excel.xssfreader; + +import java.util.HashMap; +import java.util.Map; +import org.apache.poi.xssf.model.StylesTable; + +/** Provides the format strings for number formats in an XSSF workbook. */ +public class XSSFReaderFormats { + private final StylesTable stylesTable; + private final Map numberFormats = new HashMap<>(); + + public XSSFReaderFormats(StylesTable stylesTable) { + this.stylesTable = stylesTable; + } + + public String getNumberFormatAt(short styleIdx) { + if (numberFormats.containsKey(styleIdx)) { + return numberFormats.get(styleIdx); + } + + var style = stylesTable.getStyleAt(styleIdx); + var format = style == null ? "General" : style.getDataFormatString(); + if (format == null || format.equals("General")) { + format = ""; + } + numberFormats.put(styleIdx, format); + return format; + } +} diff --git a/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderRow.java b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderRow.java new file mode 100644 index 000000000000..a35f0fcc72d3 --- /dev/null +++ b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderRow.java @@ -0,0 +1,125 @@ +package org.enso.table.excel.xssfreader; + +import java.time.LocalDateTime; +import java.util.SortedMap; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.enso.table.excel.ExcelRow; + +public class XSSFReaderRow implements ExcelRow { + private static final DataFormatter formatter = new DataFormatter(); + private final SortedMap data; + private final boolean use1904Dates; + + public XSSFReaderRow( + SortedMap data, boolean use1904Dates) { + this.data = data; + this.use1904Dates = use1904Dates; + } + + @Override + public int getFirstColumn() { + return data.firstKey(); + } + + @Override + public int getLastColumn() { + return data.lastKey(); + } + + @Override + public Cell get(int column) { + // Not supported as we don't have the underlying Apache POI Cell object. + throw new UnsupportedOperationException("XSSFReader does not support getting the Cell object."); + } + + @Override + public Object getCellValue(int column) { + var cell = data.get((short) column); + if (cell == null) { + return null; + } + + var dataType = cell.dataType(); + return switch (dataType) { + case BLANK -> null; + case BOOL -> cell.getBooleanValue(); + case DATE -> LocalDateTime.parse(cell.strValue()); // Don't believe used by Excel. + case INLINE_STRING, SST_STRING, FORMULA_STRING -> cell.strValue(); + case INTEGER -> cell.getIntegerValue(); + case NUMBER -> { + double dbl = cell.getNumberValue(); + long longVal = (long) dbl; + if (dbl == longVal) { + yield (long) dbl; + } else { + yield dbl; + } + } + case OLE_DATE -> cell.getDateValue(use1904Dates); + case OLE_DATETIME -> cell.getDateTimeValue(use1904Dates); + case ERROR -> null; + }; + } + + @Override + public String getCellText(int column) { + var cell = data.get((short) column); + if (cell == null) { + return ""; + } + + var dataType = cell.dataType(); + return switch (dataType) { + case BLANK -> ""; + case NUMBER, OLE_DATETIME, OLE_DATE, INTEGER -> { + // Special handling for Number or Date cells as want to keep formatting. + var formatText = cell.format(); + if (formatText == null || formatText.isEmpty()) { + yield cell.strValue(); + } + yield formatter.formatRawCellContents(cell.getNumberValue(), -1, formatText, use1904Dates); + } + case BOOL -> cell.getBooleanValue() ? "TRUE" : "FALSE"; + default -> cell.strValue(); + }; + } + + @Override + public boolean isEmpty(int column) { + var cell = data.get((short) column); + return cell == null || cell.strValue().isEmpty(); + } + + @Override + public boolean isEmpty(int start, int end) { + int currentEnd = end == -1 ? getLastColumn() : end; + for (int column = Math.max(getFirstColumn(), start); + column <= Math.min(getLastColumn(), currentEnd); + column++) { + if (!isEmpty(column)) { + return false; + } + } + return true; + } + + @Override + public String[] getCellsAsText(int startCol, int endCol) { + int currentEndCol = endCol == -1 ? getLastColumn() : endCol; + + String[] output = new String[currentEndCol - startCol + 1]; + for (int col = startCol; col <= currentEndCol; col++) { + + var cell = data.get((short) col); + if (cell != null && !cell.dataType().isString()) { + // Short circuit if find not a string cell. + return null; + } + + output[col - startCol] = cell == null ? "" : cell.strValue(); + } + + return output; + } +} diff --git a/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheet.java b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheet.java new file mode 100644 index 000000000000..cdb79cbdbd5b --- /dev/null +++ b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheet.java @@ -0,0 +1,150 @@ +package org.enso.table.excel.xssfreader; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import javax.xml.parsers.ParserConfigurationException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.util.XMLHelper; +import org.enso.table.excel.ExcelRow; +import org.enso.table.excel.ExcelSheet; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class XSSFReaderSheet implements ExcelSheet { + private final int sheetIdx; + private final String sheetName; + private final String relId; + private final XSSFReaderWorkbook parent; + + private boolean hasReadSheetData = false; + private String dimensions; + private int firstRow; + private int lastRow; + private Map> rowData; + + public XSSFReaderSheet(int sheetIdx, String sheetName, String relId, XSSFReaderWorkbook parent) { + this.sheetIdx = sheetIdx; + this.sheetName = sheetName; + this.relId = relId; + this.parent = parent; + } + + private synchronized void ensureReadSheetData() { + if (hasReadSheetData) { + return; + } + + try { + var strings = parent.getSharedStrings(); + var styles = parent.getStyles(); + var handler = + new XSSFReaderSheetXMLHandler(styles, strings) { + @Override + protected void onDimensions(String dimension) { + handleOnDimensions(dimension); + } + + @Override + protected void onStartRow(int rowNum) { + handleOnStartRow(rowNum); + } + + @Override + protected void onCell(int rowNumber, short columnNumber, String ref, CellValue value) { + handleOnCell(rowNumber, columnNumber, value); + } + }; + + var xmlReader = XMLHelper.newXMLReader(); + xmlReader.setContentHandler(handler); + + rowData = new HashMap<>(); + + try { + parent.withReader( + reader -> { + try { + var sheet = reader.getSheet(relId); + xmlReader.parse(new InputSource(sheet)); + } catch (SAXException | InvalidFormatException | IOException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + + hasReadSheetData = true; + } catch (SAXException | ParserConfigurationException e) { + throw new RuntimeException(e); + } + } + + @Override + public int getSheetIndex() { + return sheetIdx; + } + + @Override + public String getName() { + return sheetName; + } + + public String getDimensions() { + ensureReadSheetData(); + return dimensions; + } + + @Override + public int getFirstRow() { + ensureReadSheetData(); + return firstRow; + } + + @Override + public int getLastRow() { + ensureReadSheetData(); + return lastRow; + } + + @Override + public ExcelRow get(int row) { + ensureReadSheetData(); + + if (!rowData.containsKey(row)) { + return null; + } + + return new XSSFReaderRow(rowData.get(row), parent.use1904Format()); + } + + @Override + public Sheet getSheet() { + // Not supported as we don't have the underlying Apache POI Sheet object. + throw new UnsupportedOperationException( + "XSSFReader does not support getting the Sheet object."); + } + + protected void handleOnDimensions(String dimension) { + dimensions = dimension; + } + + private void handleOnStartRow(int rowNum) { + if (firstRow == 0 || rowNum < firstRow) { + firstRow = rowNum; + } + + if (lastRow == 0 || rowNum > lastRow) { + lastRow = rowNum; + } + } + + private void handleOnCell( + int rowNumber, short columnNumber, XSSFReaderSheetXMLHandler.CellValue value) { + rowData.computeIfAbsent(rowNumber, k -> new TreeMap<>()).put(columnNumber, value); + } +} diff --git a/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheetXMLHandler.java b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheetXMLHandler.java new file mode 100644 index 000000000000..f3ea10bcbba3 --- /dev/null +++ b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderSheetXMLHandler.java @@ -0,0 +1,259 @@ +package org.enso.table.excel.xssfreader; + +import static org.apache.poi.xssf.usermodel.XSSFRelation.NS_SPREADSHEETML; + +import java.time.ZonedDateTime; +import java.time.temporal.Temporal; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.xssf.model.SharedStrings; +import org.apache.poi.xssf.usermodel.XSSFRichTextString; +import org.enso.table.excel.ExcelUtils; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; + +/** Based on the XSSFSheetXMLHandler class from Apache POI. */ +/** + * SAX-based Handler to Read Excel XML on top of POI support. Technical specification can be found + * at: + * https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/db9b9b72-b10b-4e7e-844c-09f88c972219 + * https://ecma-international.org/publications-and-standards/standards/ecma-376/ + */ +public class XSSFReaderSheetXMLHandler extends DefaultHandler { + private final XSSFReaderFormats styles; + private final SharedStrings sharedStrings; + + public enum XSSDataType { + BLANK, + BOOL, + DATE, + ERROR, + INLINE_STRING, + SST_STRING, + NUMBER, + INTEGER, + OLE_DATE, + OLE_DATETIME, + FORMULA_STRING; + + public boolean isString() { + return this == INLINE_STRING || this == SST_STRING || this == FORMULA_STRING; + } + } + + // Record if seen a value element + private boolean seenValue; + + // Set when V start element is seen + private boolean vIsOpen; + + // Set when an Inline String "is" is seen + private boolean isIsOpen; + + // The current row being read (or -1 if not in a row) + private int rowNumber = -1; + + // Handle missing rowNumber in the XML (happens in Excel), first row would be row 1. + private int nextRowNumber = 1; + + // The current cell being read (or null if not in a cell) + private String cellRef; + + // Set when cell start element is seen, used when cell close element is seen. + private XSSDataType dataType; + + // Gathers characters as they are seen. + private final StringBuilder value = new StringBuilder(64); + private String numberFormat = null; + + public XSSFReaderSheetXMLHandler(XSSFReaderFormats styles, SharedStrings strings) { + this.styles = styles; + this.sharedStrings = strings; + } + + private boolean isTextTag(String name) { + return "v".equals(name) || "inlineStr".equals(name) || ("t".equals(name) && isIsOpen); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) { + if (uri != null && !NS_SPREADSHEETML.equals(uri)) { + return; + } + + if (isTextTag(localName)) { + seenValue = true; + vIsOpen = true; + if (!isIsOpen) { + value.setLength(0); + } + } else { + switch (localName) { + case "dimension": // Dimensions of sheet + var dimension = attributes.getValue("ref"); + if (dimension != null) { + onDimensions(dimension); + } + break; + case "row": // Row + String rowNumStr = attributes.getValue("r"); + rowNumber = rowNumStr == null ? nextRowNumber : Integer.parseInt(rowNumStr); + onStartRow(rowNumber); + break; + case "c": // Cell + cellRef = attributes.getValue("r"); + seenValue = false; + + String cellType = attributes.getValue("t"); + if (cellType == null) { + cellType = "n"; // Number is default + } + + dataType = + switch (cellType) { + case "b" -> XSSDataType.BOOL; + case "e" -> XSSDataType.ERROR; + case "d" -> XSSDataType.DATE; // Date in ISO 8601 format. + case "inlineStr" -> XSSDataType.INLINE_STRING; + case "s" -> XSSDataType.SST_STRING; + case "str" -> XSSDataType.FORMULA_STRING; // String formula + default -> XSSDataType.NUMBER; + }; + + // Read the format for NUMBER + numberFormat = null; + if (dataType == XSSDataType.NUMBER) { + String cellStyleStr = attributes.getValue("s"); + if (cellStyleStr != null) { + short styleIndex = (short) Integer.parseInt(cellStyleStr); + numberFormat = styles.getNumberFormatAt(styleIndex); + } + } + break; + case "is": // Inline String + isIsOpen = true; + break; + } + } + } + + /** Captures characters if a suitable element is open. */ + @Override + public void characters(char[] ch, int start, int length) { + if (vIsOpen) { + value.append(ch, start, length); + } + } + + @Override + public void endElement(String uri, String localName, String qName) { + if (uri != null && !NS_SPREADSHEETML.equals(uri)) { + return; + } + + if (isTextTag(localName)) { + vIsOpen = false; + } else { + switch (localName) { + case "sheetData" -> onSheetEnd(); + case "row" -> { + nextRowNumber = rowNumber + 1; + rowNumber = -1; + } + case "c" -> outputCellValue(); + case "is" -> isIsOpen = false; + case "v" -> vIsOpen = false; + } + } + } + + public record CellValue(XSSDataType dataType, String strValue, String format) { + public boolean getBooleanValue() { + return strValue.charAt(0) == '1'; + } + + public double getNumberValue() { + return Double.parseDouble(strValue); + } + + public long getIntegerValue() { + return Long.parseLong(strValue); + } + + public Temporal getDateValue(boolean use1904Dates) { + return use1904Dates + ? ExcelUtils.fromExcelDateTime1904(getIntegerValue()) + : ExcelUtils.fromExcelDateTime(getIntegerValue()); + } + + public Temporal getDateTimeValue(boolean use1904Dates) { + if (use1904Dates) { + var datetime = ExcelUtils.fromExcelDateTime1904(getNumberValue()); + if (datetime instanceof ZonedDateTime zdt + && zdt.getYear() == 1904 + && zdt.getDayOfYear() == 1 + && !format.contains("y") + && !format.contains("M") + && !format.contains("d")) { + datetime = zdt.toLocalTime(); + } + return datetime; + } + + return ExcelUtils.fromExcelDateTime(getNumberValue()); + } + } + + public String getStringValue() { + if (dataType == XSSDataType.SST_STRING) { + return getSharedString(value.toString()); + } else if (dataType == XSSDataType.INLINE_STRING) { + return new XSSFRichTextString(value.toString()).toString(); + } + return value.toString(); + } + + private String getSharedString(String value) { + int idx = Integer.parseInt(value); + var ss = sharedStrings.getItemAt(idx); + return ss == null ? null : ss.toString(); + } + + private void outputCellValue() { + short columnNumber = 0; + int i = 0; + char c; + while (i < cellRef.length() && (c = cellRef.charAt(i)) >= 'A' && c <= 'Z') { + columnNumber = (short) (columnNumber * 26 + (c - 'A' + 1)); + i++; + } + + if (!seenValue) { + onCell(rowNumber, columnNumber, cellRef, new CellValue(XSSDataType.BLANK, "", null)); + return; + } + + var stringValue = getStringValue(); + if (dataType == XSSDataType.NUMBER) { + boolean isInteger = !stringValue.contains("."); + boolean isDate = DateUtil.isADateFormat(-1, numberFormat); + if (isInteger && isDate) { + dataType = XSSDataType.OLE_DATE; + } else if (isInteger) { + dataType = XSSDataType.INTEGER; + } else if (isDate) { + dataType = XSSDataType.OLE_DATETIME; + } + } + + var cellValue = new CellValue(dataType, stringValue, numberFormat); + onCell(rowNumber, columnNumber, cellRef, cellValue); + } + + protected void onDimensions(String dimension) {} + + protected void onStartRow(int rowNumber) {} + + protected void onCell(int rowNumber, short columnNumber, String ref, CellValue cellValue) {} + + protected void onSheetEnd() {} +} diff --git a/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderWorkbook.java b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderWorkbook.java new file mode 100644 index 000000000000..6502057ff416 --- /dev/null +++ b/std-bits/table/src/main/java/org/enso/table/excel/xssfreader/XSSFReaderWorkbook.java @@ -0,0 +1,284 @@ +package org.enso.table.excel.xssfreader; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import org.apache.poi.ooxml.util.DocumentHelper; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.xssf.eventusermodel.XSSFReader; +import org.apache.poi.xssf.model.SharedStrings; +import org.apache.poi.xssf.usermodel.XSSFRelation; +import org.enso.table.excel.ExcelSheet; +import org.enso.table.excel.ExcelWorkbook; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +public class XSSFReaderWorkbook implements ExcelWorkbook { + private static final XPathFactory xpathFactory = XPathFactory.newInstance(); + private static final NamespaceContext namespaceContext = new SpreadsheetContext(); + private static final Map xpathCache = new HashMap<>(); + + private static XPathExpression compileXPathWithNamespace(String xpath) + throws XPathExpressionException { + if (!xpathCache.containsKey(xpath)) { + var newXPath = xpathFactory.newXPath(); + newXPath.setNamespaceContext(namespaceContext); + var compiled = newXPath.compile(xpath); + xpathCache.put(xpath, compiled); + } + return xpathCache.get(xpath); + } + + private static class SpreadsheetContext implements NamespaceContext { + @Override + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("prefix cannot be null"); + } + return prefix.equals("ss") ? XSSFRelation.NS_SPREADSHEETML : XMLConstants.NULL_NS_URI; + } + + @Override + public String getPrefix(String namespaceURI) { + if (namespaceURI == null) { + throw new IllegalArgumentException("namespaceURI cannot be null"); + } + return namespaceURI.equals(XSSFRelation.NS_SPREADSHEETML) ? "ss" : null; + } + + @Override + public Iterator getPrefixes(String namespaceURI) { + if (namespaceURI == null) { + throw new IllegalArgumentException("namespaceURI cannot be null"); + } + return namespaceURI.equals(XSSFRelation.NS_SPREADSHEETML) + ? Collections.singleton("ss").iterator() + : Arrays.stream(new String[0]).iterator(); + } + } + + public static final String WORKBOOK_CONFIG_XPATH = "/ss:workbook/ss:workbookPr"; + public static final String SHEET_NAME_XPATH = "/ss:workbook/ss:sheets/ss:sheet"; + public static final String NAMED_RANGE_XPATH = "/ss:workbook/ss:definedNames/ss:definedName"; + + private final String path; + + private boolean use1904DateSystemFlag = false; + private List sheetInfos; + private Map sheetInfoMap; + private Map namedRangeMap; + + private boolean hasReadShared = false; + private SharedStrings sharedStrings; + private XSSFReaderFormats styles; + + public XSSFReaderWorkbook(String path) throws IOException { + this.path = path; + + // Read the workbook data + this.readWorkbookData(); + } + + public String getPath() { + return path; + } + + void withReader(Consumer action) throws IOException { + try (var pkg = OPCPackage.open(path, PackageAccess.READ)) { + var reader = new XSSFReader(pkg); + action.accept(reader); + } catch (OpenXML4JException e) { + throw new IOException( + "Invalid format encountered when opening the file " + path + " as XLSX.", e); + } + } + + private record SheetInfo(int index, int sheetId, String name, String relID, boolean visible) {} + + private record NamedRange(String name, String formula) {} + + private void readWorkbookData() throws IOException { + withReader( + reader -> { + try { + var workbookData = reader.getWorkbookData(); + var workbookDoc = DocumentHelper.readDocument(workbookData); + read1904DateSetting(workbookDoc); + readSheetInfo(workbookDoc); + readNamedRanges(workbookDoc); + } catch (SAXException + | IOException + | InvalidFormatException + | XPathExpressionException e) { + throw new RuntimeException(e); + } + }); + } + + private void readNamedRanges(Document workbookDoc) throws XPathExpressionException { + var namesXPath = compileXPathWithNamespace(NAMED_RANGE_XPATH); + var nameNodes = (NodeList) namesXPath.evaluate(workbookDoc, XPathConstants.NODESET); + namedRangeMap = new HashMap<>(); + for (int i = 0; i < nameNodes.getLength(); i++) { + var node = nameNodes.item(i); + var name = node.getAttributes().getNamedItem("name").getNodeValue(); + var formula = node.getTextContent(); + namedRangeMap.put(name, new NamedRange(name, formula)); + } + } + + private void readSheetInfo(Document workbookDoc) throws XPathExpressionException { + var sheetXPath = compileXPathWithNamespace(SHEET_NAME_XPATH); + var sheetNodes = (NodeList) sheetXPath.evaluate(workbookDoc, XPathConstants.NODESET); + sheetInfos = new ArrayList<>(sheetNodes.getLength()); + sheetInfoMap = new HashMap<>(); + for (int i = 0; i < sheetNodes.getLength(); i++) { + var node = sheetNodes.item(i); + var sheetName = node.getAttributes().getNamedItem("name").getNodeValue(); + var sheetId = Integer.parseInt(node.getAttributes().getNamedItem("sheetId").getNodeValue()); + var relId = node.getAttributes().getNamedItem("r:id").getNodeValue(); + var visible = node.getAttributes().getNamedItem("state") == null; + var sheetInfo = new SheetInfo(i, sheetId, sheetName, relId, visible); + sheetInfos.add(sheetInfo); + sheetInfoMap.put(sheetName, sheetInfo); + } + } + + private void read1904DateSetting(Document workbookDoc) throws XPathExpressionException { + var workbookXPath = compileXPathWithNamespace(WORKBOOK_CONFIG_XPATH); + var workbookNode = (Node) workbookXPath.evaluate(workbookDoc, XPathConstants.NODE); + if (workbookNode != null) { + var date1904 = workbookNode.getAttributes().getNamedItem("date1904"); + use1904DateSystemFlag = date1904 != null && "1".equals(date1904.getNodeValue()); + } + } + + private synchronized void ensureReadShared() { + if (hasReadShared) { + return; + } + + try { + withReader( + reader -> { + try { + reader.setUseReadOnlySharedStringsTable(true); + sharedStrings = reader.getSharedStringsTable(); + if (sharedStrings == null) { + sharedStrings = + new SharedStrings() { + @Override + public RichTextString getItemAt(int idx) { + return null; + } + + @Override + public int getCount() { + return 0; + } + + @Override + public int getUniqueCount() { + return 0; + } + }; + } + + // Read the styles table and attach the format data + var stylesTable = reader.getStylesTable(); + styles = new XSSFReaderFormats(stylesTable); + + hasReadShared = true; + } catch (InvalidFormatException | IOException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** Flag that workbook is in 1904 format. */ + boolean use1904Format() { + return use1904DateSystemFlag; + } + + @Override + public int getNumberOfSheets() { + return sheetInfoMap.size(); + } + + @Override + public int getSheetIndex(String name) { + if (!sheetInfoMap.containsKey(name)) { + return -1; + } + return sheetInfoMap.get(name).index; + } + + @Override + public String getSheetName(int sheet) { + if (sheet < 0 || sheet >= sheetInfos.size()) { + throw new IllegalArgumentException("Sheet index out of range: " + sheet); + } + return sheetInfos.get(sheet).name; + } + + @Override + public int getNumberOfNames() { + return namedRangeMap.size(); + } + + @Override + public String[] getRangeNames() { + return namedRangeMap.keySet().toArray(String[]::new); + } + + @Override + public String getNameFormula(String name) { + var namedRange = namedRangeMap.get(name); + return namedRange == null ? null : namedRange.formula; + } + + public SharedStrings getSharedStrings() { + ensureReadShared(); + return sharedStrings; + } + + public XSSFReaderFormats getStyles() { + ensureReadShared(); + return styles; + } + + @Override + public ExcelSheet getSheetAt(int sheetIndex) { + if (sheetIndex < 0 || sheetIndex >= sheetInfos.size()) { + throw new IllegalArgumentException("Sheet index out of range: " + sheetIndex); + } + var sheetInfo = sheetInfos.get(sheetIndex); + return new XSSFReaderSheet(sheetIndex, sheetInfo.name, sheetInfo.relID, this); + } + + @Override + public void close() throws IOException { + // Nothing to do + } +} diff --git a/std-bits/table/src/main/java/org/enso/table/read/ExcelReader.java b/std-bits/table/src/main/java/org/enso/table/read/ExcelReader.java index 1a8e1ab54c60..6f6b289e8998 100644 --- a/std-bits/table/src/main/java/org/enso/table/read/ExcelReader.java +++ b/std-bits/table/src/main/java/org/enso/table/read/ExcelReader.java @@ -7,9 +7,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.ss.usermodel.Name; -import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellReference; import org.enso.table.data.column.builder.Builder; import org.enso.table.data.column.builder.InferredBuilder; @@ -24,6 +21,7 @@ import org.enso.table.excel.ExcelRange; import org.enso.table.excel.ExcelRow; import org.enso.table.excel.ExcelSheet; +import org.enso.table.excel.ExcelWorkbook; import org.enso.table.excel.ReadOnlyExcelConnection; import org.enso.table.problems.ProblemAggregator; import org.graalvm.polyglot.Context; @@ -38,18 +36,17 @@ public class ExcelReader { * @return a String[] containing the sheet names. * @throws IOException when the action fails */ - public static String[] readSheetNames(File file, ExcelFileFormat format) - throws IOException, InvalidFormatException { + public static String[] readSheetNames(File file, ExcelFileFormat format) throws IOException { return withWorkbook(file, format, ExcelReader::readSheetNames); } /** * Reads a list of sheet names from a workbook into an array. * - * @param workbook a {@link Workbook} to read the sheet names from. + * @param workbook a {@link ExcelWorkbook} to read the sheet names from. * @return a String[] containing the sheet names. */ - public static String[] readSheetNames(Workbook workbook) { + public static String[] readSheetNames(ExcelWorkbook workbook) { int sheetCount = workbook.getNumberOfSheets(); var output = new String[sheetCount]; Context context = Context.getCurrent(); @@ -68,20 +65,8 @@ public static String[] readSheetNames(Workbook workbook) { * @return a String[] containing the range names. * @throws IOException when the action fails */ - public static String[] readRangeNames(File file, ExcelFileFormat format) - throws IOException, InvalidFormatException { - return withWorkbook(file, format, ExcelReader::readRangeNames); - } - - /** - * Reads a list of range names for the specified XLSX/XLS file into an array. - * - * @param workbook a {@link Workbook} to read the sheet names from. - * @return a String[] containing the range names. - */ - public static String[] readRangeNames(Workbook workbook) { - var names = workbook.getAllNames(); - return names.stream().map(Name::getNameName).toArray(String[]::new); + public static String[] readRangeNames(File file, ExcelFileFormat format) throws IOException { + return withWorkbook(file, format, ExcelWorkbook::getRangeNames); } /** @@ -202,7 +187,7 @@ public static Table readRangeByName( /** * Reads a range by sheet name, named range or address for the workbook into a table. * - * @param workbook a {@link Workbook} to read from. + * @param workbook a {@link ExcelWorkbook} to read from. * @param rangeNameOrAddress sheet name, range name or address to read. * @param headers specifies whether the first row should be used as headers. * @param skip_rows skip rows from the top of the range. @@ -211,7 +196,7 @@ public static Table readRangeByName( * @throws InvalidLocationException when the range name or address is not found. */ public static Table readRangeByName( - Workbook workbook, + ExcelWorkbook workbook, String rangeNameOrAddress, ExcelHeaders.HeaderBehavior headers, int skip_rows, @@ -230,11 +215,10 @@ public static Table readRangeByName( problemAggregator); } - Name name = workbook.getName(rangeNameOrAddress); - ExcelRange excelRange; try { - excelRange = new ExcelRange(name == null ? rangeNameOrAddress : name.getRefersToFormula()); + var formula = workbook.getNameFormula(rangeNameOrAddress); + excelRange = new ExcelRange(formula == null ? rangeNameOrAddress : formula); } catch (IllegalArgumentException e) { throw new InvalidLocationException( rangeNameOrAddress, @@ -271,8 +255,8 @@ public static Table readRange( readRange(workbook, excelRange, headers, skip_rows, row_limit, problemAggregator)); } - private static T withWorkbook(File file, ExcelFileFormat format, Function action) - throws IOException { + private static T withWorkbook( + File file, ExcelFileFormat format, Function action) throws IOException { try (ReadOnlyExcelConnection connection = ExcelConnectionPool.INSTANCE.openReadOnlyConnection(file, format)) { return connection.withWorkbook(action); @@ -280,7 +264,7 @@ private static T withWorkbook(File file, ExcelFileFormat format, Function tsv_file = base_dir / "1.tsv" From aebfacd48694a7beed831f9397b0d8ea2360a93c Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Mon, 16 Dec 2024 07:15:17 -0800 Subject: [PATCH 04/12] CodeEditor improvements (#11852) --- app/gui/package.json | 12 +- .../components/CodeEditor/CodeEditorImpl.vue | 70 ++++-- .../CodeEditor/CodeEditorTooltip.vue | 47 ++++ .../components/CodeEditor/diagnostics.ts | 125 +++------- .../components/CodeEditor/ensoSyntax.ts | 162 ++++++++----- .../components/CodeEditor/sync.ts | 20 +- .../components/CodeEditor/tooltips.ts | 95 +++----- .../__tests__/widgetFunctionCallInfo.test.ts | 34 +-- .../GraphEditor/widgets/WidgetHierarchy.vue | 2 +- .../GraphEditor/widgets/WidgetToken.vue | 2 +- .../graph/__tests__/graphDatabase.test.ts | 26 +- .../util/ast/__tests__/aliasAnalysis.test.ts | 33 +-- app/gui/src/project-view/util/ast/abstract.ts | 2 +- .../project-view/util/ast/aliasAnalysis.ts | 17 +- app/gui/src/project-view/util/ast/bindings.ts | 12 +- app/gui/src/project-view/util/ast/extended.ts | 222 ------------------ app/gui/src/project-view/util/ast/raw.ts | 33 +-- .../src/project-view/util/codemirror/index.ts | 4 +- .../src/project-view/util/codemirror/text.ts | 20 ++ app/ydoc-server/src/serialization.ts | 9 +- .../src/__tests__/yjsModel.test.ts | 54 ----- app/ydoc-shared/src/ast/idMap.ts | 24 +- app/ydoc-shared/src/ast/mutableModule.ts | 36 ++- app/ydoc-shared/src/ast/repair.ts | 15 +- app/ydoc-shared/src/ast/sourceDocument.ts | 31 ++- app/ydoc-shared/src/ast/syncToCode.ts | 23 +- app/ydoc-shared/src/ast/token.ts | 19 +- app/ydoc-shared/src/ast/tree.ts | 27 ++- .../src/util/data/__tests__/text.test.ts | 78 +++++- app/ydoc-shared/src/util/data/text.ts | 116 ++++++--- app/ydoc-shared/src/util/lezer.ts | 11 +- app/ydoc-shared/src/yjsModel.ts | 44 +--- pnpm-lock.yaml | 163 +++++++------ 33 files changed, 751 insertions(+), 837 deletions(-) create mode 100644 app/gui/src/project-view/components/CodeEditor/CodeEditorTooltip.vue delete mode 100644 app/gui/src/project-view/util/ast/extended.ts create mode 100644 app/gui/src/project-view/util/codemirror/text.ts delete mode 100644 app/ydoc-shared/src/__tests__/yjsModel.test.ts diff --git a/app/gui/package.json b/app/gui/package.json index 389e9b83fcd9..fab596327b6e 100644 --- a/app/gui/package.json +++ b/app/gui/package.json @@ -92,13 +92,13 @@ "@ag-grid-enterprise/range-selection": "^32.3.3", "@babel/parser": "^7.24.7", "babel-plugin-react-compiler": "19.0.0-beta-a7bf2bd-20241110", - "@codemirror/commands": "^6.6.0", - "@codemirror/language": "^6.10.2", + "@codemirror/commands": "^6.7.1", + "@codemirror/language": "^6.10.6", "@codemirror/lang-markdown": "^v6.3.0", - "@codemirror/lint": "^6.8.1", - "@codemirror/search": "^6.5.6", - "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.35.0", + "@codemirror/lint": "^6.8.4", + "@codemirror/search": "^6.5.8", + "@codemirror/state": "^6.5.0", + "@codemirror/view": "^6.35.3", "@fast-check/vitest": "^0.0.8", "@floating-ui/vue": "^1.0.6", "@lezer/common": "^1.1.0", diff --git a/app/gui/src/project-view/components/CodeEditor/CodeEditorImpl.vue b/app/gui/src/project-view/components/CodeEditor/CodeEditorImpl.vue index 5279176f20ff..25f3451aafb5 100644 --- a/app/gui/src/project-view/components/CodeEditor/CodeEditorImpl.vue +++ b/app/gui/src/project-view/components/CodeEditor/CodeEditorImpl.vue @@ -4,45 +4,58 @@ import { ensoSyntax } from '@/components/CodeEditor/ensoSyntax' import { useEnsoSourceSync } from '@/components/CodeEditor/sync' import { ensoHoverTooltip } from '@/components/CodeEditor/tooltips' import CodeMirrorRoot from '@/components/CodeMirrorRoot.vue' +import VueComponentHost from '@/components/VueComponentHost.vue' import { useGraphStore } from '@/stores/graph' import { useProjectStore } from '@/stores/project' import { useSuggestionDbStore } from '@/stores/suggestionDatabase' import { useAutoBlur } from '@/util/autoBlur' import { useCodeMirror } from '@/util/codemirror' +import { highlightStyle } from '@/util/codemirror/highlight' import { testSupport } from '@/util/codemirror/testSupport' -import { indentWithTab } from '@codemirror/commands' -import { - bracketMatching, - defaultHighlightStyle, - foldGutter, - syntaxHighlighting, -} from '@codemirror/language' +import { indentWithTab, insertNewlineKeepIndent } from '@codemirror/commands' +import { bracketMatching, foldGutter } from '@codemirror/language' import { lintGutter } from '@codemirror/lint' import { highlightSelectionMatches } from '@codemirror/search' import { keymap } from '@codemirror/view' -import { type Highlighter } from '@lezer/highlight' import { minimalSetup } from 'codemirror' -import { computed, onMounted, useTemplateRef, type ComponentInstance } from 'vue' +import { + computed, + onMounted, + toRef, + useCssModule, + useTemplateRef, + type ComponentInstance, +} from 'vue' const projectStore = useProjectStore() const graphStore = useGraphStore() const suggestionDbStore = useSuggestionDbStore() + +const vueComponentHost = + useTemplateRef>('vueComponentHost') const editorRoot = useTemplateRef>('editorRoot') const rootElement = computed(() => editorRoot.value?.rootElement) useAutoBlur(rootElement) +const autoindentOnEnter = { + key: 'Enter', + run: insertNewlineKeepIndent, +} + +const vueHost = computed(() => vueComponentHost.value || undefined) const { editorView, setExtraExtensions } = useCodeMirror(editorRoot, { extensions: [ + keymap.of([indentWithTab, autoindentOnEnter]), minimalSetup, - syntaxHighlighting(defaultHighlightStyle as Highlighter), bracketMatching(), foldGutter(), lintGutter(), highlightSelectionMatches(), - ensoSyntax(), - ensoHoverTooltip(graphStore, suggestionDbStore), - keymap.of([indentWithTab]), + ensoSyntax(toRef(graphStore, 'moduleRoot')), + highlightStyle(useCssModule()), + ensoHoverTooltip(graphStore, suggestionDbStore, vueHost), ], + vueHost, }) ;(window as any).__codeEditorApi = testSupport(editorView) const { updateListener, connectModuleListener } = useEnsoSourceSync( @@ -61,6 +74,7 @@ onMounted(() => { + + + diff --git a/app/gui/src/project-view/components/CodeEditor/CodeEditorTooltip.vue b/app/gui/src/project-view/components/CodeEditor/CodeEditorTooltip.vue new file mode 100644 index 000000000000..3b1e79c7593e --- /dev/null +++ b/app/gui/src/project-view/components/CodeEditor/CodeEditorTooltip.vue @@ -0,0 +1,47 @@ + + + diff --git a/app/gui/src/project-view/components/CodeEditor/diagnostics.ts b/app/gui/src/project-view/components/CodeEditor/diagnostics.ts index 829daebac30c..684a00102864 100644 --- a/app/gui/src/project-view/components/CodeEditor/diagnostics.ts +++ b/app/gui/src/project-view/components/CodeEditor/diagnostics.ts @@ -1,74 +1,20 @@ import { type GraphStore } from '@/stores/graph' import { type ProjectStore } from '@/stores/project' +import { valueExt } from '@/util/codemirror/stateEffect' import { type Diagnostic, forceLinting, linter } from '@codemirror/lint' -import { type Extension, StateEffect, StateField } from '@codemirror/state' +import { type Extension } from '@codemirror/state' import { type EditorView } from '@codemirror/view' import * as iter from 'enso-common/src/utilities/data/iter' -import { computed, watch } from 'vue' -import { type Diagnostic as LSDiagnostic, type Position } from 'ydoc-shared/languageServerTypes' +import { computed, watchEffect } from 'vue' +import { type SourceRange } from 'ydoc-shared/util/data/text' +import { type ExternalId } from 'ydoc-shared/yjsModel' -// Effect that can be applied to the document to invalidate the linter state. -const diagnosticsUpdated = StateEffect.define() -// State value that is perturbed by any `diagnosticsUpdated` effect. -const diagnosticsVersion = StateField.define({ - create: (_state) => 0, - update: (value, transaction) => { - for (const effect of transaction.effects) { - if (effect.is(diagnosticsUpdated)) value += 1 - } - return value - }, -}) - -/** Given a text, indexes it and returns a function for converting between different ways of identifying positions. */ -function stringPosConverter(text: string) { - let pos = 0 - const lineStartIndex: number[] = [] - for (const line of text.split('\n')) { - lineStartIndex.push(pos) - pos += line.length + 1 - } - const length = text.length - - function lineColToIndex({ - line, - character, - }: { - line: number - character: number - }): number | undefined { - const startIx = lineStartIndex[line] - if (startIx == null) return - const ix = startIx + character - if (ix > length) return - return ix - } - - return { lineColToIndex } -} - -/** Convert the Language Server's diagnostics to CodeMirror diagnostics. */ -function lsDiagnosticsToCMDiagnostics( - diagnostics: LSDiagnostic[], - lineColToIndex: (lineCol: Position) => number | undefined, -) { - const results: Diagnostic[] = [] - for (const diagnostic of diagnostics) { - if (!diagnostic.location) continue - const from = lineColToIndex(diagnostic.location.start) - const to = lineColToIndex(diagnostic.location.end) - if (to == null || from == null) { - // Suppress temporary errors if the source is not the version of the document the LS is reporting diagnostics for. - continue - } - const severity = - diagnostic.kind === 'Error' ? 'error' - : diagnostic.kind === 'Warning' ? 'warning' - : 'info' - results.push({ from, to, message: diagnostic.message, severity }) - } - return results -} +const { + set: setDiagnostics, + get: getDiagnostics, + changed: diagnosticsChanged, + extension: stateExt, +} = valueExt(undefined) /** * CodeMirror extension providing diagnostics for an Enso module. Provides CodeMirror diagnostics based on dataflow @@ -79,6 +25,10 @@ export function useEnsoDiagnostics( graphStore: Pick, editorView: EditorView, ): Extension { + function spanOfExternalId(externalId: ExternalId): SourceRange | undefined { + const astId = graphStore.db.idFromExternal(externalId) + return astId && graphStore.moduleSource.getSpan(astId) + } const expressionUpdatesDiagnostics = computed(() => { const updates = projectStore.computedValueRegistry.db const panics = updates.type.reverseLookup('Panic') @@ -87,11 +37,9 @@ export function useEnsoDiagnostics( for (const externalId of iter.chain(panics, errors)) { const update = updates.get(externalId) if (!update) continue - const astId = graphStore.db.idFromExternal(externalId) - if (!astId) continue - const span = graphStore.moduleSource.getSpan(astId) + const span = spanOfExternalId(externalId) if (!span) continue - const [from, to] = span + const { from, to } = span switch (update.payload.type) { case 'Panic': { diagnostics.push({ from, to, message: update.payload.message, severity: 'error' }) @@ -108,27 +56,30 @@ export function useEnsoDiagnostics( } return diagnostics }) - // The LS protocol doesn't identify what version of the file updates are in reference to. When diagnostics are - // received from the LS, we map them to the text assuming that they are applicable to the current version of the - // module. This will be correct if there is no one else editing, and we aren't editing faster than the LS can send - // updates. Typing too quickly can result in incorrect ranges, but at idle it should correct itself when we receive - // new diagnostics. - const executionContextDiagnostics = computed(() => { - const { lineColToIndex } = stringPosConverter(graphStore.moduleSource.text) - return lsDiagnosticsToCMDiagnostics(projectStore.diagnostics, lineColToIndex) - }) - watch([executionContextDiagnostics, expressionUpdatesDiagnostics], () => { - editorView.dispatch({ effects: diagnosticsUpdated.of(null) }) + const executionContextDiagnostics = computed(() => + projectStore.diagnostics.flatMap((diagnostic) => { + const span = diagnostic.expressionId && spanOfExternalId(diagnostic.expressionId) + if (!span) return [] + const { from, to } = span + const severity = + diagnostic.kind === 'Error' ? 'error' + : diagnostic.kind === 'Warning' ? 'warning' + : 'info' + return [{ from, to, message: diagnostic.message, severity }] + }), + ) + watchEffect(() => { + const diagnostics = [ + ...expressionUpdatesDiagnostics.value, + ...executionContextDiagnostics.value, + ] + editorView.dispatch({ effects: setDiagnostics.of(diagnostics) }) forceLinting(editorView) }) return [ - diagnosticsVersion, - linter(() => [...executionContextDiagnostics.value, ...expressionUpdatesDiagnostics.value], { - needsRefresh(update) { - return ( - update.state.field(diagnosticsVersion) !== update.startState.field(diagnosticsVersion) - ) - }, + stateExt, + linter((view) => view.state.facet(getDiagnostics) ?? [], { + needsRefresh: diagnosticsChanged, }), ] } diff --git a/app/gui/src/project-view/components/CodeEditor/ensoSyntax.ts b/app/gui/src/project-view/components/CodeEditor/ensoSyntax.ts index 7f2dfb62668e..42f3a826fcf0 100644 --- a/app/gui/src/project-view/components/CodeEditor/ensoSyntax.ts +++ b/app/gui/src/project-view/components/CodeEditor/ensoSyntax.ts @@ -1,12 +1,13 @@ -import { RawAstExtended } from '@/util/ast/extended' -import { RawAst } from '@/util/ast/raw' +import { Ast } from '@/util/ast' import { defineLanguageFacet, foldNodeProp, + indentUnit, Language, languageDataProp, LanguageSupport, } from '@codemirror/language' +import { type Extension } from '@codemirror/state' import { type Input, NodeProp, @@ -17,73 +18,117 @@ import { Tree, } from '@lezer/common' import { styleTags, tags } from '@lezer/highlight' -import * as iter from 'enso-common/src/utilities/data/iter' +import { type Ref } from 'vue' +import { spanMapToSpanGetter, tokenSpanGetter } from 'ydoc-shared/ast/idMap' +import { assertDefined } from 'ydoc-shared/util/assert' +import { rangeLength, type SourceRange } from 'ydoc-shared/util/data/text' -const nodeTypes: NodeType[] = [ - ...RawAst.Tree.typeNames.map((name, id) => NodeType.define({ id, name })), - ...RawAst.Token.typeNames.map((name, id) => - NodeType.define({ id: id + RawAst.Tree.typeNames.length, name: 'Token' + name }), - ), -] +const treeTypeNames = Ast.astTypes +const tokenTypeNames = Ast.tokenTypes.map((name) => `Token${name}`) +const nodeTypes: NodeType[] = [...treeTypeNames, ...tokenTypeNames].map((name, id) => + NodeType.define({ id, name }), +) const nodeSet = new NodeSet(nodeTypes).extend( styleTags({ Ident: tags.variableName, - 'Private!': tags.variableName, - Number: tags.number, - 'Wildcard!': tags.variableName, + Wildcard: tags.variableName, + TokenIdent: tags.name, + 'PropertyAccess/TokenIdent': tags.propertyName, + 'NumericLiteral!': tags.number, + 'FunctionDef/Ident': tags.definition(tags.function(tags.variableName)), + 'Assignment/Ident': tags.definition(tags.variableName), + 'Import/TokenIdent': tags.moduleKeyword, + // Strings and comments 'TextLiteral!': tags.string, - OprApp: tags.operator, + TokenTextEscape: tags.escape, + TokenTextStart: tags.docComment, + TokenTextSection: tags.docComment, + TokenNewline: tags.lineComment, + TokenInvalid: tags.invalid, + // Open/close tokens + 'Group/TokenOpenSymbol': tags.paren, + 'Group/TokenCloseSymbol': tags.paren, + 'Vector/TokenOpenSymbol': tags.squareBracket, + 'Vector/TokenCloseSymbol': tags.squareBracket, + // Operator tokens TokenOperator: tags.operator, - 'Assignment/TokenOperator': tags.definitionOperator, - UnaryOprApp: tags.operator, - 'Function/Ident': tags.function(tags.variableName), - ForeignFunction: tags.function(tags.variableName), - 'Import/TokenIdent': tags.function(tags.moduleKeyword), - Export: tags.function(tags.moduleKeyword), - Lambda: tags.function(tags.variableName), - Documented: tags.docComment, - ConstructorDefinition: tags.function(tags.variableName), + TokenDotOperator: tags.operator, + TokenCommaOperator: tags.separator, + TokenUnaryOperator: tags.operator, + TokenAnnotationOperator: tags.operator, + TokenAutoscopeOperator: tags.operator, + TokenLambdaOperator: tags.function(tags.controlOperator), + TokenSuspendedDefaultArguments: tags.controlOperator, + TokenSuspensionOperator: tags.controlOperator, + TokenAssignmentOperator: tags.definitionOperator, + TokenTypeAnnotationOperator: tags.typeOperator, + TokenArrowOperator: tags.typeOperator, + TokenNegationOperator: tags.number, + // Keyword tokens + TokenAllKeyword: tags.moduleKeyword, + TokenCaseKeyword: tags.controlKeyword, + TokenOfKeyword: tags.controlKeyword, + TokenPrivateKeyword: tags.modifier, + TokenTypeKeyword: tags.definitionKeyword, + TokenForeignKeyword: tags.modifier, }), foldNodeProp.add({ - Function: (node) => node.lastChild, - ArgumentBlockApplication: (node) => node, - OperatorBlockApplication: (node) => node, + BodyBlock: (node) => (node.from === 0 ? null : node), }), ) +const typeByName = new Map(nodeSet.types.map((type) => [type.name, type])) -export type AstNode = RawAstExtended +export type AstNode = Ast.Ast | Ast.Token export const astProp = new NodeProp({ perNode: true }) function astToCodeMirrorTree( - nodeSet: NodeSet, - ast: AstNode, + ast: Ast.Ast, + getSpan: (id: Ast.AstId) => SourceRange | undefined, + getTokenSpan: (token: Ast.Token) => SourceRange | undefined, props?: readonly [number | NodeProp, any][] | undefined, ): Tree { - const [start, end] = ast.span() - const children = ast.children() - - const childrenToConvert = iter.tryGetSoleValue(children)?.isToken() ? [] : children + const nodeType = typeByName.get(ast.typeName) + assertDefined(nodeType) + const children = new Array() + const childrenPositions = new Array() + const { from, to } = getSpan(ast.id)! + for (const child of ast.children()) { + if (child instanceof Ast.Ast) { + children.push(astToCodeMirrorTree(child, getSpan, getTokenSpan)) + childrenPositions.push(getSpan(child.id)!.from - from) + } else { + if (child.code().length === 0) continue + const childSpan = getTokenSpan(child) + assertDefined(childSpan) + const tokenTree = tokenToCodeMirrorTree(child, childSpan) + if (tokenTree) { + children.push(tokenTree) + childrenPositions.push(childSpan.from - from) + } + } + } + return new Tree(nodeType, children, childrenPositions, to - from, [ + ...(props ?? []), + [astProp, ast], + ]) +} - return new Tree( - nodeSet.types[ast.inner.type + (ast.isToken() ? RawAst.Tree.typeNames.length : 0)]!, - childrenToConvert.map((child) => astToCodeMirrorTree(nodeSet, child)), - childrenToConvert.map((child) => child.span()[0] - start), - end - start, - [...(props ?? []), [astProp, ast]], - ) +function tokenToCodeMirrorTree(token: Ast.Token, span: SourceRange): Tree | undefined { + if (token.typeName === 'Raw') return + const type = typeByName.get(`Token${token.typeName}`) + assertDefined(type) + return new Tree(type, [], [], rangeLength(span), [[astProp, token]]) } const facet = defineLanguageFacet() class EnsoParser extends Parser { - nodeSet - constructor() { + private cachedCode: string | undefined + private cachedTree: Tree | undefined + constructor(private readonly moduleRoot: Readonly>) { super() - this.nodeSet = nodeSet } - cachedCode: string | undefined - cachedTree: Tree | undefined createParse(input: Input): PartialParse { return { parsedPos: input.length, @@ -93,8 +138,19 @@ class EnsoParser extends Parser { const code = input.read(0, input.length) if (code !== this.cachedCode || this.cachedTree == null) { this.cachedCode = code - const ast = RawAstExtended.parse(code) - this.cachedTree = astToCodeMirrorTree(this.nodeSet, ast, [[languageDataProp, facet]]) + assertDefined(this.moduleRoot.value) + const root = Ast.copyIntoNewModule(this.moduleRoot.value) + const tempModule = root.module + root.module.setRoot(root) + root.syncToCode(code) + const parsedRoot = tempModule.root() + assertDefined(parsedRoot) + const { info: spans } = Ast.printWithSpans(parsedRoot) + const getSpan = spanMapToSpanGetter(spans.nodes) + const getTokenSpan = tokenSpanGetter(spans.tokens) + this.cachedTree = astToCodeMirrorTree(parsedRoot, getSpan, getTokenSpan, [ + [languageDataProp, facet], + ]) } return this.cachedTree }, @@ -102,15 +158,9 @@ class EnsoParser extends Parser { } } -class EnsoLanguage extends Language { - constructor() { - super(facet, new EnsoParser()) - } -} - -const ensoLanguage = new EnsoLanguage() - /** TODO: Add docs */ -export function ensoSyntax() { - return new LanguageSupport(ensoLanguage) +export function ensoSyntax(moduleRoot: Readonly>): Extension { + return new LanguageSupport(new Language(facet, new EnsoParser(moduleRoot)), [ + indentUnit.of(' '), + ]) } diff --git a/app/gui/src/project-view/components/CodeEditor/sync.ts b/app/gui/src/project-view/components/CodeEditor/sync.ts index 0a72cba7daed..a5b3f11cd766 100644 --- a/app/gui/src/project-view/components/CodeEditor/sync.ts +++ b/app/gui/src/project-view/components/CodeEditor/sync.ts @@ -1,10 +1,10 @@ import { type GraphStore } from '@/stores/graph' import { type ProjectStore } from '@/stores/project' -import { useToast } from '@/util/toast.ts' +import { changeSetToTextEdits } from '@/util/codemirror/text' +import { useToast } from '@/util/toast' import { Annotation, ChangeSet, - type ChangeSpec, type EditorSelection, type Extension, type Text, @@ -16,18 +16,6 @@ import { MutableModule } from 'ydoc-shared/ast' import { SourceRangeEdit, textChangeToEdits } from 'ydoc-shared/util/data/text' import { type Origin } from 'ydoc-shared/yjsModel' -function changeSetToTextEdits(changes: ChangeSet) { - const textEdits = new Array() - changes.iterChanges((from, to, _fromB, _toB, insert) => - textEdits.push({ range: [from, to], insert: insert.toString() }), - ) - return textEdits -} - -function textEditToChangeSpec({ range: [from, to], insert }: SourceRangeEdit): ChangeSpec { - return { from, to, insert } -} - // Indicates a change updating the text to correspond to the given module state. const synchronizedModule = Annotation.define() @@ -78,7 +66,7 @@ export function useEnsoSourceSync( currentModule = undefined const viewText = editorView.state.doc.toString() const code = graphStore.moduleSource.text - const changes = textChangeToEdits(viewText, code).map(textEditToChangeSpec) + const changes = textChangeToEdits(viewText, code) console.info('Resetting the editor to the module code.', changes) editorView.dispatch({ changes, @@ -139,7 +127,7 @@ export function useEnsoSourceSync( // If none of the above exit-conditions were reached, the transaction is applicable to our current state. editorView.dispatch({ - changes: textEdits.map(textEditToChangeSpec), + changes: textEdits, annotations: synchronizedModule.of(graphStore.startEdit()), }) } diff --git a/app/gui/src/project-view/components/CodeEditor/tooltips.ts b/app/gui/src/project-view/components/CodeEditor/tooltips.ts index 964beac221ce..1f69dfa026a1 100644 --- a/app/gui/src/project-view/components/CodeEditor/tooltips.ts +++ b/app/gui/src/project-view/components/CodeEditor/tooltips.ts @@ -1,7 +1,10 @@ -import { type AstNode, astProp } from '@/components/CodeEditor/ensoSyntax' -import { type GraphStore, type NodeId } from '@/stores/graph' +import CodeEditorTooltip from '@/components/CodeEditor/CodeEditorTooltip.vue' +import { astProp } from '@/components/CodeEditor/ensoSyntax' +import { type VueHost } from '@/components/VueComponentHost.vue' +import { type GraphStore } from '@/stores/graph' import { type SuggestionDbStore } from '@/stores/suggestionDatabase' -import { qnJoin, tryQualifiedName } from '@/util/qualifiedName' +import { Ast } from '@/util/ast' +import { type ToValue } from '@/util/reactivity' import { syntaxTree } from '@codemirror/language' import { type Extension } from '@codemirror/state' import { @@ -11,13 +14,13 @@ import { type TooltipView, } from '@codemirror/view' import { type SyntaxNode } from '@lezer/common' -import { unwrap } from 'ydoc-shared/util/data/result' -import { rangeEncloses } from 'ydoc-shared/yjsModel' +import * as iter from 'enso-common/src/utilities/data/iter' +import { h, markRaw, toValue } from 'vue' +import { syntaxNodeAncestors } from 'ydoc-shared/util/lezer' /** TODO: Add docs */ function hoverTooltip( create: ( - ast: AstNode, syntax: SyntaxNode, ) => TooltipView | ((view: EditorView) => TooltipView) | null | undefined, ): Extension { @@ -25,9 +28,7 @@ function hoverTooltip( tooltips({ position: 'absolute' }), originalHoverTooltip((view, pos, side) => { const syntaxNode = syntaxTree(view.state).resolveInner(pos, side) - const astNode = syntaxNode.tree?.prop(astProp) - if (astNode == null) return null - const domOrCreate = create(astNode, syntaxNode) + const domOrCreate = create(syntaxNode) if (domOrCreate == null) return null return { @@ -41,62 +42,34 @@ function hoverTooltip( ] } +function codeEditorTooltip(vueHost: VueHost, props: typeof CodeEditorTooltip.props): TooltipView { + const dom = markRaw(document.createElement('div')) + dom.classList.add('CodeEditorTooltip') + const vueHostRegistration = vueHost.register(h(CodeEditorTooltip, props), dom) + return { dom, destroy: vueHostRegistration.unregister } +} + /** @returns A CodeMirror extension that creates tooltips containing type and syntax information for Enso code. */ export function ensoHoverTooltip( graphStore: Pick, - suggestionDbStore: Pick, + suggestionDbStore: SuggestionDbStore, + vueHost: ToValue, ) { - return hoverTooltip((ast, syn) => { - const dom = document.createElement('div') - const astSpan = ast.span() - let foundNode: NodeId | undefined - for (const [id, node] of graphStore.db.nodeIdToNode.entries()) { - const rootSpan = graphStore.moduleSource.getSpan(node.rootExpr.id) - if (rootSpan && rangeEncloses(rootSpan, astSpan)) { - foundNode = id - break - } - } - const expressionInfo = foundNode && graphStore.db.getExpressionInfo(foundNode) - const nodeColor = foundNode && graphStore.db.getNodeColorStyle(foundNode) - - if (foundNode != null) { - dom - .appendChild(document.createElement('div')) - .appendChild(document.createTextNode(`AST ID: ${foundNode}`)) - } - if (expressionInfo != null) { - dom - .appendChild(document.createElement('div')) - .appendChild(document.createTextNode(`Type: ${expressionInfo.typename ?? 'Unknown'}`)) - } - if (expressionInfo?.profilingInfo[0] != null) { - const profile = expressionInfo.profilingInfo[0] - const executionTime = (profile.ExecutionTime.nanoTime / 1_000_000).toFixed(3) - const text = `Execution Time: ${executionTime}ms` - dom.appendChild(document.createElement('div')).appendChild(document.createTextNode(text)) - } - - dom - .appendChild(document.createElement('div')) - .appendChild(document.createTextNode(`Syntax: ${syn.toString()}`)) - const method = expressionInfo?.methodCall?.methodPointer - if (method != null) { - const moduleName = tryQualifiedName(method.module) - const methodName = tryQualifiedName(method.name) - const qualifiedName = qnJoin(unwrap(moduleName), unwrap(methodName)) - const [id] = suggestionDbStore.entries.nameToId.lookup(qualifiedName) - const suggestionEntry = id != null ? suggestionDbStore.entries.get(id) : undefined - if (suggestionEntry != null) { - const groupNode = dom.appendChild(document.createElement('div')) - groupNode.appendChild(document.createTextNode('Group: ')) - const groupNameNode = groupNode.appendChild(document.createElement('span')) - groupNameNode.appendChild(document.createTextNode(`${method.module}.${method.name}`)) - if (nodeColor) { - groupNameNode.style.color = nodeColor - } - } + return hoverTooltip((syn) => { + const vueHostValue = toValue(vueHost) + if (!vueHostValue) { + console.error('Cannot render tooltip without Vue host.') + return } - return { dom } + const enclosingAstNodes = iter.map(syntaxNodeAncestors(syn), (syn) => syn.tree?.prop(astProp)) + const enclosingAsts = iter.filter(enclosingAstNodes, (node) => node instanceof Ast.Ast) + const enclosingExternalIds = iter.map(enclosingAsts, ({ externalId }) => externalId) + const nodeId = iter.find(enclosingExternalIds, graphStore.db.isNodeId.bind(graphStore.db)) + return codeEditorTooltip(vueHostValue, { + nodeId, + syntax: syn.name, + graphDb: graphStore.db, + suggestionDbStore: suggestionDbStore, + }) }) } diff --git a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetFunction/__tests__/widgetFunctionCallInfo.test.ts b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetFunction/__tests__/widgetFunctionCallInfo.test.ts index 8db2ed69c54b..95584d69df8f 100644 --- a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetFunction/__tests__/widgetFunctionCallInfo.test.ts +++ b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetFunction/__tests__/widgetFunctionCallInfo.test.ts @@ -9,6 +9,7 @@ import { makeStaticMethod, } from '@/stores/suggestionDatabase/entry' import { assert } from '@/util/assert' +import { Ast } from '@/util/ast' import { expect, test } from 'vitest' import { ref, type Ref } from 'vue' import type { Opt } from 'ydoc-shared/util/data/opt' @@ -40,28 +41,29 @@ const staticMethod = { } test.each` - code | callSuggestion | subjectSpan | attachedSpan | subjectType | methodName - ${'val1.method val2'} | ${method} | ${[0, 4]} | ${[0, 4]} | ${'local.Project.Type'} | ${'.method'} - ${'local.Project.Type.method val1 val2'} | ${method} | ${[0, 18]} | ${[26, 30]} | ${'local.Project.Type.type'} | ${'.method'} - ${'Type.method val1'} | ${method} | ${[0, 4]} | ${[12, 16]} | ${'local.Project.Type.type'} | ${'.method'} - ${'local.Project.Type.method'} | ${method} | ${[0, 18]} | ${null} | ${'local.Project.Type.type'} | ${'.method'} - ${'foo.method'} | ${method} | ${[0, 3]} | ${null} | ${'local.Project.Type.type'} | ${'.method'} - ${'foo.method'} | ${method} | ${[0, 3]} | ${[0, 3]} | ${'local.Project.Type'} | ${'.method'} - ${'local.Project.Type.static_method val1'} | ${staticMethod} | ${[0, 18]} | ${[0, 18]} | ${'local.Project.Type.type'} | ${'.static_method'} - ${'Type.Con val1'} | ${con} | ${[0, 4]} | ${[0, 4]} | ${'local.Project.Type.type'} | ${'.Con'} - ${'..Con val1'} | ${con} | ${null} | ${null} | ${null} | ${'.Con'} - ${'local.Project.module_method val1'} | ${moduleMethod} | ${[0, 13]} | ${[0, 13]} | ${'local.Project'} | ${'.module_method'} + code | callSuggestion | subjectSpan | attachedSpan | subjectType | methodName + ${'val1.method val2'} | ${method} | ${{ from: 0, to: 4 }} | ${{ from: 0, to: 4 }} | ${'local.Project.Type'} | ${'.method'} + ${'local.Project.Type.method val1 val2'} | ${method} | ${{ from: 0, to: 18 }} | ${{ from: 26, to: 30 }} | ${'local.Project.Type.type'} | ${'.method'} + ${'Type.method val1'} | ${method} | ${{ from: 0, to: 4 }} | ${{ from: 12, to: 16 }} | ${'local.Project.Type.type'} | ${'.method'} + ${'local.Project.Type.method'} | ${method} | ${{ from: 0, to: 18 }} | ${null} | ${'local.Project.Type.type'} | ${'.method'} + ${'foo.method'} | ${method} | ${{ from: 0, to: 3 }} | ${null} | ${'local.Project.Type.type'} | ${'.method'} + ${'foo.method'} | ${method} | ${{ from: 0, to: 3 }} | ${{ from: 0, to: 3 }} | ${'local.Project.Type'} | ${'.method'} + ${'local.Project.Type.static_method val1'} | ${staticMethod} | ${{ from: 0, to: 18 }} | ${{ from: 0, to: 18 }} | ${'local.Project.Type.type'} | ${'.static_method'} + ${'Type.Con val1'} | ${con} | ${{ from: 0, to: 4 }} | ${{ from: 0, to: 4 }} | ${'local.Project.Type.type'} | ${'.Con'} + ${'..Con val1'} | ${con} | ${null} | ${null} | ${null} | ${'.Con'} + ${'local.Project.module_method val1'} | ${moduleMethod} | ${{ from: 0, to: 13 }} | ${{ from: 0, to: 13 }} | ${'local.Project'} | ${'.module_method'} `( 'Visualization config for $code', ({ code, callSuggestion, subjectSpan, attachedSpan, subjectType, methodName }) => { const spans = { - entireFunction: [0, code.length] as [number, number], - ...(subjectSpan != null ? { subject: subjectSpan as [number, number] } : {}), - ...(attachedSpan != null ? { attached: attachedSpan as [number, number] } : {}), + entireFunction: { from: 0, to: code.length }, + ...(subjectSpan != null ? { subject: subjectSpan } : {}), + ...(attachedSpan != null ? { attached: attachedSpan } : {}), } const { ast, eid, id } = parseWithSpans(code, spans) - const node = (ast.lines[0]?.statement?.node as Ast.ExpressionStatement).expression - assert(node != null) + const statement = ast.lines[0]?.statement?.node + assert(statement instanceof Ast.ExpressionStatement) + const node = statement.expression expect(node.externalId).toBe(eid('entireFunction')) let visConfig: Ref> | undefined diff --git a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetHierarchy.vue b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetHierarchy.vue index acd2e8f5e2fc..5491750257ff 100644 --- a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetHierarchy.vue +++ b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetHierarchy.vue @@ -7,7 +7,7 @@ import { isToken } from 'ydoc-shared/ast' const props = defineProps(widgetProps(widgetDefinition)) -const spanClass = computed(() => props.input.value.typeName()) +const spanClass = computed(() => props.input.value.typeName) function* expressionChildren(expression: Ast.Expression) { for (const child of expression.children()) { diff --git a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetToken.vue b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetToken.vue index 810a52392c95..3818c9c1fa25 100644 --- a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetToken.vue +++ b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetToken.vue @@ -4,7 +4,7 @@ import { computed } from 'vue' const props = defineProps(widgetProps(widgetDefinition)) -const spanClass = computed(() => props.input.value.typeName()) +const spanClass = computed(() => props.input.value.typeName) const repr = computed(() => props.input.value.code()) diff --git a/app/gui/src/project-view/stores/graph/__tests__/graphDatabase.test.ts b/app/gui/src/project-view/stores/graph/__tests__/graphDatabase.test.ts index 0d0792a8519c..d88f17c50751 100644 --- a/app/gui/src/project-view/stores/graph/__tests__/graphDatabase.test.ts +++ b/app/gui/src/project-view/stores/graph/__tests__/graphDatabase.test.ts @@ -41,19 +41,19 @@ test('Reading graph from definition', () => { node3 = node2 + 1 node3` const spans = { - functionName: [0, 8] as [number, number], - parameter: [9, 10] as [number, number], - node1Id: [17, 22] as [number, number], - node1Content: [25, 30] as [number, number], - node1LParam: [25, 26] as [number, number], - node1RParam: [29, 30] as [number, number], - node2Id: [35, 40] as [number, number], - node2Content: [43, 52] as [number, number], - node2LParam: [43, 48] as [number, number], - node2RParam: [51, 52] as [number, number], - node3Id: [57, 62] as [number, number], - node3Content: [65, 74] as [number, number], - output: [79, 84] as [number, number], + functionName: { from: 0, to: 8 }, + parameter: { from: 9, to: 10 }, + node1Id: { from: 17, to: 22 }, + node1Content: { from: 25, to: 30 }, + node1LParam: { from: 25, to: 26 }, + node1RParam: { from: 29, to: 30 }, + node2Id: { from: 35, to: 40 }, + node2Content: { from: 43, to: 52 }, + node2LParam: { from: 43, to: 48 }, + node2RParam: { from: 51, to: 52 }, + node3Id: { from: 57, to: 62 }, + node3Content: { from: 65, to: 74 }, + output: { from: 79, to: 84 }, } const { ast, id, eid, getSpan } = parseWithSpans(code, spans) diff --git a/app/gui/src/project-view/util/ast/__tests__/aliasAnalysis.test.ts b/app/gui/src/project-view/util/ast/__tests__/aliasAnalysis.test.ts index d0a0755da692..fd7b73c03372 100644 --- a/app/gui/src/project-view/util/ast/__tests__/aliasAnalysis.test.ts +++ b/app/gui/src/project-view/util/ast/__tests__/aliasAnalysis.test.ts @@ -29,7 +29,7 @@ import { assertDefined } from '@/util/assert' import { AliasAnalyzer } from '@/util/ast/aliasAnalysis' import { MappedKeyMap, MappedSet } from '@/util/containers' import { expect, test } from 'vitest' -import { sourceRangeKey, type SourceRange } from 'ydoc-shared/yjsModel' +import { sourceRangeKey, type SourceRange } from 'ydoc-shared/util/data/text' /** The type of annotation. */ enum AnnotationType { @@ -86,9 +86,9 @@ function parseAnnotations(annotatedCode: string): { const name = bindingName ?? usageName ?? '' const kind = bindingPrefix != null ? AnnotationType.Binding : AnnotationType.Usage - const start = offset - accumulatedOffset - const end = start + name.length - const range: SourceRange = [start, end] + const from = offset - accumulatedOffset + const to = from + name.length + const range: SourceRange = { from, to } const annotation = new Annotation(kind, id) accumulatedOffset += match.length - name.length @@ -152,8 +152,8 @@ class TestCase { return testCase } - repr(range: SourceRange): string { - return this.code.substring(range[0], range[1]) + repr({ from, to }: SourceRange): string { + return this.code.substring(from, to) } prettyPrint(range: SourceRange): string { @@ -223,22 +223,23 @@ test('Annotations parsing', () => { assertDefined(a, `No annotation found at [${range}].`) expect(a.kind, 'Invalid annotation kind.').toBe(kind) expect(a.id, 'Invalid annotation prefix.').toBe(prefix) - expect(unannotatedCode.substring(range[0], range[1]), 'Invalid annotation identifier.').toBe( - identifier, - ) + expect( + unannotatedCode.substring(range.from, range.to), + 'Invalid annotation identifier.', + ).toBe(identifier) } catch (e) { const message = `Invalid annotation at [${range}]: ${e}` throw new Error(message) } } - validateAnnotation([11, 12], AnnotationType.Binding, 1, 'x') - validateAnnotation([21, 22], AnnotationType.Binding, 2, 'y') - validateAnnotation([35, 36], AnnotationType.Binding, 3, 'x') - validateAnnotation([40, 41], AnnotationType.Usage, 3, 'x') - validateAnnotation([44, 45], AnnotationType.Usage, 2, 'y') - validateAnnotation([54, 55], AnnotationType.Usage, 1, 'x') - validateAnnotation([58, 59], AnnotationType.Usage, 2, 'y') + validateAnnotation({ from: 11, to: 12 }, AnnotationType.Binding, 1, 'x') + validateAnnotation({ from: 21, to: 22 }, AnnotationType.Binding, 2, 'y') + validateAnnotation({ from: 35, to: 36 }, AnnotationType.Binding, 3, 'x') + validateAnnotation({ from: 40, to: 41 }, AnnotationType.Usage, 3, 'x') + validateAnnotation({ from: 44, to: 45 }, AnnotationType.Usage, 2, 'y') + validateAnnotation({ from: 54, to: 55 }, AnnotationType.Usage, 1, 'x') + validateAnnotation({ from: 58, to: 59 }, AnnotationType.Usage, 2, 'y') }) function runTestCase(code: string) { diff --git a/app/gui/src/project-view/util/ast/abstract.ts b/app/gui/src/project-view/util/ast/abstract.ts index ec64613798d8..9dd919ce9b8f 100644 --- a/app/gui/src/project-view/util/ast/abstract.ts +++ b/app/gui/src/project-view/util/ast/abstract.ts @@ -348,7 +348,7 @@ export function parseUpdatingIdMap( if (idMap) setExternalIds(root.module, spans, idMap) return { root, spans } }) - const getSpan = spanMapToSpanGetter(spans) + const getSpan = spanMapToSpanGetter(spans.nodes) const idMapOut = spanMapToIdMap(spans) return { root, idMap: idMapOut, getSpan } } diff --git a/app/gui/src/project-view/util/ast/aliasAnalysis.ts b/app/gui/src/project-view/util/ast/aliasAnalysis.ts index 0ab8e0bc8b0f..06c029fb100b 100644 --- a/app/gui/src/project-view/util/ast/aliasAnalysis.ts +++ b/app/gui/src/project-view/util/ast/aliasAnalysis.ts @@ -8,7 +8,7 @@ import { } from '@/util/ast/raw' import { MappedKeyMap, MappedSet, NonEmptyStack } from '@/util/containers' import { LazyObject } from 'ydoc-shared/ast/parserSupport' -import { rangeIsBefore, sourceRangeKey, type SourceRange } from 'ydoc-shared/yjsModel' +import { rangeIsBefore, sourceRangeKey, type SourceRange } from 'ydoc-shared/util/data/text' const ACCESSOR_OPERATOR = '.' @@ -306,13 +306,14 @@ export class AliasAnalyzer { const arrow = caseLine.case?.arrow const expression = caseLine.case?.expression if (pattern) { - const armStart = parsedTreeOrTokenRange(pattern)[0] - const armEnd = - expression ? parsedTreeOrTokenRange(expression)[1] - : arrow ? parsedTreeOrTokenRange(arrow)[1] - : parsedTreeOrTokenRange(pattern)[1] - - const armRange: SourceRange = [armStart, armEnd] + const patternRange = parsedTreeOrTokenRange(pattern) + const armRange: SourceRange = { + from: patternRange.from, + to: (expression ? parsedTreeOrTokenRange(expression) + : arrow ? parsedTreeOrTokenRange(arrow) + : patternRange + ).to, + } this.withNewScopeOver(armRange, () => { this.withContext(Context.Pattern, () => { this.processTree(caseLine.case?.pattern) diff --git a/app/gui/src/project-view/util/ast/bindings.ts b/app/gui/src/project-view/util/ast/bindings.ts index d7c3382ed25e..fee7a318515a 100644 --- a/app/gui/src/project-view/util/ast/bindings.ts +++ b/app/gui/src/project-view/util/ast/bindings.ts @@ -1,11 +1,11 @@ import { Ast, RawAst } from '@/util/ast' import { AliasAnalyzer } from '@/util/ast/aliasAnalysis' -import { visitRecursive } from '@/util/ast/raw' +import { parsedTreeRange, visitRecursive } from '@/util/ast/raw' import { MappedKeyMap, MappedSet } from '@/util/containers' -import type { AstId } from 'ydoc-shared/ast' -import type { SourceDocument } from 'ydoc-shared/ast/sourceDocument' +import { type AstId } from 'ydoc-shared/ast' +import { type SourceDocument } from 'ydoc-shared/ast/sourceDocument' import { assert, assertDefined } from 'ydoc-shared/util/assert' -import { type SourceRange, sourceRangeKey, type SourceRangeKey } from 'ydoc-shared/yjsModel' +import { type SourceRange, sourceRangeKey, type SourceRangeKey } from 'ydoc-shared/util/data/text' /** A variable name, and information about its usages. */ export interface BindingInfo { @@ -21,9 +21,7 @@ export function analyzeBindings( const toRaw = new Map() visitRecursive(Ast.rawParseModule(moduleSource.text), (node) => { if (node.type === RawAst.Tree.Type.Function) { - const start = node.whitespaceStartInCodeParsed + node.whitespaceLengthInCodeParsed - const end = start + node.childrenLengthInCodeParsed - toRaw.set(sourceRangeKey([start, end]), node) + toRaw.set(sourceRangeKey(parsedTreeRange(node)), node) return false } return true diff --git a/app/gui/src/project-view/util/ast/extended.ts b/app/gui/src/project-view/util/ast/extended.ts deleted file mode 100644 index 623f8190f196..000000000000 --- a/app/gui/src/project-view/util/ast/extended.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { assert, assertDefined } from '@/util/assert' -import { - childrenAstNodesOrTokens, - parsedTreeOrTokenRange, - rawParseModule, - readAstOrTokenSpan, - visitGenerator, - visitRecursive, - walkRecursive, -} from '@/util/ast/raw' -import type { Opt } from '@/util/data/opt' -import * as iter from 'enso-common/src/utilities/data/iter' -import * as encoding from 'lib0/encoding' -import * as sha256 from 'lib0/hash/sha256' -import * as map from 'lib0/map' -import { markRaw } from 'vue' -import * as Ast from 'ydoc-shared/ast/generated/ast' -import { Token, Tree } from 'ydoc-shared/ast/generated/ast' -import type { ExternalId, IdMap, SourceRange } from 'ydoc-shared/yjsModel' - -export { AstExtended as RawAstExtended } - -type ExtractType = - T extends ReadonlyArray ? Extract : Extract - -type OneOrArray = T | readonly T[] - -/** - * AST with additional metadata containing AST IDs and original code reference. Can only be - * constructed by parsing any enso source code string. - */ -class AstExtended { - inner: T - private ctx: AstExtendedCtx - - public static isToken>(type?: T) { - return (obj: unknown): obj is AstExtended, boolean> => - obj instanceof AstExtended && obj.isToken(type) - } - - public static isTree>(type?: T) { - return (obj: unknown): obj is AstExtended, boolean> => - obj instanceof AstExtended && obj.isTree(type) - } - - public static parse(code: string): AstExtended - public static parse(code: string, idMap: IdMap): AstExtended - public static parse(code: string, idMap?: IdMap): AstExtended { - const ast = rawParseModule(code) - if (idMap != null) { - visitRecursive(ast, (node) => { - const range = parsedTreeOrTokenRange(node) - idMap.getOrInsertUniqueId(range) - return true - }) - } - - const ctx = new AstExtendedCtx(code, idMap) - return new AstExtended(ast, ctx) - } - - public static parseLine(code: string): AstExtended { - const block = AstExtended.parse(code) - assert(block.isTree(Tree.Type.BodyBlock)) - return block.map((block) => { - const soleStatement = iter.tryGetSoleValue(block.statements) - assertDefined(soleStatement?.expression) - return soleStatement.expression - }) - } - - isToken>( - type?: T, - ): this is AstExtended, HasIdMap> { - if (!Token.isInstance(this.inner)) return false - if (type == null) return true - if (Array.isArray(type)) return (type as Ast.Token.Type[]).includes(this.inner.type) - return this.inner.type === type - } - - isTree>( - type?: T, - ): this is AstExtended, HasIdMap> { - if (!Tree.isInstance(this.inner)) return false - if (type == null) return true - if (Array.isArray(type)) return (type as Ast.Tree.Type[]).includes(this.inner.type) - return this.inner.type === type - } - - private constructor(tree: T, ctx: AstExtendedCtx) { - markRaw(this) - this.inner = tree - this.ctx = ctx - } - - get astId(): CondType { - if (this.ctx.idMap != null) { - const id = this.ctx.idMap.getIfExist(parsedTreeOrTokenRange(this.inner)) - assert(id != null, 'All AST nodes should have an assigned ID') - return id as CondType - } else { - return undefined as CondType - } - } - - tryMap( - mapper: (t: T) => Opt, - ): AstExtended | undefined { - const mapped = mapper(this.inner) - if (mapped == null) return - return new AstExtended(mapped, this.ctx) - } - - map(mapper: (t: T) => T2): AstExtended { - return new AstExtended(mapper(this.inner), this.ctx) - } - - mapIter( - mapper: (t: T) => Iterable, - ): Iterable> { - return [...mapper(this.inner)].map((m) => new AstExtended(m, this.ctx)) - } - - tryMapIter( - mapper: (t: T) => Iterable>, - ): Iterable | undefined> { - return [...mapper(this.inner)].map((m) => - m != null ? new AstExtended(m, this.ctx) : undefined, - ) - } - - repr() { - return readAstOrTokenSpan(this.inner, this.ctx.parsedCode) - } - - span(): SourceRange { - return parsedTreeOrTokenRange(this.inner) - } - - contentHash() { - return this.ctx.getHash(this) - } - - children(): AstExtended[] { - return childrenAstNodesOrTokens(this.inner).map((child) => new AstExtended(child, this.ctx)) - } - - walkRecursive(): Generator> { - return this.visit(walkRecursive) - } - - whitespaceLength() { - return 'whitespaceLengthInCodeBuffer' in this.inner ? - this.inner.whitespaceLengthInCodeBuffer - : this.inner.whitespaceLengthInCodeParsed - } - - *visit( - visitor: (t: T) => Generator, - ): Generator> { - for (const child of visitor(this.inner)) { - yield new AstExtended(child, this.ctx) - } - } - - /** - * Recursively visit AST nodes in depth-first order. - * @param visitor Callback that is called for each node. If it returns `false`, the children of that - * node will be skipped, and the walk will continue to the next sibling. - */ - visitRecursive(visitor: (t: AstExtended) => boolean) { - visitGenerator(this.walkRecursive(), visitor) - } - - get parsedCode() { - return this.ctx.parsedCode - } -} - -type CondType = - Cond extends true ? T - : Cond extends false ? undefined - : T | undefined - -class AstExtendedCtx { - parsedCode: string - idMap: CondType - contentHashes: Map - - constructor(parsedCode: string, idMap: CondType) { - this.parsedCode = parsedCode - this.idMap = idMap - this.contentHashes = new Map() - } - - static getHashKey(ast: AstExtended) { - return `${ast.isToken() ? 'T.' : ''}${ast.inner.type}.${ast.span()[0]}` - } - - getHash(ast: AstExtended) { - const key = AstExtendedCtx.getHashKey(ast) - return map.setIfUndefined(this.contentHashes, key, () => - sha256.digest( - encoding.encode((encoder) => { - const whitespace = ast.whitespaceLength() - encoding.writeUint32(encoder, whitespace) - if (ast.isToken()) { - encoding.writeUint8(encoder, 0) - encoding.writeUint32(encoder, ast.inner.type) - encoding.writeVarString(encoder, ast.repr()) - } else { - encoding.writeUint8(encoder, 1) - encoding.writeUint32(encoder, ast.inner.type) - for (const child of ast.children()) { - encoding.writeUint8Array(encoder, this.getHash(child)) - } - } - }), - ), - ) - } -} diff --git a/app/gui/src/project-view/util/ast/raw.ts b/app/gui/src/project-view/util/ast/raw.ts index f6197bbbde4b..6c5307e98170 100644 --- a/app/gui/src/project-view/util/ast/raw.ts +++ b/app/gui/src/project-view/util/ast/raw.ts @@ -1,7 +1,7 @@ import * as RawAst from 'ydoc-shared/ast/generated/ast' import { rawParseModule } from 'ydoc-shared/ast/parse' import { LazyObject } from 'ydoc-shared/ast/parserSupport' -import type { SourceRange } from 'ydoc-shared/yjsModel' +import { type SourceRange } from 'ydoc-shared/util/data/text' export { RawAst, rawParseModule } @@ -15,7 +15,7 @@ export type HasAstRange = SourceRange | RawAst.Tree | RawAst.Token */ export function readAstOrTokenSpan(node: RawAst.Tree | RawAst.Token, code: string): string { const range = parsedTreeOrTokenRange(node) - return code.substring(range[0], range[1]) + return code.substring(range.from, range.to) } /** @@ -25,18 +25,7 @@ export function readAstOrTokenSpan(node: RawAst.Tree | RawAst.Token, code: strin */ export function readTokenSpan(token: RawAst.Token, code: string): string { const range = parsedTokenRange(token) - return code.substring(range[0], range[1]) -} - -/** Read direct AST children. */ -export function childrenAstNodes(obj: LazyObject): RawAst.Tree[] { - const children: RawAst.Tree[] = [] - const visitor = (obj: LazyObject) => { - if (RawAst.Tree.isInstance(obj)) children.push(obj) - else if (!RawAst.Token.isInstance(obj)) obj.visitChildren(visitor) - } - obj.visitChildren(visitor) - return children + return code.substring(range.from, range.to) } /** TODO: Add docs */ @@ -90,20 +79,20 @@ export function visitRecursive( /** * Read ast span information in `String.substring` compatible way. The returned span does not * include left whitespace offset. - * @returns Object with `start` and `end` properties; index of first character in the `node` + * @returns Object with `from` and `to` properties; index of first character in the `node` * and first character _not_ being in the `node`. */ -function parsedTreeRange(tree: RawAst.Tree): SourceRange { - const start = tree.whitespaceStartInCodeParsed + tree.whitespaceLengthInCodeParsed - const end = start + tree.childrenLengthInCodeParsed - return [start, end] +export function parsedTreeRange(tree: RawAst.Tree): SourceRange { + const from = tree.whitespaceStartInCodeParsed + tree.whitespaceLengthInCodeParsed + const to = from + tree.childrenLengthInCodeParsed + return { from, to } } /** TODO: Add docs */ function parsedTokenRange(token: RawAst.Token): SourceRange { - const start = token.startInCodeBuffer - const end = start + token.lengthInCodeBuffer - return [start, end] + const from = token.startInCodeBuffer + const to = from + token.lengthInCodeBuffer + return { from, to } } /** TODO: Add docs */ diff --git a/app/gui/src/project-view/util/codemirror/index.ts b/app/gui/src/project-view/util/codemirror/index.ts index ea8f99b40ae7..2a220fd08784 100644 --- a/app/gui/src/project-view/util/codemirror/index.ts +++ b/app/gui/src/project-view/util/codemirror/index.ts @@ -7,7 +7,7 @@ import { setVueHost } from '@/util/codemirror/vueHostExt' import { yCollab } from '@/util/codemirror/yCollab' import { elementHierarchy } from '@/util/dom' import { ToValue } from '@/util/reactivity' -import { Compartment, EditorState, Extension, Text } from '@codemirror/state' +import { Compartment, EditorState, type Extension, Text } from '@codemirror/state' import { EditorView } from '@codemirror/view' import { LINE_BOUNDARIES } from 'enso-common/src/utilities/data/string' import { @@ -40,7 +40,7 @@ export function useCodeMirror( /** If a value is provided, the editor state will be synchronized with it. */ content?: ToValue /** CodeMirror {@link Extension}s to include in the editor's initial state. */ - extensions?: Extension[] + extensions?: Extension /** If a value is provided, it will be made available to extensions that render Vue components. */ vueHost?: WatchSource }, diff --git a/app/gui/src/project-view/util/codemirror/text.ts b/app/gui/src/project-view/util/codemirror/text.ts new file mode 100644 index 000000000000..7bafd28574df --- /dev/null +++ b/app/gui/src/project-view/util/codemirror/text.ts @@ -0,0 +1,20 @@ +import { type ChangeDesc, type ChangeSet } from '@codemirror/state' +import { type SourceRangeEdit, type SourceRangeEditDesc } from 'ydoc-shared/util/data/text' + +/** Collect the changes in a {@link ChangeSet} as {@link SourceRangeEdit}s. */ +export function changeSetToTextEdits(changes: ChangeSet): SourceRangeEdit[] { + const textEdits = new Array() + changes.iterChanges((from, to, _fromB, _toB, insert) => + textEdits.push({ from, to, insert: insert.toString() }), + ) + return textEdits +} + +/** Collect the change descriptions in a {@link ChangeDesc} as {@link SourceRangeEditDesc}s. */ +export function changeDescToSourceRangeEditDesc(changeDesc: ChangeDesc): SourceRangeEditDesc[] { + const textEdits = new Array() + changeDesc.iterChangedRanges((fromA, toA, fromB, toB) => { + textEdits.push({ from: fromA, to: toA, insert: { length: toB - fromB } }) + }) + return textEdits +} diff --git a/app/ydoc-server/src/serialization.ts b/app/ydoc-server/src/serialization.ts index 0cf94c3626a9..eb3d465f0f08 100644 --- a/app/ydoc-server/src/serialization.ts +++ b/app/ydoc-server/src/serialization.ts @@ -1,7 +1,8 @@ /** Translation of `yjsModel` types to and from the `fileFormat` representation. */ import * as json from 'lib0/json' -import { ExternalId, IdMap, sourceRangeFromKey } from 'ydoc-shared/yjsModel' +import { sourceRangeFromKey } from 'ydoc-shared/util/data/text' +import { type ExternalId, IdMap } from 'ydoc-shared/yjsModel' import * as fileFormat from './fileFormat' /** Convert a JSON string to an {@link IdMap}. */ @@ -14,7 +15,7 @@ export function deserializeIdMap(idMapJson: string): IdMap { console.error(`Invalid range for id ${id}:`, range) continue } - idMap.insertKnownId([index.value, index.value + size.value], id as ExternalId) + idMap.insertKnownId({ from: index.value, to: index.value + size.value }, id as ExternalId) } return idMap } @@ -30,8 +31,8 @@ export function idMapToArray(map: IdMap): fileFormat.IdMapEntry[] { const entries: fileFormat.IdMapEntry[] = [] map.entries().forEach(([rangeBuffer, id]) => { const decoded = sourceRangeFromKey(rangeBuffer) - const index = decoded[0] - const endIndex = decoded[1] + const index = decoded.from + const endIndex = decoded.to if (index == null || endIndex == null) return const size = endIndex - index entries.push([{ index: { value: index }, size: { value: size } }, id]) diff --git a/app/ydoc-shared/src/__tests__/yjsModel.test.ts b/app/ydoc-shared/src/__tests__/yjsModel.test.ts deleted file mode 100644 index 7f1170439f20..000000000000 --- a/app/ydoc-shared/src/__tests__/yjsModel.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { expect, test } from 'vitest' -import { rangeEncloses, rangeIntersects, type SourceRange } from '../yjsModel' - -type RangeTest = { a: SourceRange; b: SourceRange } - -const equalRanges: RangeTest[] = [ - { a: [0, 0], b: [0, 0] }, - { a: [0, 1], b: [0, 1] }, - { a: [-5, 5], b: [-5, 5] }, -] - -const totalOverlap: RangeTest[] = [ - { a: [0, 1], b: [0, 0] }, - { a: [0, 2], b: [2, 2] }, - { a: [-1, 1], b: [1, 1] }, - { a: [0, 2], b: [0, 1] }, - { a: [-10, 10], b: [-3, 7] }, - { a: [0, 5], b: [1, 2] }, - { a: [3, 5], b: [3, 4] }, -] - -const reverseTotalOverlap: RangeTest[] = totalOverlap.map(({ a, b }) => ({ a: b, b: a })) - -const noOverlap: RangeTest[] = [ - { a: [0, 1], b: [2, 3] }, - { a: [0, 1], b: [-1, -1] }, - { a: [5, 6], b: [2, 3] }, - { a: [0, 2], b: [-2, -1] }, - { a: [-5, -3], b: [9, 10] }, - { a: [-3, 2], b: [3, 4] }, -] - -const partialOverlap: RangeTest[] = [ - { a: [0, 3], b: [-1, 1] }, - { a: [0, 1], b: [-1, 0] }, - { a: [0, 0], b: [-1, 0] }, - { a: [0, 2], b: [1, 4] }, - { a: [-8, 0], b: [0, 10] }, -] - -test.each([...equalRanges, ...totalOverlap])('Range $a should enclose $b', ({ a, b }) => - expect(rangeEncloses(a, b)).toBe(true), -) -test.each([...noOverlap, ...partialOverlap, ...reverseTotalOverlap])( - 'Range $a should not enclose $b', - ({ a, b }) => expect(rangeEncloses(a, b)).toBe(false), -) -test.each([...equalRanges, ...totalOverlap, ...reverseTotalOverlap, ...partialOverlap])( - 'Range $a should intersect $b', - ({ a, b }) => expect(rangeIntersects(a, b)).toBe(true), -) -test.each([...noOverlap])('Range $a should not intersect $b', ({ a, b }) => - expect(rangeIntersects(a, b)).toBe(false), -) diff --git a/app/ydoc-shared/src/ast/idMap.ts b/app/ydoc-shared/src/ast/idMap.ts index 9caa1437979b..5042da3571e7 100644 --- a/app/ydoc-shared/src/ast/idMap.ts +++ b/app/ydoc-shared/src/ast/idMap.ts @@ -1,13 +1,12 @@ import * as random from 'lib0/random' import { - type ExternalId, type SourceRange, type SourceRangeKey, - IdMap, sourceRangeFromKey, sourceRangeKey, -} from '../yjsModel' -import { type Token } from './token' +} from '../util/data/text' +import { type ExternalId, IdMap } from '../yjsModel' +import { type Token, type TokenId } from './token' import { type Ast, type AstId, ExpressionStatement } from './tree' declare const nodeKeyBrand: unique symbol @@ -18,11 +17,11 @@ declare const tokenKeyBrand: unique symbol export type TokenKey = SourceRangeKey & { [tokenKeyBrand]: never } /** Create a source-range key for an `Ast`. */ export function nodeKey(start: number, length: number): NodeKey { - return sourceRangeKey([start, start + length]) as NodeKey + return sourceRangeKey({ from: start, to: start + length }) as NodeKey } /** Create a source-range key for a `Token`. */ export function tokenKey(start: number, length: number): TokenKey { - return sourceRangeKey([start, start + length]) as TokenKey + return sourceRangeKey({ from: start, to: start + length }) as TokenKey } /** Maps from source ranges to `Ast`s. */ @@ -56,13 +55,20 @@ export function spanMapToIdMap(spans: SpanMap): IdMap { return idMap } -/** Given a `SpanMap`, return a function that can look up source ranges by AST ID. */ -export function spanMapToSpanGetter(spans: SpanMap): (id: AstId) => SourceRange | undefined { +/** Returns a function that can look up source ranges by AST ID. */ +export function spanMapToSpanGetter(spans: NodeSpanMap): (id: AstId) => SourceRange | undefined { const reverseMap = new Map() - for (const [key, asts] of spans.nodes) { + for (const [key, asts] of spans) { for (const ast of asts) { reverseMap.set(ast.id, sourceRangeFromKey(key)) } } return id => reverseMap.get(id) } + +/** Returns a function that can look up token source ranges. */ +export function tokenSpanGetter(spans: TokenSpanMap): (token: Token) => SourceRange | undefined { + const reverseMap = new Map() + for (const [key, token] of spans) reverseMap.set(token.id, sourceRangeFromKey(key)) + return ({ id }) => reverseMap.get(id) +} diff --git a/app/ydoc-shared/src/ast/mutableModule.ts b/app/ydoc-shared/src/ast/mutableModule.ts index 748b7e56b7ed..71ee3cbc3dc9 100644 --- a/app/ydoc-shared/src/ast/mutableModule.ts +++ b/app/ydoc-shared/src/ast/mutableModule.ts @@ -2,26 +2,24 @@ import * as random from 'lib0/random' import * as Y from 'yjs' import { subtreeRoots } from '.' import { assert, assertDefined } from '../util/assert' -import type { SourceRangeEdit } from '../util/data/text' -import { defaultLocalOrigin, tryAsOrigin, type Origin } from '../yjsModel' +import { type SourceRangeEdit } from '../util/data/text' +import { type Origin, defaultLocalOrigin, tryAsOrigin } from '../yjsModel' import { newExternalId } from './idMap' import { parseModule } from './parse' -import type { SyncTokenId } from './token' -import { Token, isTokenId } from './token' -import type { - AstFields, - AstId, - BodyBlock, - FixedMap, - Mutable, - MutableAst, - MutableBodyBlock, - MutableInvalid, - NodeChild, - Owned, - RawNodeChild, -} from './tree' +import { type SyncTokenId, Token, isTokenId } from './token' import { + type AstFields, + type AstId, + type AstType, + type BodyBlock, + type FixedMap, + type Mutable, + type MutableAst, + type MutableBodyBlock, + type MutableInvalid, + type NodeChild, + type Owned, + type RawNodeChild, Ast, Wildcard, asOwned, @@ -160,7 +158,7 @@ export class MutableModule implements Module { /** Copy the given node into the module. */ copy(ast: T): Owned> { - const id = newAstId(ast.typeName()) + const id = newAstId(ast.typeName) const fields = ast.fields.clone() this.nodes.set(id, fields as any) fields.set('id', id) @@ -373,7 +371,7 @@ export class MutableModule implements Module { } /** @internal */ - baseObject(type: string, overrideId?: AstId): FixedMap { + baseObject(type: AstType, overrideId?: AstId): FixedMap { const map = new Y.Map() const map_ = map as unknown as FixedMap const id = overrideId ?? newAstId(type) diff --git a/app/ydoc-shared/src/ast/repair.ts b/app/ydoc-shared/src/ast/repair.ts index f6ed0f10a364..4d4b1f5db681 100644 --- a/app/ydoc-shared/src/ast/repair.ts +++ b/app/ydoc-shared/src/ast/repair.ts @@ -1,12 +1,11 @@ import { subtreeRoots } from '.' import { assertDefined, assertEqual } from '../util/assert' -import { sourceRangeFromKey } from '../yjsModel' -import type { NodeKey, NodeSpanMap } from './idMap' -import type { MutableModule } from './mutableModule' +import { sourceRangeFromKey } from '../util/data/text' +import { type NodeKey, type NodeSpanMap } from './idMap' +import { type MutableModule } from './mutableModule' import { parseModuleWithSpans } from './parse' import { printWithSpans } from './print' -import type { Ast, AstId } from './tree' -import { BodyBlock, Group } from './tree' +import { BodyBlock, Group, type Ast, type AstId } from './tree' /** * Try to find all the spans in `expected` in `encountered`. If any are missing, use the provided `code` to determine @@ -24,10 +23,10 @@ function checkSpans(expected: NodeSpanMap, encountered: NodeSpanMap, code: strin const lostInline = new Array() const lostBlock = new Array() for (const [key, ast] of lost) { - const [start, end] = sourceRangeFromKey(key) + const { from, to } = sourceRangeFromKey(key) // Do not report lost empty body blocks, we don't want them to be considered for repair. - if (start === end && ast instanceof BodyBlock) continue - ;(code.substring(start, end).match(/[\r\n]/) ? lostBlock : lostInline).push(ast) + if (from === to && ast instanceof BodyBlock) continue + ;(code.substring(from, to).match(/[\r\n]/) ? lostBlock : lostInline).push(ast) } return { lostInline, lostBlock } } diff --git a/app/ydoc-shared/src/ast/sourceDocument.ts b/app/ydoc-shared/src/ast/sourceDocument.ts index 32a093625830..88ef330a4d5f 100644 --- a/app/ydoc-shared/src/ast/sourceDocument.ts +++ b/app/ydoc-shared/src/ast/sourceDocument.ts @@ -1,11 +1,16 @@ import { assertDefined } from '../util/assert' -import type { SourceRangeEdit } from '../util/data/text' -import { offsetEdit, textChangeToEdits } from '../util/data/text' -import type { Origin, SourceRange } from '../yjsModel' -import { rangeEquals, sourceRangeFromKey } from '../yjsModel' -import type { Module, ModuleUpdate } from './mutableModule' +import { + rangeEquals, + sourceRangeFromKey, + textChangeToEdits, + translateRange, + type SourceRange, + type SourceRangeEdit, +} from '../util/data/text' +import { type Origin } from '../yjsModel' +import { type Module, type ModuleUpdate } from './mutableModule' import { printWithSpans } from './print' -import type { AstId } from './tree' +import { type AstId } from './tree' /** * Provides a view of the text representation of a module, @@ -32,9 +37,9 @@ export class SourceDocument { clear() { if (this.state.spans.size !== 0) this.state.spans.clear() if (this.state.text !== '') { - const range: SourceRange = [0, this.state.text.length] + const textEdit = { from: 0, to: this.state.text.length, insert: '' } this.state.text = '' - this.notifyObservers([{ range, insert: '' }], undefined) + this.notifyObservers([textEdit], undefined) } } @@ -52,10 +57,10 @@ export class SourceDocument { if (!oldSpan || !rangeEquals(range, oldSpan)) this.state.spans.set(node.id, range) if (update.updateRoots.has(node.id) && node.id !== root.id) { assertDefined(oldSpan) - const oldCode = this.rawState.text.slice(oldSpan[0], oldSpan[1]) - const newCode = printed.code.slice(range[0], range[1]) + const oldCode = this.rawState.text.slice(oldSpan.from, oldSpan.to) + const newCode = printed.code.slice(range.from, range.to) const subedits = textChangeToEdits(oldCode, newCode).map(textEdit => - offsetEdit(textEdit, oldSpan[0]), + translateRange(textEdit, oldSpan.from), ) subtreeTextEdits.push(...subedits) } @@ -64,7 +69,7 @@ export class SourceDocument { if (printed.code !== this.rawState.text) { const textEdits = update.updateRoots.has(root.id) ? - [{ range: [0, this.rawState.text.length] satisfies SourceRange, insert: printed.code }] + [{ from: 0, to: this.rawState.text.length, insert: printed.code }] : subtreeTextEdits this.state.text = printed.code this.notifyObservers(textEdits, update.origin) @@ -85,7 +90,7 @@ export class SourceDocument { observe(observer: SourceDocumentObserver) { this.observers.push(observer) if (this.rawState.text.length) - observer([{ range: [0, 0], insert: this.rawState.text }], undefined) + observer([{ from: 0, to: 0, insert: this.rawState.text }], undefined) } /** Remove a callback to no longer be called with a list of edits on every update. */ diff --git a/app/ydoc-shared/src/ast/syncToCode.ts b/app/ydoc-shared/src/ast/syncToCode.ts index 77c5feb376d2..ee08c41bb33e 100644 --- a/app/ydoc-shared/src/ast/syncToCode.ts +++ b/app/ydoc-shared/src/ast/syncToCode.ts @@ -2,21 +2,20 @@ import * as iter from 'enso-common/src/utilities/data/iter' import * as map from 'lib0/map' import { assert, assertDefined } from '../util/assert' import { + type SourceRange, type SourceRangeEdit, + type SourceRangeEditDesc, + type SourceRangeKey, type SpanTree, applyTextEdits, applyTextEditsToSpans, enclosingSpans, - textChangeToEdits, - trimEnd, -} from '../util/data/text' -import { - type SourceRange, - type SourceRangeKey, rangeLength, sourceRangeFromKey, sourceRangeKey, -} from '../yjsModel' + textChangeToEdits, + trimEnd, +} from '../util/data/text' import { xxHash128 } from './ffi' import { type NodeKey, type NodeSpanMap, newExternalId } from './idMap' import type { Module, MutableModule } from './mutableModule' @@ -88,7 +87,7 @@ function calculateCorrespondence( astSpans: NodeSpanMap, parsedRoot: Ast, parsedSpans: NodeSpanMap, - textEdits: SourceRangeEdit[], + textEdits: SourceRangeEditDesc[], codeAfter: string, ): Map { const newSpans = new Map() @@ -118,7 +117,7 @@ function calculateCorrespondence( for (const [astAfter, partsAfter] of astsMatchingPartsAfter) { for (const partAfter of partsAfter) { const astBefore = partAfterToAstBefore.get(sourceRangeKey(partAfter))! - if (astBefore.typeName() === astAfter.typeName()) { + if (astBefore.typeName === astAfter.typeName) { ;(rangeLength(newSpans.get(astAfter.id)!) === rangeLength(partAfter) ? toSync : candidates @@ -143,7 +142,7 @@ function calculateCorrespondence( const unmatchedNewAsts = newAsts.filter(ast => !newIdsMatched.has(ast.id)) const unmatchedOldAsts = oldHashes.get(hash)?.filter(ast => !oldIdsMatched.has(ast.id)) ?? [] for (const [unmatchedNew, unmatchedOld] of iter.zip(unmatchedNewAsts, unmatchedOldAsts)) { - if (unmatchedNew.typeName() === unmatchedOld.typeName()) { + if (unmatchedNew.typeName === unmatchedOld.typeName) { toSync.set(unmatchedOld.id, unmatchedNew) // Update the matched-IDs indices. oldIdsMatched.add(unmatchedOld.id) @@ -156,13 +155,13 @@ function calculateCorrespondence( // movement-matching. for (const [beforeId, after] of candidates) { if (oldIdsMatched.has(beforeId) || newIdsMatched.has(after.id)) continue - if (after.typeName() === ast.module.get(beforeId).typeName()) { + if (after.typeName === ast.module.get(beforeId).typeName) { toSync.set(beforeId, after) } } for (const [idBefore, astAfter] of toSync.entries()) - assert(ast.module.get(idBefore).typeName() === astAfter.typeName()) + assert(ast.module.get(idBefore).typeName === astAfter.typeName) return toSync } diff --git a/app/ydoc-shared/src/ast/token.ts b/app/ydoc-shared/src/ast/token.ts index 153e09f139f1..6220b7403e6c 100644 --- a/app/ydoc-shared/src/ast/token.ts +++ b/app/ydoc-shared/src/ast/token.ts @@ -7,6 +7,7 @@ import { newExternalId } from './idMap' import type { AstId, DeepReadonly, NodeChild, Owned } from './tree' import { Ast } from './tree' export import TokenType = RawAst.Token.Type +export import tokenTypes = RawAst.Token.typeNames /** Whether the given value is a {@link Token}. */ export function isToken(maybeToken: unknown): maybeToken is Token { @@ -34,15 +35,11 @@ export interface SyncTokenId { /** A structure representing a lexical source code unit in the AST. */ export class Token implements SyncTokenId { - readonly id: TokenId - code_: string - tokenType_: TokenType | undefined - - private constructor(code: string, type: TokenType | undefined, id: TokenId) { - this.id = id - this.code_ = code - this.tokenType_ = type - } + private constructor( + readonly code_: string, + readonly tokenType_: TokenType | undefined, + readonly id: TokenId, + ) {} /** The id of this token. */ get externalId(): TokenId { @@ -71,8 +68,8 @@ export class Token implements SyncTokenId { } /** The name of the token type of this token. */ - typeName(): string { - if (this.tokenType_) return RawAst.Token.typeNames[this.tokenType_]! + get typeName(): string { + if (this.tokenType_ != null) return RawAst.Token.typeNames[this.tokenType_]! else return 'Raw' } } diff --git a/app/ydoc-shared/src/ast/tree.ts b/app/ydoc-shared/src/ast/tree.ts index fc2068b1ff09..62b8dab1d5e3 100644 --- a/app/ydoc-shared/src/ast/tree.ts +++ b/app/ydoc-shared/src/ast/tree.ts @@ -125,10 +125,33 @@ const nodeMetadataKeys = allKeys({ export type NodeMetadata = FixedMapView export type MutableNodeMetadata = FixedMap +export const astTypes = [ + 'App', + 'Assignment', + 'BodyBlock', + 'ExpressionStatement', + 'FunctionDef', + 'Generic', + 'Group', + 'Ident', + 'Import', + 'Invalid', + 'NegationApp', + 'NumericLiteral', + 'OprApp', + 'PropertyAccess', + 'TextLiteral', + 'UnaryOprApp', + 'AutoscopedIdentifier', + 'Vector', + 'Wildcard', +] as const +export type AstType = (typeof astTypes)[number] + /** @internal */ interface RawAstFields { id: AstId - type: string + type: AstType parent: AstId | undefined metadata: FixedMap } @@ -227,7 +250,7 @@ export abstract class Ast { } /** TODO: Add docs */ - typeName(): string { + get typeName(): AstType { return this.fields.get('type') } diff --git a/app/ydoc-shared/src/util/data/__tests__/text.test.ts b/app/ydoc-shared/src/util/data/__tests__/text.test.ts index 63c02dacd083..7986c5cb2349 100644 --- a/app/ydoc-shared/src/util/data/__tests__/text.test.ts +++ b/app/ydoc-shared/src/util/data/__tests__/text.test.ts @@ -1,6 +1,70 @@ import { fc, test } from '@fast-check/vitest' import { expect } from 'vitest' -import { applyTextEdits, applyTextEditsToSpans, textChangeToEdits, trimEnd } from '../text' +import { + type SourceRange, + applyTextEdits, + applyTextEditsToSpans, + rangeEncloses, + rangeIntersects, + textChangeToEdits, + trimEnd, +} from '../text' + +type RangeTest = { a: SourceRange; b: SourceRange } + +function rangeTest({ a, b }: { a: number[]; b: number[] }) { + return { a: { from: a[0]!, to: a[1]! }, b: { from: b[0]!, to: b[1]! } } +} + +const equalRanges: RangeTest[] = [ + { a: [0, 0], b: [0, 0] }, + { a: [0, 1], b: [0, 1] }, + { a: [-5, 5], b: [-5, 5] }, +].map(rangeTest) + +const totalOverlap: RangeTest[] = [ + { a: [0, 1], b: [0, 0] }, + { a: [0, 2], b: [2, 2] }, + { a: [-1, 1], b: [1, 1] }, + { a: [0, 2], b: [0, 1] }, + { a: [-10, 10], b: [-3, 7] }, + { a: [0, 5], b: [1, 2] }, + { a: [3, 5], b: [3, 4] }, +].map(rangeTest) + +const reverseTotalOverlap: RangeTest[] = totalOverlap.map(({ a, b }) => ({ a: b, b: a })) + +const noOverlap: RangeTest[] = [ + { a: [0, 1], b: [2, 3] }, + { a: [0, 1], b: [-1, -1] }, + { a: [5, 6], b: [2, 3] }, + { a: [0, 2], b: [-2, -1] }, + { a: [-5, -3], b: [9, 10] }, + { a: [-3, 2], b: [3, 4] }, +].map(rangeTest) + +const partialOverlap: RangeTest[] = [ + { a: [0, 3], b: [-1, 1] }, + { a: [0, 1], b: [-1, 0] }, + { a: [0, 0], b: [-1, 0] }, + { a: [0, 2], b: [1, 4] }, + { a: [-8, 0], b: [0, 10] }, +].map(rangeTest) + +test.each([...equalRanges, ...totalOverlap])('Range $a should enclose $b', ({ a, b }) => + expect(rangeEncloses(a, b)).toBe(true), +) +test.each([...noOverlap, ...partialOverlap, ...reverseTotalOverlap])( + 'Range $a should not enclose $b', + ({ a, b }) => expect(rangeEncloses(a, b)).toBe(false), +) +test.each([...equalRanges, ...totalOverlap, ...reverseTotalOverlap, ...partialOverlap])( + 'Range $a should intersect $b', + ({ a, b }) => expect(rangeIntersects(a, b)).toBe(true), +) +test.each([...noOverlap])('Range $a should not intersect $b', ({ a, b }) => + expect(rangeIntersects(a, b)).toBe(false), +) test.prop({ before: fc.array(fc.boolean(), { minLength: 32, maxLength: 64 }), @@ -45,12 +109,12 @@ function checkCorrespondence(a: string[], b: string[]) { Performs the same check as {@link checkCorrespondence}, for correspondences that are not expected to be reversible. */ function checkCorrespondenceForward(before: string[], after: string[]) { - const leadingSpacesAndLength = (input: string): [number, number] => [ - input.lastIndexOf(' ') + 1, - input.length, - ] - const spacesAndHyphens = ([spaces, length]: readonly [number, number]) => { - return ' '.repeat(spaces) + '-'.repeat(length - spaces) + const leadingSpacesAndLength = (input: string): SourceRange => ({ + from: input.lastIndexOf(' ') + 1, + to: input.length, + }) + const spacesAndHyphens = ({ from, to }: SourceRange) => { + return ' '.repeat(from) + '-'.repeat(to - from) } const edits = textChangeToEdits(before[0]!, after[0]!) const spansAfter = applyTextEditsToSpans(edits, before.slice(1).map(leadingSpacesAndLength)).map( diff --git a/app/ydoc-shared/src/util/data/text.ts b/app/ydoc-shared/src/util/data/text.ts index e38464c81d6c..9c756b53036b 100644 --- a/app/ydoc-shared/src/util/data/text.ts +++ b/app/ydoc-shared/src/util/data/text.ts @@ -1,8 +1,63 @@ import * as iter from 'enso-common/src/utilities/data/iter' import diff from 'fast-diff' -import { rangeEncloses, rangeLength, type SourceRange } from '../../yjsModel' +import { type DeepReadonly } from '../../ast' -export type SourceRangeEdit = { range: SourceRange; insert: string } +export interface SourceRange { + readonly from: number + readonly to: number +} +declare const brandSourceRangeKey: unique symbol +export type SourceRangeKey = string & { [brandSourceRangeKey]: never } + +/** Serializes a {@link SourceRange}, making it suitable for use as a key in maps or sets. */ +export function sourceRangeKey({ from, to }: SourceRange): SourceRangeKey { + return `${from.toString(16)}:${to.toString(16)}` as SourceRangeKey +} +/** Deserializes a {@link SourceRange} that was serialized by {@link sourceRangeKey} */ +export function sourceRangeFromKey(key: SourceRangeKey): SourceRange { + const [from, to] = key.split(':').map(x => parseInt(x, 16)) as [number, number] + return { from, to } +} + +/** @returns Whether the two ranges have the same start and end. */ +export function rangeEquals(a: SourceRange, b: SourceRange): boolean { + return a.from == b.from && a.to == b.to +} + +/** @returns Whether the point `b` is within the range `a`. */ +export function rangeIncludes(a: SourceRange, b: number): boolean { + return a.from <= b && a.to >= b +} + +/** @returns whether the point `b` is within the range `a`. */ +export function rangeLength(a: SourceRange): number { + return a.to - a.from +} + +/** @returns whether range `a` fully contains range `b`. */ +export function rangeEncloses(a: SourceRange, b: SourceRange): boolean { + return a.from <= b.from && a.to >= b.to +} + +/** @returns Whether the ranges meet. */ +export function rangeIntersects(a: SourceRange, b: SourceRange): boolean { + return a.from <= b.to && a.to >= b.from +} + +/** Whether the given range is before the other range. */ +export function rangeIsBefore(a: SourceRange, b: SourceRange): boolean { + return a.to <= b.from +} + +/** Describes how a change to text will affect document locations. */ +export interface SourceRangeEditDesc extends SourceRange { + insert: { length: number } +} + +/** A change that can be applied to text. */ +export interface SourceRangeEdit extends SourceRangeEditDesc { + insert: string +} /** Given text and a set of `TextEdit`s, return the result of applying the edits to the text. */ export function applyTextEdits( @@ -10,13 +65,13 @@ export function applyTextEdits( textEdits: ReadonlyArray>, ) { const editsOrdered = [...textEdits] - editsOrdered.sort((a, b) => a.range[0] - b.range[0]) + editsOrdered.sort((a, b) => a.from - b.from) let start = 0 let newText = '' for (const textEdit of editsOrdered) { - newText += oldText.slice(start, textEdit.range[0]) + newText += oldText.slice(start, textEdit.from) newText += textEdit.insert - start = textEdit.range[1] + start = textEdit.to } newText += oldText.slice(start) return newText @@ -36,7 +91,7 @@ export function textChangeToEdits(before: string, after: string): SourceRangeEdi for (const [op, text] of diff(before, after)) { switch (op) { case diff.INSERT: - if (!nextEdit) nextEdit = { range: [pos, pos], insert: '' } + if (!nextEdit) nextEdit = { from: pos, to: pos, insert: '' } nextEdit.insert = text break case diff.EQUAL: @@ -49,7 +104,7 @@ export function textChangeToEdits(before: string, after: string): SourceRangeEdi case diff.DELETE: { if (nextEdit) textEdits.push(nextEdit) const endPos = pos + text.length - nextEdit = { range: [pos, endPos], insert: '' } + nextEdit = { from: pos, to: endPos, insert: '' } pos = endPos break } @@ -59,9 +114,9 @@ export function textChangeToEdits(before: string, after: string): SourceRangeEdi return textEdits } -/** Translate a `TextEdit` by the specified offset. */ -export function offsetEdit(textEdit: SourceRangeEdit, offset: number): SourceRangeEdit { - return { ...textEdit, range: [textEdit.range[0] + offset, textEdit.range[1] + offset] } +/** Translate a source range by the specified offset. */ +export function translateRange(textEdit: T, offset: number): T { + return { ...textEdit, from: textEdit.from + offset, to: textEdit.to + offset } } /** @@ -71,38 +126,42 @@ export function offsetEdit(textEdit: SourceRangeEdit, offset: number): SourceRan * @returns - A sequence of: Each span from `spansBefore` paired with the smallest span of the text after the edit that * contains all text that was in the original span and has not been deleted. */ -export function applyTextEditsToSpans(textEdits: SourceRangeEdit[], spansBefore: SourceRange[]) { +export function applyTextEditsToSpans( + textEdits: DeepReadonly, + spansBefore: DeepReadonly, +) { // Gather start and end points. const numerically = (a: number, b: number) => a - b - const starts = new iter.Resumable(spansBefore.map(([start, _end]) => start).sort(numerically)) - const ends = new iter.Resumable(spansBefore.map(([_start, end]) => end).sort(numerically)) + const starts = new iter.Resumable(spansBefore.map(({ from }) => from).sort(numerically)) + const ends = new iter.Resumable(spansBefore.map(({ to }) => to).sort(numerically)) // Construct translations from old locations to new locations for all start and end points. const startMap = new Map() const endMap = new Map() let offset = 0 - for (const { range, insert } of textEdits) { + for (const textEdit of textEdits) { + const { from, to, insert } = textEdit starts.advanceWhile(start => { - if (start < range[0]) { + if (start < from) { startMap.set(start, start + offset) return true - } else if (start <= range[1]) { - startMap.set(start, range[0] + offset + insert.length) + } else if (start <= to) { + startMap.set(start, from + offset + insert.length) return true } return false }) ends.advanceWhile(end => { - if (end <= range[0]) { + if (end <= from) { endMap.set(end, end + offset) return true - } else if (end <= range[1]) { - endMap.set(end, range[0] + offset) + } else if (end <= to) { + endMap.set(end, from + offset) return true } return false }) - offset += insert.length - rangeLength(range) + offset += insert.length - rangeLength(textEdit) } starts.forEach(start => startMap.set(start, start + offset)) ends.forEach(end => endMap.set(end, end + offset)) @@ -110,9 +169,10 @@ export function applyTextEditsToSpans(textEdits: SourceRangeEdit[], spansBefore: // Apply the translations to the map. const spansBeforeAndAfter = new Array() for (const spanBefore of spansBefore) { - const startAfter = startMap.get(spanBefore[0])! - const endAfter = endMap.get(spanBefore[1])! - if (endAfter > startAfter) spansBeforeAndAfter.push([spanBefore, [startAfter, endAfter]]) + const startAfter = startMap.get(spanBefore.from)! + const endAfter = endMap.get(spanBefore.to)! + if (endAfter > startAfter) + spansBeforeAndAfter.push([spanBefore, { from: startAfter, to: endAfter }]) } return spansBeforeAndAfter } @@ -150,7 +210,9 @@ export function enclosingSpans( } /** Return the given range with any trailing spaces stripped. */ -export function trimEnd(range: SourceRange, text: string): SourceRange { - const trimmedLength = text.slice(range[0], range[1]).search(/ +$/) - return trimmedLength === -1 ? range : [range[0], range[0] + trimmedLength] +export function trimEnd(range: T, text: string): T { + const trimmedLength = text.slice(range.from, range.to).search(/ +$/) + return trimmedLength === -1 ? range : ( + { ...range, from: range.from, to: range.from + trimmedLength } + ) } diff --git a/app/ydoc-shared/src/util/lezer.ts b/app/ydoc-shared/src/util/lezer.ts index e12ef4abb1c6..da222c76bbd7 100644 --- a/app/ydoc-shared/src/util/lezer.ts +++ b/app/ydoc-shared/src/util/lezer.ts @@ -1,4 +1,4 @@ -import type { TreeCursor } from '@lezer/common' +import { type SyntaxNode, type TreeCursor } from '@lezer/common' /** * Compares the value of `cursor.name` to the provided value. This can be used instead of reading the field directly to @@ -8,3 +8,12 @@ import type { TreeCursor } from '@lezer/common' export function isNodeType(cursor: TreeCursor, type: string): boolean { return cursor.name === type } + +/** Yields the provided node, and its parents recursively. */ +export function* syntaxNodeAncestors(syn: SyntaxNode | null) { + let currentSyn: SyntaxNode | null = syn + while (currentSyn != null) { + yield currentSyn + currentSyn = currentSyn.parent + } +} diff --git a/app/ydoc-shared/src/yjsModel.ts b/app/ydoc-shared/src/yjsModel.ts index 69532fcd2135..80b911c5a714 100644 --- a/app/ydoc-shared/src/yjsModel.ts +++ b/app/ydoc-shared/src/yjsModel.ts @@ -1,6 +1,7 @@ import * as object from 'lib0/object' import * as random from 'lib0/random' import * as Y from 'yjs' +import { type SourceRange, type SourceRangeKey, sourceRangeKey } from './util/data/text' export type Uuid = `${string}-${string}-${string}-${string}-${string}` @@ -166,19 +167,6 @@ export function tryAsOrigin(origin: string): Origin | undefined { if (origin === 'remote') return origin } -export type SourceRange = readonly [start: number, end: number] -declare const brandSourceRangeKey: unique symbol -export type SourceRangeKey = string & { [brandSourceRangeKey]: never } - -/** TODO: Add docs */ -export function sourceRangeKey(range: SourceRange): SourceRangeKey { - return `${range[0].toString(16)}:${range[1].toString(16)}` as SourceRangeKey -} -/** TODO: Add docs */ -export function sourceRangeFromKey(key: SourceRangeKey): SourceRange { - return key.split(':').map(x => parseInt(x, 16)) as [number, number] -} - /** TODO: Add docs */ export class IdMap { private readonly rangeToExpr: Map @@ -278,33 +266,3 @@ const uuidRegex = /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/ export function isUuid(x: unknown): x is Uuid { return typeof x === 'string' && x.length === 36 && uuidRegex.test(x) } - -/** TODO: Add docs */ -export function rangeEquals(a: SourceRange, b: SourceRange): boolean { - return a[0] == b[0] && a[1] == b[1] -} - -/** TODO: Add docs */ -export function rangeIncludes(a: SourceRange, b: number): boolean { - return a[0] <= b && a[1] >= b -} - -/** TODO: Add docs */ -export function rangeLength(a: SourceRange): number { - return a[1] - a[0] -} - -/** TODO: Add docs */ -export function rangeEncloses(a: SourceRange, b: SourceRange): boolean { - return a[0] <= b[0] && a[1] >= b[1] -} - -/** TODO: Add docs */ -export function rangeIntersects(a: SourceRange, b: SourceRange): boolean { - return a[0] <= b[1] && a[1] >= b[0] -} - -/** Whether the given range is before the other range. */ -export function rangeIsBefore(a: SourceRange, b: SourceRange): boolean { - return a[1] <= b[0] -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 972b3378b195..cd8885031bbd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -125,26 +125,26 @@ importers: specifier: ^7.24.7 version: 7.25.6 '@codemirror/commands': - specifier: ^6.6.0 - version: 6.6.0 + specifier: ^6.7.1 + version: 6.7.1 '@codemirror/lang-markdown': specifier: ^v6.3.0 version: 6.3.0 '@codemirror/language': - specifier: ^6.10.2 - version: 6.10.2 + specifier: ^6.10.6 + version: 6.10.6 '@codemirror/lint': - specifier: ^6.8.1 - version: 6.8.1 + specifier: ^6.8.4 + version: 6.8.4 '@codemirror/search': - specifier: ^6.5.6 - version: 6.5.6 + specifier: ^6.5.8 + version: 6.5.8 '@codemirror/state': - specifier: ^6.4.1 - version: 6.4.1 + specifier: ^6.5.0 + version: 6.5.0 '@codemirror/view': - specifier: ^6.35.0 - version: 6.35.0 + specifier: ^6.35.3 + version: 6.35.3 '@fast-check/vitest': specifier: ^0.0.8 version: 0.0.8(vitest@1.6.0(@types/node@22.9.0)(jsdom@24.1.0)(lightningcss@1.25.1)) @@ -1410,8 +1410,8 @@ packages: '@codemirror/view': ^6.0.0 '@lezer/common': ^1.0.0 - '@codemirror/commands@6.6.0': - resolution: {integrity: sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==} + '@codemirror/commands@6.7.1': + resolution: {integrity: sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==} '@codemirror/lang-css@6.3.0': resolution: {integrity: sha512-CyR4rUNG9OYcXDZwMPvJdtb6PHbBDKUc/6Na2BIwZ6dKab1JQqKa4di+RNRY9Myn7JB81vayKwJeQ7jEdmNVDA==} @@ -1428,23 +1428,23 @@ packages: '@codemirror/lang-markdown@6.3.0': resolution: {integrity: sha512-lYrI8SdL/vhd0w0aHIEvIRLRecLF7MiiRfzXFZY94dFwHqC9HtgxgagJ8fyYNBldijGatf9wkms60d8SrAj6Nw==} - '@codemirror/language@6.10.2': - resolution: {integrity: sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==} + '@codemirror/language@6.10.6': + resolution: {integrity: sha512-KrsbdCnxEztLVbB5PycWXFxas4EOyk/fPAfruSOnDDppevQgid2XZ+KbJ9u+fDikP/e7MW7HPBTvTb8JlZK9vA==} - '@codemirror/lint@6.8.1': - resolution: {integrity: sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==} + '@codemirror/lint@6.8.4': + resolution: {integrity: sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==} - '@codemirror/search@6.5.6': - resolution: {integrity: sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==} + '@codemirror/search@6.5.8': + resolution: {integrity: sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==} - '@codemirror/state@6.4.1': - resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==} + '@codemirror/state@6.5.0': + resolution: {integrity: sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==} '@codemirror/theme-one-dark@6.1.2': resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==} - '@codemirror/view@6.35.0': - resolution: {integrity: sha512-I0tYy63q5XkaWsJ8QRv5h6ves7kvtrBWjBcnf/bzohFJQc5c14a1AQRdE8QpPF9eMp5Mq2FMm59TCj1gDfE7kw==} + '@codemirror/view@6.35.3': + resolution: {integrity: sha512-ScY7L8+EGdPl4QtoBiOzE4FELp7JmNUsBvgBcCakXWM2uiv/K89VAzU3BMDscf0DsACLvTKePbd5+cFDTcei6g==} '@csstools/selector-resolve-nested@1.1.0': resolution: {integrity: sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==} @@ -2036,6 +2036,9 @@ packages: resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} engines: {node: '>= 10.0.0'} + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + '@mdx-js/react@3.1.0': resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} peerDependencies: @@ -8972,25 +8975,25 @@ snapshots: - '@chromatic-com/playwright' - react - '@codemirror/autocomplete@6.16.3(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.1)': + '@codemirror/autocomplete@6.16.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.1)': dependencies: - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 '@lezer/common': 1.2.1 - '@codemirror/commands@6.6.0': + '@codemirror/commands@6.7.1': dependencies: - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 '@lezer/common': 1.2.1 - '@codemirror/lang-css@6.3.0(@codemirror/view@6.35.0)': + '@codemirror/lang-css@6.3.0(@codemirror/view@6.35.3)': dependencies: - '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 + '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.1) + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 '@lezer/common': 1.2.1 '@lezer/css': 1.1.9 transitivePeerDependencies: @@ -8998,74 +9001,76 @@ snapshots: '@codemirror/lang-html@6.4.9': dependencies: - '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.1) - '@codemirror/lang-css': 6.3.0(@codemirror/view@6.35.0) + '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.1) + '@codemirror/lang-css': 6.3.0(@codemirror/view@6.35.3) '@codemirror/lang-javascript': 6.2.2 - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 '@lezer/common': 1.2.1 '@lezer/css': 1.1.9 '@lezer/html': 1.3.10 '@codemirror/lang-javascript@6.2.2': dependencies: - '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.1) - '@codemirror/language': 6.10.2 - '@codemirror/lint': 6.8.1 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.1) + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 '@lezer/common': 1.2.1 '@lezer/javascript': 1.4.18 '@codemirror/lang-json@6.0.1': dependencies: - '@codemirror/language': 6.10.2 + '@codemirror/language': 6.10.6 '@lezer/json': 1.0.2 '@codemirror/lang-markdown@6.3.0': dependencies: - '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.1) + '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.1) '@codemirror/lang-html': 6.4.9 - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 '@lezer/common': 1.2.1 '@lezer/markdown': 1.3.1 - '@codemirror/language@6.10.2': + '@codemirror/language@6.10.6': dependencies: - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 '@lezer/common': 1.2.1 '@lezer/highlight': 1.2.0 '@lezer/lr': 1.4.1 style-mod: 4.1.2 - '@codemirror/lint@6.8.1': + '@codemirror/lint@6.8.4': dependencies: - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 crelt: 1.0.6 - '@codemirror/search@6.5.6': + '@codemirror/search@6.5.8': dependencies: - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 crelt: 1.0.6 - '@codemirror/state@6.4.1': {} + '@codemirror/state@6.5.0': + dependencies: + '@marijn/find-cluster-break': 1.0.2 '@codemirror/theme-one-dark@6.1.2': dependencies: - '@codemirror/language': 6.10.2 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 '@lezer/highlight': 1.2.0 - '@codemirror/view@6.35.0': + '@codemirror/view@6.35.3': dependencies: - '@codemirror/state': 6.4.1 + '@codemirror/state': 6.5.0 style-mod: 4.1.2 w3c-keyname: 2.2.8 @@ -9409,13 +9414,13 @@ snapshots: '@histoire/controls@0.17.17(vite@5.4.10(@types/node@22.9.0)(lightningcss@1.25.1))': dependencies: - '@codemirror/commands': 6.6.0 + '@codemirror/commands': 6.7.1 '@codemirror/lang-json': 6.0.1 - '@codemirror/language': 6.10.2 - '@codemirror/lint': 6.8.1 - '@codemirror/state': 6.4.1 + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/state': 6.5.0 '@codemirror/theme-one-dark': 6.1.2 - '@codemirror/view': 6.35.0 + '@codemirror/view': 6.35.3 '@histoire/shared': 0.17.17(vite@5.4.10(@types/node@22.9.0)(lightningcss@1.25.1)) '@histoire/vendors': 0.17.17 transitivePeerDependencies: @@ -9675,6 +9680,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@marijn/find-cluster-break@1.0.2': {} + '@mdx-js/react@3.1.0(@types/react@18.3.3)(react@18.3.1)': dependencies: '@types/mdx': 2.0.13 @@ -12554,13 +12561,13 @@ snapshots: codemirror@6.0.1(@lezer/common@1.2.1): dependencies: - '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.1) - '@codemirror/commands': 6.6.0 - '@codemirror/language': 6.10.2 - '@codemirror/lint': 6.8.1 - '@codemirror/search': 6.5.6 - '@codemirror/state': 6.4.1 - '@codemirror/view': 6.35.0 + '@codemirror/autocomplete': 6.16.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.1) + '@codemirror/commands': 6.7.1 + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/search': 6.5.8 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 transitivePeerDependencies: - '@lezer/common' From 61bb1ce4ebbe0d4af55466943cf83b9862381f2c Mon Sep 17 00:00:00 2001 From: Gregory Michael Travis Date: Mon, 16 Dec 2024 10:38:47 -0500 Subject: [PATCH 05/12] Fix unused variable warning (#11851) --- .../Standard/Base/0.0.0-dev/src/Network/Reload_Detector.enso | 2 +- std-bits/base/src/main/java/org/enso/base/cache/LRUCache.java | 2 +- .../main/java/org/enso/base/enso_cloud/EnsoSecretHelper.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/Reload_Detector.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/Reload_Detector.enso index 966975d0ecf7..3669c7eaacfe 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Network/Reload_Detector.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Network/Reload_Detector.enso @@ -18,7 +18,7 @@ type Reload_Detector private Value mr:Managed_Resource new -> Reload_Detector = - mr = Managed_Resource.register (Ref.new 1) (x-> Nothing) True + mr = Managed_Resource.register (Ref.new 1) (_-> Nothing) True Reload_Detector.Value mr has_reload_occurred self = diff --git a/std-bits/base/src/main/java/org/enso/base/cache/LRUCache.java b/std-bits/base/src/main/java/org/enso/base/cache/LRUCache.java index eba05b6c3345..64a199b424eb 100644 --- a/std-bits/base/src/main/java/org/enso/base/cache/LRUCache.java +++ b/std-bits/base/src/main/java/org/enso/base/cache/LRUCache.java @@ -109,7 +109,7 @@ public CacheResult getResult(ItemBuilder itemBuilder) // a rare case so it seems unnecessary. logger.log( Level.WARNING, - "Error in cache file handling; will re-execute without caching: {}", + "Error in cache file handling; will re-execute without caching: {0}", e.getMessage()); Item rerequested = itemBuilder.buildItem(); return new CacheResult<>(rerequested.stream(), rerequested.metadata()); diff --git a/std-bits/base/src/main/java/org/enso/base/enso_cloud/EnsoSecretHelper.java b/std-bits/base/src/main/java/org/enso/base/enso_cloud/EnsoSecretHelper.java index 2e7b622e6848..c618398b99c5 100644 --- a/std-bits/base/src/main/java/org/enso/base/enso_cloud/EnsoSecretHelper.java +++ b/std-bits/base/src/main/java/org/enso/base/enso_cloud/EnsoSecretHelper.java @@ -163,7 +163,7 @@ public String hashKey() { keyStrings.add(resolvedHeader.getRight()); } - return Integer.toString(Arrays.deepHashCode(keyStrings.toArray())); + return Integer.toHexString(Arrays.deepHashCode(keyStrings.toArray())); } @Override From d2ae17ffc9d26327c584cb26b59510c7ed511efa Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Mon, 16 Dec 2024 07:54:19 -0800 Subject: [PATCH 06/12] Disallow a confusing constructor syntax (#11856) Previously, a constructor or type definition with a single argument defined inline could use spaces within the argument's definition without parentheses, as in the draft spec. This syntax was found confusing and is no longer allowed. No usages occurred in our `.enso` files. Fixes #10812. --- CHANGELOG.md | 4 ++ .../test/AnnotationsCompilerTest.java | 2 +- lib/rust/parser/debug/src/lib.rs | 9 +++- lib/rust/parser/debug/tests/parse.rs | 8 +-- lib/rust/parser/src/macros/built_in.rs | 3 +- .../src/syntax/statement/function_def.rs | 53 +++---------------- .../parser/src/syntax/statement/type_def.rs | 4 +- 7 files changed, 30 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ddee6d8bda9..4df253fba6e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,12 @@ #### Enso Language & Runtime - [Intersection types & type checks][11600] +- A constructor or type definition with a single inline argument definition was + previously allowed to use spaces in the argument definition without + parentheses. [This is now a syntax error.][11856] [11600]: https://github.com/enso-org/enso/pull/11600 +[11856]: https://github.com/enso-org/enso/pull/11856 # Next Release diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/AnnotationsCompilerTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/AnnotationsCompilerTest.java index b78b8b06cd45..c115fae8320a 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/AnnotationsCompilerTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/AnnotationsCompilerTest.java @@ -67,7 +67,7 @@ public void testConstructor() throws Exception { type Foo @a foo @b bar - Cons a b = a b + Cons a b """); var typeDefinition = (Definition.SugaredType) ir.bindings().apply(0); diff --git a/lib/rust/parser/debug/src/lib.rs b/lib/rust/parser/debug/src/lib.rs index 3c55e29423d8..987a30f9bda0 100644 --- a/lib/rust/parser/debug/src/lib.rs +++ b/lib/rust/parser/debug/src/lib.rs @@ -67,7 +67,11 @@ where T: serde::Serialize + Reflect { let text_escape_token = rust_to_meta[&TextEscape::reflect().id]; let token_to_str = move |token: Value| { let range = token_code_range(&token, base); - code[range].to_owned().into_boxed_str() + if range.is_empty() { + "".into() + } else { + code[range].to_owned().into_boxed_str() + } }; for token in identish_tokens { let token_to_str_ = token_to_str.clone(); @@ -158,6 +162,9 @@ fn token_code_range(token: &Value, base: usize) -> std::ops::Range { |field| fields(token).find(|(name, _)| *name == field).unwrap().1.as_u64().unwrap() as u32; let begin = get_u32(":codeReprBegin"); let len = get_u32(":codeReprLen"); + if len == 0 { + return 0..0; + } let begin = (begin as u64) | (base as u64 & !(u32::MAX as u64)); let begin = if begin < (base as u64) { begin + 1 << 32 } else { begin }; let begin = begin as usize - base; diff --git a/lib/rust/parser/debug/tests/parse.rs b/lib/rust/parser/debug/tests/parse.rs index d567a46ed4f9..6795084da883 100644 --- a/lib/rust/parser/debug/tests/parse.rs +++ b/lib/rust/parser/debug/tests/parse.rs @@ -346,12 +346,14 @@ fn type_def_full() { #[test] fn type_def_defaults() { - let code = ["type Result error ok=Nothing", " Ok value:ok = Nothing"]; - test!(code.join("\n"), + test!("type Result error ok=Nothing\n Ok value:ok=Nothing\n Error (value:e = Nothing)", (TypeDef Result #((() (Ident error) () ()) (() (Ident ok) () ((Ident Nothing)))) #(,(Constructor::new("Ok") - .with_arg(sexp![(() (Ident value) (":" (Ident ok)) ((Ident Nothing)))]))))); + .with_arg(sexp![(() (Ident value) (":" (Ident ok)) ((Ident Nothing)))])) + ,(Constructor::new("Error") + .with_arg(sexp![(() (Ident value) (":" (Ident e)) ((Ident Nothing)))]))))); + expect_invalid_node("type Result\n Ok value:ok = Nothing"); } #[test] diff --git a/lib/rust/parser/src/macros/built_in.rs b/lib/rust/parser/src/macros/built_in.rs index 97af2301b1b5..548494d13b62 100644 --- a/lib/rust/parser/src/macros/built_in.rs +++ b/lib/rust/parser/src/macros/built_in.rs @@ -277,7 +277,8 @@ fn lambda_body<'s>( let (body, mut rest) = segments.pop(); let arguments = rest.pop().unwrap(); let backslash = arguments.header.with_variant(token::variant::LambdaOperator()); - let arguments = syntax::parse_args(&mut arguments.result.tokens(), 0, precedence); + let arguments = + syntax::parse_args(&mut arguments.result.tokens(), 0, precedence, &mut default()); let arrow = body.header.with_variant(token::variant::ArrowOperator()); let body_expression = precedence.resolve(&mut body.result.tokens()); let body_expression = diff --git a/lib/rust/parser/src/syntax/statement/function_def.rs b/lib/rust/parser/src/syntax/statement/function_def.rs index 545375bbe9fc..ae9b2b6cb2db 100644 --- a/lib/rust/parser/src/syntax/statement/function_def.rs +++ b/lib/rust/parser/src/syntax/statement/function_def.rs @@ -182,6 +182,7 @@ pub fn parse_args<'s>( items: &mut Vec>, start: usize, precedence: &mut Precedence<'s>, + args_buffer: &mut Vec>, ) -> Vec> { let mut arg_starts = vec![]; for (i, item) in items.iter().enumerate().skip(start) { @@ -189,13 +190,11 @@ pub fn parse_args<'s>( arg_starts.push(i); } } - let mut defs: Vec<_> = arg_starts - .drain(..) - .rev() - .map(|arg_start| parse_arg_def(items, arg_start, precedence)) - .collect(); - defs.reverse(); - defs + args_buffer.extend( + arg_starts.drain(..).rev().map(|arg_start| parse_arg_def(items, arg_start, precedence)), + ); + debug_assert_eq!(items.len(), start); + args_buffer.drain(..).rev().collect() } pub fn parse_constructor_definition<'s>( @@ -270,43 +269,12 @@ fn parse_constructor_decl<'s>( precedence: &mut Precedence<'s>, args_buffer: &mut Vec>, ) -> (token::Ident<'s>, Vec>) { - let args = parse_type_args(items, start + 1, precedence, args_buffer); + let args = parse_args(items, start + 1, precedence, args_buffer); let name = items.pop().unwrap().into_token().unwrap().try_into().unwrap(); debug_assert_eq!(items.len(), start); (name, args) } -pub fn parse_type_args<'s>( - items: &mut Vec>, - start: usize, - precedence: &mut Precedence<'s>, - args_buffer: &mut Vec>, -) -> Vec> { - if start == items.len() { - return default(); - } - let mut arg_starts = vec![start]; - let mut expecting_rhs = false; - for (i, item) in items.iter().enumerate().skip(start + 1) { - if expecting_rhs { - expecting_rhs = false; - continue; - } - if let Item::Token(Token { variant: token::Variant::AssignmentOperator(_), .. }) = item { - expecting_rhs = true; - continue; - } - if Spacing::of_item(item) == Spacing::Spaced { - arg_starts.push(i); - } - } - args_buffer.extend( - arg_starts.drain(..).rev().map(|arg_start| parse_arg_def(items, arg_start, precedence)), - ); - debug_assert_eq!(items.len(), start); - args_buffer.drain(..).rev().collect() -} - pub fn try_parse_foreign_function<'s>( items: &mut Vec>, start: usize, @@ -493,12 +461,7 @@ fn parse_arg_def<'s>( .or_else(|| open2.as_ref().map(|t| t.code.position_after())) .or_else(|| open1.as_ref().map(|t| t.code.position_after())) .or_else(|| type_.as_ref().map(|t| t.operator.left_offset.code.position_before())) - // Why does this one need a type annotation??? - .or_else(|| { - close2 - .as_ref() - .map(|t: &token::CloseSymbol| t.left_offset.code.position_before()) - }) + .or_else(|| close2.as_ref().map(|t| t.left_offset.code.position_before())) .or_else(|| default.as_ref().map(|t| t.equals.left_offset.code.position_before())) .or_else(|| close1.as_ref().map(|t| t.left_offset.code.position_before())) .unwrap(), diff --git a/lib/rust/parser/src/syntax/statement/type_def.rs b/lib/rust/parser/src/syntax/statement/type_def.rs index 828a22dfaf6d..cc6ee56aa464 100644 --- a/lib/rust/parser/src/syntax/statement/type_def.rs +++ b/lib/rust/parser/src/syntax/statement/type_def.rs @@ -5,8 +5,8 @@ use crate::syntax::maybe_with_error; use crate::syntax::operator::Precedence; use crate::syntax::statement::apply_excess_private_keywords; use crate::syntax::statement::compound_lines; +use crate::syntax::statement::function_def::parse_args; use crate::syntax::statement::function_def::parse_constructor_definition; -use crate::syntax::statement::function_def::parse_type_args; use crate::syntax::statement::parse_statement; use crate::syntax::statement::scan_private_keywords; use crate::syntax::statement::EvaluationContext; @@ -66,7 +66,7 @@ pub fn try_parse_type_def<'s>( default() }; - let params = parse_type_args(items, start + 2, precedence, args_buffer); + let params = parse_args(items, start + 2, precedence, args_buffer); let name = items.pop().unwrap().into_token().unwrap().try_into().unwrap(); From 96c5f31009c1cf53548d22a567ea124b6e4f06c2 Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Mon, 16 Dec 2024 19:07:03 +0300 Subject: [PATCH 07/12] Upgrade Scala to 2.13.15 (#11853) close #11733 --- build.sbt | 20 +- distribution/engine/THIRD-PARTY/NOTICE | 8 +- .../org.jline.jline-3.23.0/NOTICES | 3 - .../org.jline.jline-3.26.3/NOTICES | 32 + .../LICENSE | 0 .../NOTICE | 4 +- .../NOTICES | 0 .../LICENSE | 0 .../NOTICE | 4 +- .../NOTICES | 0 .../LICENSE | 0 .../NOTICE | 4 +- .../NOTICES | 0 distribution/launcher/THIRD-PARTY/NOTICE | 8 +- .../org.jline.jline-3.26.3/NOTICES | 49 + .../LICENSE | 201 +++ .../NOTICE | 16 + .../NOTICES | 0 .../LICENSE | 201 +++ .../NOTICE | 16 + .../NOTICES | 0 .../LICENSE | 201 +++ .../NOTICE | 16 + .../NOTICES | 0 .../project-manager/THIRD-PARTY/NOTICE | 8 +- .../org.jline.jline-3.23.0/NOTICES | 73 - .../org.jline.jline-3.26.3/NOTICES | 49 + .../LICENSE | 201 +++ .../NOTICE | 16 + .../NOTICES | 2 + .../LICENSE | 201 +++ .../NOTICE | 16 + .../NOTICES | 0 .../LICENSE | 201 +++ .../NOTICE | 16 + .../NOTICES | 0 .../scala/org/enso/compiler/Compiler.scala | 2 +- .../execution/JobExecutionEngine.scala | 8 +- .../org/enso/projectmanager/jni-config.json | 27 +- .../org/enso/projectmanager/proxy-config.json | 3 +- .../enso/projectmanager/reflect-config.json | 1255 ++++++++++------- .../enso/projectmanager/resource-config.json | 198 ++- .../projectmanager/boot/ProjectManager.scala | 5 +- .../repository/ProjectFileRepository.scala | 6 +- project/JPMSPlugin.scala | 4 +- project/build.properties | 2 +- project/plugins.sbt | 2 +- .../org.jline.jline-3.23.0/copyright-keep | 2 - .../org.jline.jline-3.26.3}/copyright-keep | 6 + .../copyright-ignore | 2 +- .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep | 0 .../copyright-ignore | 2 +- .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep | 0 .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep | 2 +- tools/legal-review/engine/report-state | 4 +- .../org.jline.jline-3.26.3/copyright-keep | 24 +- .../copyright-ignore | 2 +- .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep} | 2 +- .../copyright-ignore | 2 +- .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep} | 2 +- .../files-ignore | 2 - .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep} | 2 +- tools/legal-review/launcher/report-state | 4 +- .../copyright-keep-context | 2 - .../org.jline.jline-3.26.3/copyright-keep} | 8 + .../copyright-ignore | 3 +- .../copyright-keep | 1 + .../default-and-custom-license | 0 .../files-keep | 2 + .../files-ignore | 2 - .../copyright-ignore | 2 +- .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep | 2 + .../files-ignore | 2 - .../copyright-keep | 0 .../default-and-custom-license | 0 .../files-keep | 2 + .../legal-review/project-manager/report-state | 4 +- 91 files changed, 2394 insertions(+), 772 deletions(-) delete mode 100644 distribution/engine/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES rename tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep => distribution/engine/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES (67%) rename distribution/engine/THIRD-PARTY/{org.scala-lang.scala-compiler-2.13.11 => org.scala-lang.scala-compiler-2.13.15}/LICENSE (100%) rename distribution/{launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11 => engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15}/NOTICE (89%) rename distribution/{launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11 => engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15}/NOTICES (100%) rename distribution/{launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11 => engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15}/LICENSE (100%) rename distribution/engine/THIRD-PARTY/{org.scala-lang.scala-compiler-2.13.11 => org.scala-lang.scala-library-2.13.15}/NOTICE (89%) rename distribution/engine/THIRD-PARTY/{org.scala-lang.scala-library-2.13.11 => org.scala-lang.scala-library-2.13.15}/NOTICES (100%) rename distribution/{project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11 => engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15}/LICENSE (100%) rename distribution/{project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11 => engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15}/NOTICE (89%) rename distribution/engine/THIRD-PARTY/{org.scala-lang.scala-reflect-2.13.11 => org.scala-lang.scala-reflect-2.13.15}/NOTICES (100%) create mode 100644 distribution/launcher/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES create mode 100644 distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE create mode 100644 distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE rename distribution/{project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11 => launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15}/NOTICES (100%) create mode 100644 distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE create mode 100644 distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE rename distribution/launcher/THIRD-PARTY/{org.scala-lang.scala-library-2.13.11 => org.scala-lang.scala-library-2.13.15}/NOTICES (100%) create mode 100644 distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE create mode 100644 distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE rename distribution/launcher/THIRD-PARTY/{org.scala-lang.scala-reflect-2.13.11 => org.scala-lang.scala-reflect-2.13.15}/NOTICES (100%) delete mode 100644 distribution/project-manager/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES create mode 100644 distribution/project-manager/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES create mode 100644 distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE create mode 100644 distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE rename distribution/{engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11 => project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15}/NOTICES (79%) create mode 100644 distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE create mode 100644 distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE rename distribution/project-manager/THIRD-PARTY/{org.scala-lang.scala-library-2.13.11 => org.scala-lang.scala-library-2.13.15}/NOTICES (100%) create mode 100644 distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE create mode 100644 distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE rename distribution/project-manager/THIRD-PARTY/{org.scala-lang.scala-reflect-2.13.11 => org.scala-lang.scala-reflect-2.13.15}/NOTICES (100%) delete mode 100644 tools/legal-review/engine/org.jline.jline-3.23.0/copyright-keep rename tools/legal-review/{launcher/org.jline.jline-3.23.0 => engine/org.jline.jline-3.26.3}/copyright-keep (75%) rename tools/legal-review/{project-manager/org.scala-lang.scala-compiler-2.13.11 => engine/org.scala-lang.scala-compiler-2.13.15}/copyright-ignore (89%) rename tools/legal-review/{launcher/org.scala-lang.scala-compiler-2.13.11 => engine/org.scala-lang.scala-compiler-2.13.15}/copyright-keep (100%) rename tools/legal-review/engine/{org.scala-lang.scala-compiler-2.13.11 => org.scala-lang.scala-compiler-2.13.15}/default-and-custom-license (100%) rename tools/legal-review/engine/{org.scala-lang.scala-compiler-2.13.11 => org.scala-lang.scala-compiler-2.13.15}/files-keep (100%) rename tools/legal-review/{launcher/org.scala-lang.scala-library-2.13.11 => engine/org.scala-lang.scala-library-2.13.15}/copyright-ignore (79%) rename tools/legal-review/engine/{org.scala-lang.scala-library-2.13.11 => org.scala-lang.scala-library-2.13.15}/copyright-keep (100%) rename tools/legal-review/{launcher/org.scala-lang.scala-compiler-2.13.11 => engine/org.scala-lang.scala-library-2.13.15}/default-and-custom-license (100%) rename tools/legal-review/{project-manager/org.scala-lang.scala-compiler-2.13.11 => engine/org.scala-lang.scala-library-2.13.15}/files-keep (100%) rename tools/legal-review/engine/{org.scala-lang.scala-reflect-2.13.11 => org.scala-lang.scala-reflect-2.13.15}/copyright-keep (100%) rename tools/legal-review/{project-manager/org.scala-lang.scala-compiler-2.13.11 => engine/org.scala-lang.scala-reflect-2.13.15}/default-and-custom-license (100%) rename tools/legal-review/{launcher/org.scala-lang.scala-compiler-2.13.11 => engine/org.scala-lang.scala-reflect-2.13.15}/files-keep (100%) rename distribution/launcher/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES => tools/legal-review/launcher/org.jline.jline-3.26.3/copyright-keep (75%) rename tools/legal-review/launcher/{org.scala-lang.scala-compiler-2.13.11 => org.scala-lang.scala-compiler-2.13.15}/copyright-ignore (89%) rename tools/legal-review/{project-manager/org.scala-lang.scala-compiler-2.13.11 => launcher/org.scala-lang.scala-compiler-2.13.15}/copyright-keep (100%) create mode 100644 tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license rename tools/legal-review/{engine/org.scala-lang.scala-library-2.13.11/files-ignore => launcher/org.scala-lang.scala-compiler-2.13.15/files-keep} (100%) rename tools/legal-review/{project-manager/org.scala-lang.scala-library-2.13.11 => launcher/org.scala-lang.scala-library-2.13.15}/copyright-ignore (79%) rename tools/legal-review/launcher/{org.scala-lang.scala-library-2.13.11 => org.scala-lang.scala-library-2.13.15}/copyright-keep (100%) create mode 100644 tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/default-and-custom-license rename tools/legal-review/{engine/org.scala-lang.scala-reflect-2.13.11/files-ignore => launcher/org.scala-lang.scala-library-2.13.15/files-keep} (100%) delete mode 100644 tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.11/files-ignore rename tools/legal-review/launcher/{org.scala-lang.scala-reflect-2.13.11 => org.scala-lang.scala-reflect-2.13.15}/copyright-keep (100%) create mode 100644 tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license rename tools/legal-review/launcher/{org.scala-lang.scala-library-2.13.11/files-ignore => org.scala-lang.scala-reflect-2.13.15/files-keep} (100%) delete mode 100644 tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep-context rename tools/legal-review/{engine/org.jline.jline-3.23.0/copyright-ignore => project-manager/org.jline.jline-3.26.3/copyright-keep} (68%) rename tools/legal-review/{engine/org.scala-lang.scala-compiler-2.13.11 => project-manager/org.scala-lang.scala-compiler-2.13.15}/copyright-ignore (82%) rename tools/legal-review/{engine/org.scala-lang.scala-compiler-2.13.11 => project-manager/org.scala-lang.scala-compiler-2.13.15}/copyright-keep (79%) create mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license create mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/files-keep delete mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/files-ignore rename tools/legal-review/{engine/org.scala-lang.scala-library-2.13.11 => project-manager/org.scala-lang.scala-library-2.13.15}/copyright-ignore (79%) rename tools/legal-review/project-manager/{org.scala-lang.scala-library-2.13.11 => org.scala-lang.scala-library-2.13.15}/copyright-keep (100%) create mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/default-and-custom-license create mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/files-keep delete mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.11/files-ignore rename tools/legal-review/project-manager/{org.scala-lang.scala-reflect-2.13.11 => org.scala-lang.scala-reflect-2.13.15}/copyright-keep (100%) create mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license create mode 100644 tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/files-keep diff --git a/build.sbt b/build.sbt index 758ae5cd9415..a7491b8881c3 100644 --- a/build.sbt +++ b/build.sbt @@ -26,7 +26,7 @@ import java.nio.file.Paths // === Global Configuration =================================================== // ============================================================================ -val scalacVersion = "2.13.11" +val scalacVersion = "2.13.15" // source version of the Java language val javaVersion = "21" // version of the GraalVM JDK @@ -603,18 +603,18 @@ val diffsonVersion = "4.4.0" val directoryWatcherVersion = "0.18.0" val flatbuffersVersion = "24.3.25" val guavaVersion = "32.0.0-jre" -val jlineVersion = "3.23.0" +val jlineVersion = "3.26.3" val jgitVersion = "6.7.0.202309050840-r" -val kindProjectorVersion = "0.13.2" +val kindProjectorVersion = "0.13.3" val mockitoScalaVersion = "1.17.14" val newtypeVersion = "0.4.4" val pprintVersion = "0.8.1" val pureconfigVersion = "0.17.4" -val scalacheckVersion = "1.17.0" -val scalacticVersion = "3.3.0-SNAP4" +val scalacheckVersion = "1.18.1" +val scalacticVersion = "3.2.19" val scalaLoggingVersion = "3.9.4" val scalameterVersion = "0.19" -val scalatestVersion = "3.3.0-SNAP4" +val scalatestVersion = "3.2.19" val slf4jVersion = JPMSUtils.slf4jVersion val sqliteVersion = "3.46.1.0" val tikaVersion = "2.4.1" @@ -1693,8 +1693,8 @@ lazy val `project-manager` = (project in file("lib/scala/project-manager")) ourFullCp, pkgsToExclude, streams.value.log, - scalaBinaryVersion.value, - moduleName.value + moduleName.value, + scalaBinaryVersion.value ) }, assembly / assemblyMergeStrategy := { @@ -1750,6 +1750,7 @@ lazy val `project-manager` = (project in file("lib/scala/project-manager")) "project-manager", staticOnLinux = true, initializeAtRuntime = Seq( + "org.jline", "scala.util.Random", "zio.internal.ZScheduler$$anon$4", "zio.Runtime$", @@ -3789,6 +3790,9 @@ lazy val launcher = project .buildNativeImage( "ensoup", staticOnLinux = true, + initializeAtRuntime = Seq( + "org.jline" + ), additionalOptions = Seq( "-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog", "-H:IncludeResources=.*Main.enso$" diff --git a/distribution/engine/THIRD-PARTY/NOTICE b/distribution/engine/THIRD-PARTY/NOTICE index 8f0701367375..e6174fdd8e3a 100644 --- a/distribution/engine/THIRD-PARTY/NOTICE +++ b/distribution/engine/THIRD-PARTY/NOTICE @@ -508,7 +508,7 @@ Copyright notices related to this dependency can be found in the directory `org. 'jline', licensed under the The BSD License, is distributed with the engine. The license file can be found at `licenses/BSD-3-Clause`. -Copyright notices related to this dependency can be found in the directory `org.jline.jline-3.23.0`. +Copyright notices related to this dependency can be found in the directory `org.jline.jline-3.26.3`. 'org-netbeans-modules-sampler', licensed under the The Apache Software License, Version 2.0, is distributed with the engine. @@ -543,17 +543,17 @@ Copyright notices related to this dependency can be found in the directory `org. 'scala-compiler', licensed under the Apache-2.0, is distributed with the engine. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-compiler-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-compiler-2.13.15`. 'scala-library', licensed under the Apache-2.0, is distributed with the engine. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-library-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-library-2.13.15`. 'scala-reflect', licensed under the Apache-2.0, is distributed with the engine. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-reflect-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-reflect-2.13.15`. 'slf4j-api', licensed under the MIT License, is distributed with the engine. diff --git a/distribution/engine/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES b/distribution/engine/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES deleted file mode 100644 index bf184a2877ab..000000000000 --- a/distribution/engine/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES +++ /dev/null @@ -1,3 +0,0 @@ -Copyright (C) 2022 the original author(s). - -Copyright (c) 2000-2005 Dieter Wimberger diff --git a/tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep b/distribution/engine/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES similarity index 67% rename from tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep rename to distribution/engine/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES index eb81f73fb954..5cf1d7180f6d 100644 --- a/tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep +++ b/distribution/engine/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES @@ -1,17 +1,49 @@ Copyright (C) 2022 the original author(s). + +Copyright (c) 2000-2005 Dieter Wimberger + Copyright (c) 2002-2016, the original author or authors. + Copyright (c) 2002-2016, the original author(s). + +Copyright (c) 2002-2017, the original author(s). + Copyright (c) 2002-2018, the original author or authors. + Copyright (c) 2002-2018, the original author(s). + Copyright (c) 2002-2019, the original author(s). + Copyright (c) 2002-2020, the original author or authors. + Copyright (c) 2002-2020, the original author(s). + +Copyright (c) 2002-2021, the original author or authors. + Copyright (c) 2002-2021, the original author(s). + +Copyright (c) 2002-2022, the original author or authors. + Copyright (c) 2002-2022, the original author(s). + Copyright (c) 2002-2023, the original author(s). + +Copyright (c) 2002-2024, the original author(s). + Copyright (c) 2009-2018, the original author(s). + +Copyright (c) 2009-2023, the original author(s). + Copyright (c) 2022, the original author(s). + +Copyright (c) 2022-2023, the original author(s). + +Copyright (c) 2023, the original author or authors. + Copyright (c) 2023, the original author(s). + Copyright 2019 the original author or authors. + regarding copyright ownership. The ASF licenses this file + this work for additional information regarding copyright ownership. diff --git a/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/LICENSE b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE similarity index 100% rename from distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/LICENSE rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE similarity index 89% rename from distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE index 5bceee7b366a..22457ecf1a2d 100644 --- a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE +++ b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE @@ -1,6 +1,6 @@ Scala -Copyright (c) 2002-2023 EPFL -Copyright (c) 2011-2023 Lightbend, Inc. +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. Scala includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICES b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICES similarity index 100% rename from distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICES rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICES diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/LICENSE b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE similarity index 100% rename from distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/LICENSE rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE diff --git a/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE similarity index 89% rename from distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE index 5bceee7b366a..22457ecf1a2d 100644 --- a/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE +++ b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE @@ -1,6 +1,6 @@ Scala -Copyright (c) 2002-2023 EPFL -Copyright (c) 2011-2023 Lightbend, Inc. +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. Scala includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and diff --git a/distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.11/NOTICES b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICES similarity index 100% rename from distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.11/NOTICES rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICES diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/LICENSE b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE similarity index 100% rename from distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/LICENSE rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE similarity index 89% rename from distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE index 5bceee7b366a..22457ecf1a2d 100644 --- a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICE +++ b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE @@ -1,6 +1,6 @@ Scala -Copyright (c) 2002-2023 EPFL -Copyright (c) 2011-2023 Lightbend, Inc. +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. Scala includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and diff --git a/distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.11/NOTICES b/distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICES similarity index 100% rename from distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.11/NOTICES rename to distribution/engine/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICES diff --git a/distribution/launcher/THIRD-PARTY/NOTICE b/distribution/launcher/THIRD-PARTY/NOTICE index b09d657a906e..095eac616b0a 100644 --- a/distribution/launcher/THIRD-PARTY/NOTICE +++ b/distribution/launcher/THIRD-PARTY/NOTICE @@ -98,7 +98,7 @@ Copyright notices related to this dependency can be found in the directory `org. 'jline', licensed under the The BSD License, is distributed with the launcher. The license file can be found at `licenses/BSD-3-Clause`. -Copyright notices related to this dependency can be found in the directory `org.jline.jline-3.23.0`. +Copyright notices related to this dependency can be found in the directory `org.jline.jline-3.26.3`. 'scala-java8-compat_2.13', licensed under the Apache-2.0, is distributed with the launcher. @@ -108,17 +108,17 @@ Copyright notices related to this dependency can be found in the directory `org. 'scala-compiler', licensed under the Apache-2.0, is distributed with the launcher. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-compiler-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-compiler-2.13.15`. 'scala-library', licensed under the Apache-2.0, is distributed with the launcher. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-library-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-library-2.13.15`. 'scala-reflect', licensed under the Apache-2.0, is distributed with the launcher. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-reflect-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-reflect-2.13.15`. 'slf4j-api', licensed under the MIT License, is distributed with the launcher. diff --git a/distribution/launcher/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES b/distribution/launcher/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES new file mode 100644 index 000000000000..5cf1d7180f6d --- /dev/null +++ b/distribution/launcher/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES @@ -0,0 +1,49 @@ +Copyright (C) 2022 the original author(s). + +Copyright (c) 2000-2005 Dieter Wimberger + +Copyright (c) 2002-2016, the original author or authors. + +Copyright (c) 2002-2016, the original author(s). + +Copyright (c) 2002-2017, the original author(s). + +Copyright (c) 2002-2018, the original author or authors. + +Copyright (c) 2002-2018, the original author(s). + +Copyright (c) 2002-2019, the original author(s). + +Copyright (c) 2002-2020, the original author or authors. + +Copyright (c) 2002-2020, the original author(s). + +Copyright (c) 2002-2021, the original author or authors. + +Copyright (c) 2002-2021, the original author(s). + +Copyright (c) 2002-2022, the original author or authors. + +Copyright (c) 2002-2022, the original author(s). + +Copyright (c) 2002-2023, the original author(s). + +Copyright (c) 2002-2024, the original author(s). + +Copyright (c) 2009-2018, the original author(s). + +Copyright (c) 2009-2023, the original author(s). + +Copyright (c) 2022, the original author(s). + +Copyright (c) 2022-2023, the original author(s). + +Copyright (c) 2023, the original author or authors. + +Copyright (c) 2023, the original author(s). + +Copyright 2019 the original author or authors. + +regarding copyright ownership. The ASF licenses this file + +this work for additional information regarding copyright ownership. diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE new file mode 100644 index 000000000000..261eeb9e9f8b --- /dev/null +++ b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE new file mode 100644 index 000000000000..22457ecf1a2d --- /dev/null +++ b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE @@ -0,0 +1,16 @@ +Scala +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. + +Scala includes software developed at +LAMP/EPFL (https://lamp.epfl.ch/) and +Lightbend, Inc. (https://www.lightbend.com/). + +Licensed under the Apache License, Version 2.0 (the "License"). +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. + +This software includes projects with other licenses -- see `doc/LICENSE.md`. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICES b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICES similarity index 100% rename from distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICES rename to distribution/launcher/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICES diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE new file mode 100644 index 000000000000..261eeb9e9f8b --- /dev/null +++ b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE new file mode 100644 index 000000000000..22457ecf1a2d --- /dev/null +++ b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE @@ -0,0 +1,16 @@ +Scala +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. + +Scala includes software developed at +LAMP/EPFL (https://lamp.epfl.ch/) and +Lightbend, Inc. (https://www.lightbend.com/). + +Licensed under the Apache License, Version 2.0 (the "License"). +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. + +This software includes projects with other licenses -- see `doc/LICENSE.md`. diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.11/NOTICES b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICES similarity index 100% rename from distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.11/NOTICES rename to distribution/launcher/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICES diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE new file mode 100644 index 000000000000..261eeb9e9f8b --- /dev/null +++ b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE new file mode 100644 index 000000000000..22457ecf1a2d --- /dev/null +++ b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE @@ -0,0 +1,16 @@ +Scala +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. + +Scala includes software developed at +LAMP/EPFL (https://lamp.epfl.ch/) and +Lightbend, Inc. (https://www.lightbend.com/). + +Licensed under the Apache License, Version 2.0 (the "License"). +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. + +This software includes projects with other licenses -- see `doc/LICENSE.md`. diff --git a/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.11/NOTICES b/distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICES similarity index 100% rename from distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.11/NOTICES rename to distribution/launcher/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICES diff --git a/distribution/project-manager/THIRD-PARTY/NOTICE b/distribution/project-manager/THIRD-PARTY/NOTICE index 0646f4065546..c00e8922ba01 100644 --- a/distribution/project-manager/THIRD-PARTY/NOTICE +++ b/distribution/project-manager/THIRD-PARTY/NOTICE @@ -363,7 +363,7 @@ Copyright notices related to this dependency can be found in the directory `org. 'jline', licensed under the The BSD License, is distributed with the project-manager. The license file can be found at `licenses/BSD-3-Clause`. -Copyright notices related to this dependency can be found in the directory `org.jline.jline-3.23.0`. +Copyright notices related to this dependency can be found in the directory `org.jline.jline-3.26.3`. 'reactive-streams', licensed under the CC0, is distributed with the project-manager. @@ -383,17 +383,17 @@ Copyright notices related to this dependency can be found in the directory `org. 'scala-compiler', licensed under the Apache-2.0, is distributed with the project-manager. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-compiler-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-compiler-2.13.15`. 'scala-library', licensed under the Apache-2.0, is distributed with the project-manager. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-library-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-library-2.13.15`. 'scala-reflect', licensed under the Apache-2.0, is distributed with the project-manager. The license file can be found at `licenses/APACHE2.0`. -Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-reflect-2.13.11`. +Copyright notices related to this dependency can be found in the directory `org.scala-lang.scala-reflect-2.13.15`. 'slf4j-api', licensed under the MIT License, is distributed with the project-manager. diff --git a/distribution/project-manager/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES b/distribution/project-manager/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES deleted file mode 100644 index 8d779e074170..000000000000 --- a/distribution/project-manager/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2002-2017, the original author(s). - * - * This software is distributable under the BSD license. See the terms of the - * BSD license in the documentation provided with this software. - * - * https://opensource.org/licenses/BSD-3-Clause - */ - -/* - * Java TelnetD library (embeddable telnet daemon) - * Copyright (c) 2000-2005 Dieter Wimberger - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * Neither the name of the author nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS - * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - ***/ - -Copyright (C) 2022 the original author(s). - -Copyright (c) 2002-2016, the original author or authors. - -Copyright (c) 2002-2016, the original author(s). - -Copyright (c) 2002-2018, the original author or authors. - -Copyright (c) 2002-2018, the original author(s). - -Copyright (c) 2002-2019, the original author(s). - -Copyright (c) 2002-2020, the original author or authors. - -Copyright (c) 2002-2020, the original author(s). - -Copyright (c) 2002-2021, the original author(s). - -Copyright (c) 2002-2022, the original author(s). - -Copyright (c) 2002-2023, the original author(s). - -Copyright (c) 2009-2018, the original author(s). - -Copyright (c) 2022, the original author(s). - -Copyright (c) 2023, the original author(s). - -Copyright 2019 the original author or authors. - -regarding copyright ownership. The ASF licenses this file - -this work for additional information regarding copyright ownership. diff --git a/distribution/project-manager/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES b/distribution/project-manager/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES new file mode 100644 index 000000000000..5cf1d7180f6d --- /dev/null +++ b/distribution/project-manager/THIRD-PARTY/org.jline.jline-3.26.3/NOTICES @@ -0,0 +1,49 @@ +Copyright (C) 2022 the original author(s). + +Copyright (c) 2000-2005 Dieter Wimberger + +Copyright (c) 2002-2016, the original author or authors. + +Copyright (c) 2002-2016, the original author(s). + +Copyright (c) 2002-2017, the original author(s). + +Copyright (c) 2002-2018, the original author or authors. + +Copyright (c) 2002-2018, the original author(s). + +Copyright (c) 2002-2019, the original author(s). + +Copyright (c) 2002-2020, the original author or authors. + +Copyright (c) 2002-2020, the original author(s). + +Copyright (c) 2002-2021, the original author or authors. + +Copyright (c) 2002-2021, the original author(s). + +Copyright (c) 2002-2022, the original author or authors. + +Copyright (c) 2002-2022, the original author(s). + +Copyright (c) 2002-2023, the original author(s). + +Copyright (c) 2002-2024, the original author(s). + +Copyright (c) 2009-2018, the original author(s). + +Copyright (c) 2009-2023, the original author(s). + +Copyright (c) 2022, the original author(s). + +Copyright (c) 2022-2023, the original author(s). + +Copyright (c) 2023, the original author or authors. + +Copyright (c) 2023, the original author(s). + +Copyright 2019 the original author or authors. + +regarding copyright ownership. The ASF licenses this file + +this work for additional information regarding copyright ownership. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE new file mode 100644 index 000000000000..261eeb9e9f8b --- /dev/null +++ b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE new file mode 100644 index 000000000000..22457ecf1a2d --- /dev/null +++ b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICE @@ -0,0 +1,16 @@ +Scala +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. + +Scala includes software developed at +LAMP/EPFL (https://lamp.epfl.ch/) and +Lightbend, Inc. (https://www.lightbend.com/). + +Licensed under the Apache License, Version 2.0 (the "License"). +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. + +This software includes projects with other licenses -- see `doc/LICENSE.md`. diff --git a/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICES b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICES similarity index 79% rename from distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICES rename to distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICES index ffad47f71a4d..28f3becac42a 100644 --- a/distribution/engine/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.11/NOTICES +++ b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-compiler-2.13.15/NOTICES @@ -7,3 +7,5 @@ Copyright 2005-2017 LAMP/EPFL and Lightbend, Inc Copyright 2005-2017 LAMP/EPFL and Lightbend, Inc. Copyright EPFL and Lightbend, Inc. + +additional information regarding copyright ownership. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE new file mode 100644 index 000000000000..261eeb9e9f8b --- /dev/null +++ b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE new file mode 100644 index 000000000000..22457ecf1a2d --- /dev/null +++ b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICE @@ -0,0 +1,16 @@ +Scala +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. + +Scala includes software developed at +LAMP/EPFL (https://lamp.epfl.ch/) and +Lightbend, Inc. (https://www.lightbend.com/). + +Licensed under the Apache License, Version 2.0 (the "License"). +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. + +This software includes projects with other licenses -- see `doc/LICENSE.md`. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.11/NOTICES b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICES similarity index 100% rename from distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.11/NOTICES rename to distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-library-2.13.15/NOTICES diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE new file mode 100644 index 000000000000..261eeb9e9f8b --- /dev/null +++ b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE new file mode 100644 index 000000000000..22457ecf1a2d --- /dev/null +++ b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICE @@ -0,0 +1,16 @@ +Scala +Copyright (c) 2002-2024 EPFL +Copyright (c) 2011-2024 Lightbend, Inc. + +Scala includes software developed at +LAMP/EPFL (https://lamp.epfl.ch/) and +Lightbend, Inc. (https://www.lightbend.com/). + +Licensed under the Apache License, Version 2.0 (the "License"). +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. + +This software includes projects with other licenses -- see `doc/LICENSE.md`. diff --git a/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.11/NOTICES b/distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICES similarity index 100% rename from distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.11/NOTICES rename to distribution/project-manager/THIRD-PARTY/org.scala-lang.scala-reflect-2.13.15/NOTICES diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/Compiler.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/Compiler.scala index 8df72d828b26..467306ebfbf5 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/Compiler.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/Compiler.scala @@ -279,7 +279,7 @@ class Compiler( context.log( Compiler.defaultLogLevel, "{0} imported module caches were invalided, forcing invalidation of {1}. [{2}]", - Array( + Array[Any]( importedModulesLoadedFromSource.length, context.getModuleName(module).toString, importedModulesLoadedFromSource.take(10).mkString("", ",", "...") diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/JobExecutionEngine.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/JobExecutionEngine.scala index d7b090543722..d5b528a11ee8 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/JobExecutionEngine.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/JobExecutionEngine.scala @@ -237,7 +237,7 @@ final class JobExecutionEngine( logger.log( Level.FINE, s"Submitting job: {0} with {1} id...", - Array(job, jobId) + Array[AnyRef](job, jobId) ) val future = executorService.submit(() => { logger.log(Level.FINE, s"Executing job: {0}...", job) @@ -245,7 +245,11 @@ final class JobExecutionEngine( try { val result = job.run(runtimeContext) val took = System.currentTimeMillis() - before - logger.log(Level.FINE, s"Job {0} finished in {1} ms.", Array(job, took)) + logger.log( + Level.FINE, + s"Job {0} finished in {1} ms.", + Array[Any](job, took) + ) promise.success(result) } catch { case NonFatal(ex) => diff --git a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/jni-config.json b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/jni-config.json index 3da6f910c917..6fc141ea0b16 100644 --- a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/jni-config.json +++ b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/jni-config.json @@ -1,15 +1,16 @@ [ - { - "name": "java.lang.ClassLoader", - "methods": [ - { "name": "getPlatformClassLoader", "parameterTypes": [] }, - { "name": "loadClass", "parameterTypes": ["java.lang.String"] } - ] - }, - { - "name": "java.lang.ClassNotFoundException" - }, - { - "name": "java.lang.NoSuchMethodError" - } +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getPlatformClassLoader","parameterTypes":[] }, {"name":"loadClass","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.ClassNotFoundException" +}, +{ + "name":"java.lang.NoSuchMethodError" +} ] diff --git a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/proxy-config.json b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/proxy-config.json index fe51488c7066..0d4f101c7a37 100644 --- a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/proxy-config.json +++ b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/proxy-config.json @@ -1 +1,2 @@ -[] +[ +] diff --git a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/reflect-config.json b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/reflect-config.json index 2303fa6cf34d..c5f3b34aa4ed 100644 --- a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/reflect-config.json +++ b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/reflect-config.json @@ -1,527 +1,732 @@ [ - { - "name":"akka.actor.ActorCell", - "fields":[{"name":"akka$actor$dungeon$Children$$_childrenRefsDoNotCallMeDirectly"}, {"name":"akka$actor$dungeon$Children$$_functionRefsDoNotCallMeDirectly"}, {"name":"akka$actor$dungeon$Children$$_nextNameDoNotCallMeDirectly"}, {"name":"akka$actor$dungeon$Dispatch$$_mailboxDoNotCallMeDirectly"}] - }, - { - "name":"akka.actor.DefaultSupervisorStrategy", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"akka.actor.LightArrayRevolverScheduler", - "methods":[{"name":"","parameterTypes":["com.typesafe.config.Config","akka.event.LoggingAdapter","java.util.concurrent.ThreadFactory"] }] - }, - { - "name":"akka.actor.LightArrayRevolverScheduler$TaskHolder", - "fields":[{"name":"task"}] - }, - { - "name":"akka.actor.LocalActorRefProvider", - "methods":[{"name":"","parameterTypes":["java.lang.String","akka.actor.ActorSystem$Settings","akka.event.EventStream","akka.actor.DynamicAccess"] }] - }, - { - "name":"akka.actor.LocalActorRefProvider$Guardian", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.actor.SupervisorStrategy"] }] - }, - { - "name":"akka.actor.LocalActorRefProvider$SystemGuardian", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.actor.SupervisorStrategy","akka.actor.ActorRef"] }] - }, - { - "name":"akka.actor.Props$EmptyActor", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"akka.actor.RepointableActorRef", - "fields":[{"name":"_cellDoNotCallMeDirectly"}, {"name":"_lookupDoNotCallMeDirectly"}] - }, - { - "name":"akka.dispatch.AbstractNodeQueue", - "fields":[{"name":"_tailDoNotCallMeDirectly"}] - }, - { - "name":"akka.dispatch.AbstractNodeQueue$Node", - "fields":[{"name":"_nextDoNotCallMeDirectly"}] - }, - { - "name":"akka.dispatch.BoundedControlAwareMessageQueueSemantics" - }, - { - "name":"akka.dispatch.BoundedDequeBasedMessageQueueSemantics" - }, - { - "name":"akka.dispatch.BoundedMessageQueueSemantics" - }, - { - "name":"akka.dispatch.ControlAwareMessageQueueSemantics" - }, - { - "name":"akka.dispatch.DequeBasedMessageQueueSemantics" - }, - { - "name":"akka.dispatch.Dispatcher", - "fields":[{"name":"executorServiceDelegate"}] - }, - { - "name":"akka.dispatch.Mailbox", - "fields":[{"name":"_statusDoNotCallMeDirectly"}, {"name":"_systemQueueDoNotCallMeDirectly"}] - }, - { - "name":"akka.dispatch.MessageDispatcher", - "fields":[{"name":"_inhabitantsDoNotCallMeDirectly"}, {"name":"_shutdownScheduleDoNotCallMeDirectly"}] - }, - { - "name":"akka.dispatch.MultipleConsumerSemantics" - }, - { - "name":"akka.dispatch.UnboundedControlAwareMessageQueueSemantics" - }, - { - "name":"akka.dispatch.UnboundedDequeBasedMailbox", - "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","com.typesafe.config.Config"] }] - }, - { - "name":"akka.dispatch.UnboundedDequeBasedMessageQueueSemantics" - }, - { - "name":"akka.dispatch.UnboundedMailbox", - "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","com.typesafe.config.Config"] }] - }, - { - "name":"akka.dispatch.UnboundedMessageQueueSemantics" - }, - { - "name":"akka.event.DeadLetterListener", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"akka.event.DefaultLoggingFilter", - "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","akka.event.EventStream"] }] - }, - { - "name":"akka.event.EventStreamUnsubscriber", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.event.EventStream","boolean"] }] - }, - { - "name":"akka.event.LoggerMailboxType", - "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","com.typesafe.config.Config"] }] - }, - { - "name":"akka.event.LoggerMessageQueueSemantics" - }, - { - "name":"akka.event.Logging$DefaultLogger", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"akka.http.DefaultParsingErrorHandler$", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"akka.http.impl.engine.client.PoolMasterActor", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"akka.io.InetAddressDnsProvider", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"akka.io.InetAddressDnsResolver", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.io.SimpleDnsCache","com.typesafe.config.Config"] }] - }, - { - "name":"akka.io.SelectionHandler", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.io.SelectionHandlerSettings"] }] - }, - { - "name":"akka.io.SimpleDnsManager", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.io.DnsExt"] }] - }, - { - "name":"akka.io.TcpIncomingConnection", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.io.TcpExt","java.nio.channels.SocketChannel","akka.io.ChannelRegistry","akka.actor.ActorRef","scala.collection.immutable.Iterable","boolean"] }] - }, - { - "name":"akka.io.TcpListener", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.actor.ActorRef","akka.io.TcpExt","akka.io.ChannelRegistry","akka.actor.ActorRef","akka.io.Tcp$Bind"] }] - }, - { - "name":"akka.io.TcpManager", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.io.TcpExt"] }] - }, - { - "name":"akka.io.TcpOutgoingConnection", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.io.TcpExt","akka.io.ChannelRegistry","akka.actor.ActorRef","akka.io.Tcp$Connect"] }] - }, - { - "name":"akka.pattern.PromiseActorRef", - "fields":[{"name":"_stateDoNotCallMeDirectly"}, {"name":"_watchedByDoNotCallMeDirectly"}] - }, - { - "name":"akka.routing.ConsistentHashingPool", - "methods":[{"name":"","parameterTypes":["com.typesafe.config.Config"] }] - }, - { - "name":"akka.routing.RoundRobinPool", - "methods":[{"name":"","parameterTypes":["com.typesafe.config.Config"] }] - }, - { - "name":"akka.routing.RoutedActorCell$RouterActorCreator", - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["akka.routing.RouterConfig"] }] - }, - { - "name":"akka.serialization.BooleanSerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.serialization.ByteArraySerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.serialization.ByteStringSerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.serialization.DisabledJavaSerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.serialization.IntSerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.serialization.LongSerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.serialization.SerializationExtension$", - "fields":[{"name":"MODULE$"}] - }, - { - "name":"akka.serialization.StringSerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.stream.SinkRef" - }, - { - "name":"akka.stream.SourceRef" - }, - { - "name":"akka.stream.SystemMaterializer$", - "fields":[{"name":"MODULE$"}] - }, - { - "name":"akka.stream.impl.streamref.StreamRefsProtocol" - }, - { - "name":"akka.stream.serialization.StreamRefSerializer", - "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] - }, - { - "name":"akka.util.ByteString$ByteString1" - }, - { - "name":"akka.util.ByteString$ByteString1C" - }, - { - "name":"akka.util.ByteString$ByteStrings" - }, - { - "name": "com.sun.crypto.provider.TlsMasterSecretGenerator", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "com.typesafe.sslconfig.ssl.NoopHostnameVerifier", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { "name": "java.io.Serializable" }, - { "name": "java.lang.Boolean" }, - { "name": "java.lang.Class[]" }, - { "name": "java.lang.Integer" }, - { "name": "java.lang.Long" }, - { "name": "java.lang.Object[]" }, - { - "name": "java.lang.String", - "fields": [{ "name": "value", "allowUnsafeAccess": true }] - }, - { "name": "java.lang.String[]" }, - { "name": "java.lang.invoke.VarHandle" }, - { "name": "java.nio.file.Path[]" }, - { "name": "java.security.AlgorithmParametersSpi" }, - { "name": "java.security.KeyStoreSpi" }, - { "name": "java.security.MessageDigestSpi" }, - { "name": "java.security.SecureRandomParameters" }, - { "name": "java.sql.Date" }, - { "name": "java.sql.Timestamp" }, - { "name": "javax.net.ssl.KeyManager[]" }, - { "name": "javax.net.ssl.TrustManager[]" }, - { - "name": "javax.security.auth.x500.X500Principal", - "fields": [{ "name": "thisX500Name" }], - "methods": [ - { "name": "", "parameterTypes": ["sun.security.x509.X500Name"] } - ] - }, - { - "name": "org.apache.commons.compress.archivers.zip.AsiExtraField", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.JarMarker", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.ResourceAlignmentExtraField", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.UnicodeCommentExtraField", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.UnicodePathExtraField", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X000A_NTFS", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X0014_X509Certificates", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X0015_CertificateIdForFile", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X0016_CertificateIdForCentralDirectory", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X0017_StrongEncryptionHeader", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X0019_EncryptionRecipientCertificateList", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X5455_ExtendedTimestamp", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.X7875_NewUnix", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "org.apache.commons.compress.archivers.zip.Zip64ExtendedInformationExtraField", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { "name": "scala.Boolean" }, - { "name": "scala.Int" }, - { "name": "scala.Long" }, - { "name": "scala.Symbol" }, - { "name": "scala.Tuple2[]" }, - { "name": "sun.misc.Unsafe", "allDeclaredFields": true }, - { - "name": "sun.security.pkcs12.PKCS12KeyStore", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.provider.JavaKeyStore$JKS", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.provider.NativePRNG", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.provider.SHA", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.provider.X509Factory", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.rsa.RSAKeyFactory$Legacy", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.ssl.KeyManagerFactoryImpl$SunX509", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.ssl.SSLContextImpl$DefaultSSLContext", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.ssl.SSLContextImpl$TLS12Context", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", - "methods": [{ "name": "", "parameterTypes": [] }] - }, - { - "name": "sun.security.x509.AuthorityInfoAccessExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.AuthorityKeyIdentifierExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.BasicConstraintsExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.CRLDistributionPointsExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.CertificatePoliciesExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.ExtendedKeyUsageExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.IssuerAlternativeNameExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.KeyUsageExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.NetscapeCertTypeExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.PrivateKeyUsageExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.SubjectAlternativeNameExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name": "sun.security.x509.SubjectKeyIdentifierExtension", - "methods": [ - { - "name": "", - "parameterTypes": ["java.lang.Boolean", "java.lang.Object"] - } - ] - }, - { - "name":"org.enso.logger.LogbackSetup", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.classic.pattern.DateConverter", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.classic.pattern.LevelConverter", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.classic.pattern.LineSeparatorConverter", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.classic.pattern.LoggerConverter", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.classic.pattern.NopThrowableInformationConverter", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.classic.pattern.MessageConverter", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.core.rolling.helper.DateTokenConverter", - "methods":[{"name":"","parameterTypes":[] }] - }, - { - "name":"ch.qos.logback.core.rolling.helper.IntegerTokenConverter", - "methods":[{"name":"","parameterTypes":[] }] - } +{ + "name":"[B" +}, +{ + "name":"[Lakka.actor.LightArrayRevolverScheduler$TaskQueue;" +}, +{ + "name":"[Lakka.io.dns.RecordType;" +}, +{ + "name":"[Lakka.routing.ConsistentRoutee;" +}, +{ + "name":"[Lakka.stream.stage.GraphStageLogic;" +}, +{ + "name":"[Ljava.lang.Class;" +}, +{ + "name":"[Ljava.lang.ProcessHandle;" +}, +{ + "name":"[Ljava.lang.String;" +}, +{ + "name":"[Ljava.lang.reflect.Field;" +}, +{ + "name":"[Ljava.lang.reflect.Method;" +}, +{ + "name":"[Ljava.nio.file.Path;" +}, +{ + "name":"[Lscala.Tuple2;" +}, +{ + "name":"[Lzio.ZIO$EvaluationStep;" +}, +{ + "name":"[Lzio.internal.ZScheduler$Worker;" +}, +{ + "name":"akka.actor.ActorCell", + "fields":[{"name":"akka$actor$dungeon$Children$$_childrenRefsDoNotCallMeDirectly"}, {"name":"akka$actor$dungeon$Children$$_functionRefsDoNotCallMeDirectly"}, {"name":"akka$actor$dungeon$Children$$_nextNameDoNotCallMeDirectly"}, {"name":"akka$actor$dungeon$Dispatch$$_mailboxDoNotCallMeDirectly"}] +}, +{ + "name":"akka.actor.DefaultSupervisorStrategy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.actor.LightArrayRevolverScheduler", + "methods":[{"name":"","parameterTypes":["com.typesafe.config.Config","akka.event.LoggingAdapter","java.util.concurrent.ThreadFactory"] }] +}, +{ + "name":"akka.actor.LightArrayRevolverScheduler$TaskHolder", + "fields":[{"name":"task"}] +}, +{ + "name":"akka.actor.LocalActorRefProvider", + "methods":[{"name":"","parameterTypes":["java.lang.String","akka.actor.ActorSystem$Settings","akka.event.EventStream","akka.actor.DynamicAccess"] }] +}, +{ + "name":"akka.actor.LocalActorRefProvider$Guardian", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.actor.SupervisorStrategy"] }] +}, +{ + "name":"akka.actor.LocalActorRefProvider$SystemGuardian", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.actor.SupervisorStrategy","akka.actor.ActorRef"] }] +}, +{ + "name":"akka.actor.Props$EmptyActor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.actor.RepointableActorRef", + "fields":[{"name":"_cellDoNotCallMeDirectly"}, {"name":"_lookupDoNotCallMeDirectly"}] +}, +{ + "name":"akka.dispatch.AbstractNodeQueue", + "fields":[{"name":"_tailDoNotCallMeDirectly"}] +}, +{ + "name":"akka.dispatch.AbstractNodeQueue$Node", + "fields":[{"name":"_nextDoNotCallMeDirectly"}] +}, +{ + "name":"akka.dispatch.BoundedControlAwareMessageQueueSemantics" +}, +{ + "name":"akka.dispatch.BoundedDequeBasedMessageQueueSemantics" +}, +{ + "name":"akka.dispatch.BoundedMessageQueueSemantics" +}, +{ + "name":"akka.dispatch.ControlAwareMessageQueueSemantics" +}, +{ + "name":"akka.dispatch.DequeBasedMessageQueueSemantics" +}, +{ + "name":"akka.dispatch.Dispatcher", + "fields":[{"name":"executorServiceDelegate"}] +}, +{ + "name":"akka.dispatch.Mailbox", + "fields":[{"name":"_statusDoNotCallMeDirectly"}, {"name":"_systemQueueDoNotCallMeDirectly"}] +}, +{ + "name":"akka.dispatch.MessageDispatcher", + "fields":[{"name":"_inhabitantsDoNotCallMeDirectly"}, {"name":"_shutdownScheduleDoNotCallMeDirectly"}] +}, +{ + "name":"akka.dispatch.MultipleConsumerSemantics" +}, +{ + "name":"akka.dispatch.UnboundedControlAwareMessageQueueSemantics" +}, +{ + "name":"akka.dispatch.UnboundedDequeBasedMailbox", + "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","com.typesafe.config.Config"] }] +}, +{ + "name":"akka.dispatch.UnboundedDequeBasedMessageQueueSemantics" +}, +{ + "name":"akka.dispatch.UnboundedMailbox", + "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","com.typesafe.config.Config"] }] +}, +{ + "name":"akka.dispatch.UnboundedMessageQueueSemantics" +}, +{ + "name":"akka.event.DeadLetterListener", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.event.DefaultLoggingFilter", + "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","akka.event.EventStream"] }] +}, +{ + "name":"akka.event.EventStreamUnsubscriber", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.event.EventStream","boolean"] }] +}, +{ + "name":"akka.event.LoggerMailboxType", + "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","com.typesafe.config.Config"] }] +}, +{ + "name":"akka.event.LoggerMessageQueueSemantics" +}, +{ + "name":"akka.event.Logging$DefaultLogger", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.event.slf4j.Slf4jLogger", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.event.slf4j.Slf4jLoggingFilter", + "methods":[{"name":"","parameterTypes":["akka.actor.ActorSystem$Settings","akka.event.EventStream"] }] +}, +{ + "name":"akka.http.DefaultParsingErrorHandler$", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.http.impl.engine.client.PoolMasterActor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.io.InetAddressDnsProvider", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"akka.io.InetAddressDnsResolver", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.io.SimpleDnsCache","com.typesafe.config.Config"] }] +}, +{ + "name":"akka.io.SelectionHandler", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.io.SelectionHandlerSettings"] }] +}, +{ + "name":"akka.io.SimpleDnsManager", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.io.DnsExt"] }] +}, +{ + "name":"akka.io.TcpIncomingConnection", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.io.TcpExt","java.nio.channels.SocketChannel","akka.io.ChannelRegistry","akka.actor.ActorRef","scala.collection.immutable.Iterable","boolean"] }] +}, +{ + "name":"akka.io.TcpListener", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.actor.ActorRef","akka.io.TcpExt","akka.io.ChannelRegistry","akka.actor.ActorRef","akka.io.Tcp$Bind"] }] +}, +{ + "name":"akka.io.TcpManager", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.io.TcpExt"] }] +}, +{ + "name":"akka.io.TcpOutgoingConnection", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.io.TcpExt","akka.io.ChannelRegistry","akka.actor.ActorRef","akka.io.Tcp$Connect"] }] +}, +{ + "name":"akka.pattern.PromiseActorRef", + "fields":[{"name":"_stateDoNotCallMeDirectly"}, {"name":"_watchedByDoNotCallMeDirectly"}] +}, +{ + "name":"akka.routing.ConsistentHashingPool", + "methods":[{"name":"","parameterTypes":["com.typesafe.config.Config"] }] +}, +{ + "name":"akka.routing.RoundRobinPool", + "methods":[{"name":"","parameterTypes":["com.typesafe.config.Config"] }] +}, +{ + "name":"akka.routing.RoutedActorCell$RouterActorCreator", + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":["akka.routing.RouterConfig"] }] +}, +{ + "name":"akka.serialization.BooleanSerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.serialization.ByteArraySerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.serialization.ByteStringSerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.serialization.DisabledJavaSerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.serialization.IntSerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.serialization.LongSerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.serialization.SerializationExtension$", + "fields":[{"name":"MODULE$"}] +}, +{ + "name":"akka.serialization.StringSerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.stream.SinkRef" +}, +{ + "name":"akka.stream.SourceRef" +}, +{ + "name":"akka.stream.SystemMaterializer$", + "fields":[{"name":"MODULE$"}] +}, +{ + "name":"akka.stream.impl.streamref.StreamRefsProtocol" +}, +{ + "name":"akka.stream.serialization.StreamRefSerializer", + "methods":[{"name":"","parameterTypes":["akka.actor.ExtendedActorSystem"] }] +}, +{ + "name":"akka.util.ByteString$ByteString1" +}, +{ + "name":"akka.util.ByteString$ByteString1C" +}, +{ + "name":"akka.util.ByteString$ByteStrings" +}, +{ + "name":"ch.qos.logback.classic.pattern.DateConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LevelConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LineSeparatorConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LoggerConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.MessageConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.NopThrowableInformationConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.rolling.helper.DateTokenConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.rolling.helper.IntegerTokenConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DHParameters", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.TlsMasterSecretGenerator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.typesafe.sslconfig.ssl.NoopHostnameVerifier", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"java.beans.Introspector" +}, +{ + "name":"java.io.FilePermission" +}, +{ + "name":"java.io.Serializable" +}, +{ + "name":"java.lang.Boolean" +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"getModule","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassValue" +}, +{ + "name":"java.lang.Class[]" +}, +{ + "name":"java.lang.Integer" +}, +{ + "name":"java.lang.Long" +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"getDescriptor","parameterTypes":[] }] +}, +{ + "name":"java.lang.Object", + "allDeclaredFields":true +}, +{ + "name":"java.lang.Object[]" +}, +{ + "name":"java.lang.RuntimePermission" +}, +{ + "name":"java.lang.String", + "fields":[{"name":"value"}] +}, +{ + "name":"java.lang.String[]" +}, +{ + "name":"java.lang.invoke.VarHandle", + "methods":[{"name":"releaseFence","parameterTypes":[] }] +}, +{ + "name":"java.net.NetPermission" +}, +{ + "name":"java.net.SocketPermission" +}, +{ + "name":"java.net.URLPermission", + "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"java.nio.file.Path[]" +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.AllPermission" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.MessageDigestSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.security.SecurityPermission" +}, +{ + "name":"java.sql.Date" +}, +{ + "name":"java.sql.Timestamp" +}, +{ + "name":"java.util.PropertyPermission" +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.net.ssl.KeyManager[]" +}, +{ + "name":"javax.net.ssl.TrustManager[]" +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"javax.smartcardio.CardPermission" +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"org.apache.commons.compress.archivers.zip.AsiExtraField", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.JarMarker", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.ResourceAlignmentExtraField", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.UnicodeCommentExtraField", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.UnicodePathExtraField", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X000A_NTFS", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X0014_X509Certificates", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X0015_CertificateIdForFile", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X0016_CertificateIdForCentralDirectory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X0017_StrongEncryptionHeader", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X0019_EncryptionRecipientCertificateList", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X5455_ExtendedTimestamp", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.X7875_NewUnix", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.compress.archivers.zip.Zip64ExtendedInformationExtraField", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.enso.logger.LogbackSetup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.enso.projectmanager.data.MissingComponentActions$", + "allDeclaredFields":true, + "queryAllPublicMethods":true, + "methods":[{"name":"Fail","parameterTypes":[] }, {"name":"ForceInstallBroken","parameterTypes":[] }, {"name":"Install","parameterTypes":[] }] +}, +{ + "name":"org.enso.projectmanager.model.ProjectKinds$", + "allDeclaredFields":true, + "queryAllPublicMethods":true, + "methods":[{"name":"UserProject","parameterTypes":[] }] +}, +{ + "name":"scala.Boolean" +}, +{ + "name":"scala.Enumeration", + "allDeclaredFields":true +}, +{ + "name":"scala.Int" +}, +{ + "name":"scala.Long" +}, +{ + "name":"scala.Symbol", + "methods":[{"name":"apply","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"scala.Tuple2[]" +}, +{ + "name":"scala.collection.concurrent.CNodeBase", + "fields":[{"name":"csize"}] +}, +{ + "name":"scala.collection.concurrent.INodeBase", + "fields":[{"name":"mainnode"}] +}, +{ + "name":"scala.collection.concurrent.MainNode", + "fields":[{"name":"prev"}] +}, +{ + "name":"scala.collection.concurrent.TrieMap", + "fields":[{"name":"root"}] +}, +{ + "name":"sun.misc.Unsafe", + "allDeclaredFields":true +}, +{ + "name":"sun.reflect.Reflection" +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.DSA$SHA224withDSA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.DSA$SHA256withDSA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.JavaKeyStore$JKS", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA224", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA256", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA5$SHA384", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA5$SHA512", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.PSSParameters", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAPSSSignature", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSASignature$SHA224withRSA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.KeyManagerFactoryImpl$SunX509", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$DefaultSSLContext", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLS12Context", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.IssuerAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"zio.internal.HeadPadding", + "fields":[{"name":"headCounter"}] +}, +{ + "name":"zio.internal.TailPadding", + "fields":[{"name":"tailCounter"}] +} ] diff --git a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/resource-config.json b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/resource-config.json index cdda671e57d4..ea7d6840e83f 100644 --- a/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/resource-config.json +++ b/lib/scala/project-manager/src/main/resources/META-INF/native-image/org/enso/projectmanager/resource-config.json @@ -1,77 +1,125 @@ { - "resources": [ - { "pattern": "\\QMETA-INF/MANIFEST.MF\\E" }, - { "pattern": "\\Qakka-http-version.conf\\E" }, - { "pattern": "\\Qapplication.conf\\E" }, - { "pattern": "\\Qorg/enso/projectmanager/boot/ProjectManager$.class\\E" }, - { - "pattern": "\\Qorg/enso/projectmanager/control/core/CovariantFlatMapOps.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/control/core/ZioApplicative.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/control/core/ZioCovariantFlatMap.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/control/effect/ZioAsync.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/control/effect/ZioEnvExec.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/control/effect/ZioErrorChannel.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/infrastructure/file/BlockingFileSystem.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/infrastructure/file/JsonFileStorage.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/infrastructure/languageserver/LanguageServerGatewayImpl.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/infrastructure/log/Slf4jLogging.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/infrastructure/repository/ProjectFileRepository.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/infrastructure/time/RealClock.class\\E" - }, - { "pattern": "\\Qorg/enso/projectmanager/service/ProjectService.class\\E" }, - { - "pattern": "\\Qorg/enso/projectmanager/service/config/GlobalConfigService$AccessErrorRecovery.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/service/config/GlobalConfigService.class\\E" - }, - { - "pattern": "\\Qorg/enso/projectmanager/service/versionmanagement/RuntimeVersionManagerMixin$ErrorRecovery.class\\E" - }, - { "pattern": "\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" }, - { "pattern": "\\QMETA-INF/services/org.enso.logger.LoggerSetup\\E" }, - { "pattern": "\\QMETA-INF/services/org.enso.logging.LogbackLoggingServiceFactory\\E" }, - { "pattern": "\\Qch/qos/logback/classic/spi/Configurator.class\\E" }, - { "pattern": "\\Qreference.conf\\E" }, - { "pattern": "\\Qversion.conf\\E" }, - { "pattern": "\\Qzio/App$$anon$1.class\\E" }, - { "pattern": "\\Qzio/App.class\\E" }, - { "pattern": "\\Qzio/Fiber.class\\E" }, - { "pattern": "\\Qzio/ZIO$.class\\E" }, - { "pattern": "\\Qzio/ZIO$TimeoutTo.class\\E" }, - { "pattern": "\\Qzio/ZIO$ZipLeftFn.class\\E" }, - { "pattern": "\\Qzio/ZIO.class\\E" }, - { "pattern": "\\Qzio/ZScope$.class\\E" }, - { "pattern": "\\Qzio/blocking/package$.class\\E" }, - { "pattern": "\\Qzio/clock/PlatformSpecific$$anon$1.class\\E" }, - { "pattern": "\\Qzio/clock/package$.class\\E" }, - { "pattern": "\\Qzio/clock/package$Clock$Service$$anon$1.class\\E" }, - { "pattern": "\\Qzio/console/package$.class\\E" }, - { "pattern": "\\Qzio/console/package$Console$Service$$anon$1.class\\E" }, - { "pattern": "\\Qzio/internal/FiberContext$InterruptExit$.class\\E" }, - { "pattern": "\\Qzio/internal/FiberContext.class\\E" } - ], - "bundles": [] + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/MANIFEST.MF\\E" + }, { + "pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" + }, { + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.nio.channels.spi.SelectorProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.nio.charset.spi.CharsetProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.enso.logger.LoggerSetup\\E" + }, { + "pattern":"\\QMETA-INF/services/org.enso.logging.LogbackLoggingServiceFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.enso.logging.config.LoggerSetup\\E" + }, { + "pattern":"\\QMETA-INF/services/org.enso.logging.service.LoggingServiceFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qakka-http-version.conf\\E" + }, { + "pattern":"\\Qakka-http-version.json\\E" + }, { + "pattern":"\\Qakka-http-version.properties\\E" + }, { + "pattern":"\\Qapplication.conf\\E" + }, { + "pattern":"\\Qapplication.json\\E" + }, { + "pattern":"\\Qapplication.properties\\E" + }, { + "pattern":"\\Qch/qos/logback/classic/spi/Configurator.class\\E" + }, { + "pattern":"\\Qlogback-test.xml\\E" + }, { + "pattern":"\\Qlogback.xml\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/boot/ProjectManager$.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/control/core/CovariantFlatMapOps.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/control/core/ZioApplicative.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/control/core/ZioCovariantFlatMap.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/control/effect/ZioAsync.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/control/effect/ZioEnvExec.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/control/effect/ZioErrorChannel.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/infrastructure/file/BlockingFileSystem.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/infrastructure/file/JsonFileStorage.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/infrastructure/languageserver/LanguageServerGatewayImpl.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/infrastructure/log/Slf4jLogging.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/infrastructure/repository/ProjectFileRepository.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/infrastructure/time/RealClock.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/service/ProjectService.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/service/config/GlobalConfigService$AccessErrorRecovery.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/service/config/GlobalConfigService.class\\E" + }, { + "pattern":"\\Qorg/enso/projectmanager/service/versionmanagement/RuntimeVersionManagerMixin$ErrorRecovery.class\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qreference.conf\\E" + }, { + "pattern":"\\Qversion.conf\\E" + }, { + "pattern":"\\Qversion.json\\E" + }, { + "pattern":"\\Qversion.properties\\E" + }, { + "pattern":"\\Qzio/App$$anon$1.class\\E" + }, { + "pattern":"\\Qzio/App.class\\E" + }, { + "pattern":"\\Qzio/Fiber.class\\E" + }, { + "pattern":"\\Qzio/ZIO$.class\\E" + }, { + "pattern":"\\Qzio/ZIO$TimeoutTo.class\\E" + }, { + "pattern":"\\Qzio/ZIO$ZipLeftFn.class\\E" + }, { + "pattern":"\\Qzio/ZIO.class\\E" + }, { + "pattern":"\\Qzio/ZScope$.class\\E" + }, { + "pattern":"\\Qzio/blocking/package$.class\\E" + }, { + "pattern":"\\Qzio/clock/PlatformSpecific$$anon$1.class\\E" + }, { + "pattern":"\\Qzio/clock/package$.class\\E" + }, { + "pattern":"\\Qzio/clock/package$Clock$Service$$anon$1.class\\E" + }, { + "pattern":"\\Qzio/console/package$.class\\E" + }, { + "pattern":"\\Qzio/console/package$Console$Service$$anon$1.class\\E" + }, { + "pattern":"\\Qzio/internal/FiberContext$InterruptExit$.class\\E" + }, { + "pattern":"\\Qzio/internal/FiberContext.class\\E" + }, { + "pattern":"java.base:\\Qsun/net/www/content-types.properties\\E" + }]}, + "bundles":[] } diff --git a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/boot/ProjectManager.scala b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/boot/ProjectManager.scala index 576ac84889c9..516ad153b154 100644 --- a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/boot/ProjectManager.scala +++ b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/boot/ProjectManager.scala @@ -111,7 +111,10 @@ object ProjectManager extends ZIOAppDefault with LazyLogging { .as("") } - private def killAllLanguageServer(mainModule: MainModule[ZIO[ZAny, +*, +*]]) = + @scala.annotation.nowarn("msg=pure expression does nothing") + private def killAllLanguageServer( + mainModule: MainModule[ZIO[ZAny, +*, +*]] + ): ZIO[ZAny, Nothing, Unit] = mainModule.languageServerGateway .killAllServers() .foldZIO( diff --git a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala index e7895797e72c..af6a06808048 100644 --- a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala +++ b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala @@ -367,9 +367,9 @@ class ProjectFileRepository[ Traverse[List].traverse(clashing) { case (isClashing, project) => if (isClashing) { for { - newId <- gen.randomUUID() - updatedProject = project.copy(id = newId) - _ <- update(updatedProject) + newId <- gen.randomUUID() + updatedProject <- Applicative[F].pure(project.copy(id = newId)) + _ <- update(updatedProject) } yield updatedProject } else { Applicative[F].pure(project) diff --git a/project/JPMSPlugin.scala b/project/JPMSPlugin.scala index 570520875cfd..29a8185cf42c 100644 --- a/project/JPMSPlugin.scala +++ b/project/JPMSPlugin.scala @@ -310,8 +310,8 @@ object JPMSPlugin extends AutoPlugin { internalModuleDeps: Seq[File], classPath: Def.Classpath, logger: ManagedLogger, - scalaBinaryVersion: String, - currProjName: String + currProjName: String, + scalaBinaryVersion: String ): Seq[File] = { moduleDeps.foreach { moduleDep => if (moduleDep.organization == "org.enso") { diff --git a/project/build.properties b/project/build.properties index e8a1e246e8ad..e88a0d817da1 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.7 +sbt.version=1.10.6 diff --git a/project/plugins.sbt b/project/plugins.sbt index 9e2a74b2060d..07cbb14059e5 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.3") -addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6") +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.13") addSbtPlugin("com.github.sbt" % "sbt-license-report" % "1.5.0") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0") addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.3") diff --git a/tools/legal-review/engine/org.jline.jline-3.23.0/copyright-keep b/tools/legal-review/engine/org.jline.jline-3.23.0/copyright-keep deleted file mode 100644 index 022fcfc11ca4..000000000000 --- a/tools/legal-review/engine/org.jline.jline-3.23.0/copyright-keep +++ /dev/null @@ -1,2 +0,0 @@ -Copyright (C) 2022 the original author(s). -Copyright (c) 2000-2005 Dieter Wimberger diff --git a/tools/legal-review/launcher/org.jline.jline-3.23.0/copyright-keep b/tools/legal-review/engine/org.jline.jline-3.26.3/copyright-keep similarity index 75% rename from tools/legal-review/launcher/org.jline.jline-3.23.0/copyright-keep rename to tools/legal-review/engine/org.jline.jline-3.26.3/copyright-keep index ebc27285eeba..f02d852bce13 100644 --- a/tools/legal-review/launcher/org.jline.jline-3.23.0/copyright-keep +++ b/tools/legal-review/engine/org.jline.jline-3.26.3/copyright-keep @@ -8,12 +8,18 @@ Copyright (c) 2002-2018, the original author(s). Copyright (c) 2002-2019, the original author(s). Copyright (c) 2002-2020, the original author or authors. Copyright (c) 2002-2020, the original author(s). +Copyright (c) 2002-2021, the original author or authors. Copyright (c) 2002-2021, the original author(s). +Copyright (c) 2002-2022, the original author or authors. Copyright (c) 2002-2022, the original author(s). Copyright (c) 2002-2023, the original author(s). +Copyright (c) 2002-2024, the original author(s). Copyright (c) 2009-2018, the original author(s). +Copyright (c) 2009-2023, the original author(s). Copyright (c) 2022, the original author(s). +Copyright (c) 2023, the original author or authors. Copyright (c) 2023, the original author(s). Copyright 2019 the original author or authors. regarding copyright ownership. The ASF licenses this file this work for additional information regarding copyright ownership. +Copyright (c) 2022-2023, the original author(s). diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/copyright-ignore b/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/copyright-ignore similarity index 89% rename from tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/copyright-ignore rename to tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/copyright-ignore index da57f7f4fd90..7ee6e4ce09e3 100644 --- a/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/copyright-ignore +++ b/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/copyright-ignore @@ -1,5 +1,5 @@ "A footer on every Scaladoc page, by default the EPFL/Lightbend copyright notice. Can be overridden with a custom footer.", -Div(id = "footer", elems = Txt("Scala programming documentation. Copyright (c) 2002-2023 ") :: A(href = "https://www.epfl.ch", target = "_top", elems = Txt("EPFL")) :: Txt(" and ") :: A(href = "https://www.lightbend.com", target = "_top", elems = Txt("Lightbend")) :: Txt(".")) +Div(id = "footer", elems = Txt("Scala programming documentation. Copyright (c) 2002-2024 ") :: A(href = "https://www.epfl.ch", target = "_top", elems = Txt("EPFL")) :: Txt(" and ") :: A(href = "https://www.lightbend.com", target = "_top", elems = Txt("Lightbend")) :: Txt(".")) Properties.copyrightString rem # Copyright EPFL and Lightbend, Inc. rem # additional information regarding copyright ownership. diff --git a/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/copyright-keep b/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/copyright-keep rename to tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/copyright-keep diff --git a/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/default-and-custom-license b/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license similarity index 100% rename from tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/default-and-custom-license rename to tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license diff --git a/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/files-keep b/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/files-keep similarity index 100% rename from tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/files-keep rename to tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.15/files-keep diff --git a/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/copyright-ignore b/tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/copyright-ignore similarity index 79% rename from tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/copyright-ignore rename to tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/copyright-ignore index 407fbdf5c469..56d77b97bbf1 100644 --- a/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/copyright-ignore +++ b/tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/copyright-ignore @@ -1,3 +1,3 @@ case _ => "No copyright" private[scala] def versionFor(command: String) = s"Scala $command $versionString -- $copyrightString" -val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2023, LAMP/EPFL and Lightbend, Inc.") +val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2024, LAMP/EPFL and Lightbend, Inc.") diff --git a/tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/copyright-keep b/tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/copyright-keep rename to tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/copyright-keep diff --git a/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/default-and-custom-license b/tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/default-and-custom-license similarity index 100% rename from tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/default-and-custom-license rename to tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/default-and-custom-license diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/files-keep b/tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/files-keep similarity index 100% rename from tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/files-keep rename to tools/legal-review/engine/org.scala-lang.scala-library-2.13.15/files-keep diff --git a/tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.11/copyright-keep b/tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.11/copyright-keep rename to tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.15/copyright-keep diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/default-and-custom-license b/tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license similarity index 100% rename from tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/default-and-custom-license rename to tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license diff --git a/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/files-keep b/tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.15/files-keep similarity index 100% rename from tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/files-keep rename to tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.15/files-keep index 7b5afa970a01..9ef2c9b4d859 100644 --- a/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/files-keep +++ b/tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.15/files-keep @@ -1,2 +1,2 @@ -NOTICE LICENSE +NOTICE diff --git a/tools/legal-review/engine/report-state b/tools/legal-review/engine/report-state index 047c7be3e777..31a84c136c27 100644 --- a/tools/legal-review/engine/report-state +++ b/tools/legal-review/engine/report-state @@ -1,3 +1,3 @@ -420453723CD8943E16C160D0EF9331E55F3D8D1EAD9C0817DC71755794C641A6 -DCC05A7CA7244AE43F2758CECE4ACEFA5EC362B4D247077BF0679F270E3864AA +D5AD7FD632D061E654B2E7D4723488372E19D28EC952496E264F4F43ED949F44 +969A75B923B9FF1EC319979BBD92806FC2C22CCFD4795CF9C07ECF1CC7A4EBA3 0 diff --git a/distribution/launcher/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES b/tools/legal-review/launcher/org.jline.jline-3.26.3/copyright-keep similarity index 75% rename from distribution/launcher/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES rename to tools/legal-review/launcher/org.jline.jline-3.26.3/copyright-keep index d69984f3ea90..f02d852bce13 100644 --- a/distribution/launcher/THIRD-PARTY/org.jline.jline-3.23.0/NOTICES +++ b/tools/legal-review/launcher/org.jline.jline-3.26.3/copyright-keep @@ -1,37 +1,25 @@ Copyright (C) 2022 the original author(s). - Copyright (c) 2000-2005 Dieter Wimberger - Copyright (c) 2002-2016, the original author or authors. - Copyright (c) 2002-2016, the original author(s). - Copyright (c) 2002-2017, the original author(s). - Copyright (c) 2002-2018, the original author or authors. - Copyright (c) 2002-2018, the original author(s). - Copyright (c) 2002-2019, the original author(s). - Copyright (c) 2002-2020, the original author or authors. - Copyright (c) 2002-2020, the original author(s). - +Copyright (c) 2002-2021, the original author or authors. Copyright (c) 2002-2021, the original author(s). - +Copyright (c) 2002-2022, the original author or authors. Copyright (c) 2002-2022, the original author(s). - Copyright (c) 2002-2023, the original author(s). - +Copyright (c) 2002-2024, the original author(s). Copyright (c) 2009-2018, the original author(s). - +Copyright (c) 2009-2023, the original author(s). Copyright (c) 2022, the original author(s). - +Copyright (c) 2023, the original author or authors. Copyright (c) 2023, the original author(s). - Copyright 2019 the original author or authors. - regarding copyright ownership. The ASF licenses this file - this work for additional information regarding copyright ownership. +Copyright (c) 2022-2023, the original author(s). diff --git a/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/copyright-ignore b/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/copyright-ignore similarity index 89% rename from tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/copyright-ignore rename to tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/copyright-ignore index da57f7f4fd90..7ee6e4ce09e3 100644 --- a/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.11/copyright-ignore +++ b/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/copyright-ignore @@ -1,5 +1,5 @@ "A footer on every Scaladoc page, by default the EPFL/Lightbend copyright notice. Can be overridden with a custom footer.", -Div(id = "footer", elems = Txt("Scala programming documentation. Copyright (c) 2002-2023 ") :: A(href = "https://www.epfl.ch", target = "_top", elems = Txt("EPFL")) :: Txt(" and ") :: A(href = "https://www.lightbend.com", target = "_top", elems = Txt("Lightbend")) :: Txt(".")) +Div(id = "footer", elems = Txt("Scala programming documentation. Copyright (c) 2002-2024 ") :: A(href = "https://www.epfl.ch", target = "_top", elems = Txt("EPFL")) :: Txt(" and ") :: A(href = "https://www.lightbend.com", target = "_top", elems = Txt("Lightbend")) :: Txt(".")) Properties.copyrightString rem # Copyright EPFL and Lightbend, Inc. rem # additional information regarding copyright ownership. diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/copyright-keep b/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.11/copyright-keep rename to tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/copyright-keep diff --git a/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license b/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/files-ignore b/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/files-keep similarity index 100% rename from tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/files-ignore rename to tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/files-keep index 7b5afa970a01..9ef2c9b4d859 100644 --- a/tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/files-ignore +++ b/tools/legal-review/launcher/org.scala-lang.scala-compiler-2.13.15/files-keep @@ -1,2 +1,2 @@ -NOTICE LICENSE +NOTICE diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/copyright-ignore b/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/copyright-ignore similarity index 79% rename from tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/copyright-ignore rename to tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/copyright-ignore index 407fbdf5c469..56d77b97bbf1 100644 --- a/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/copyright-ignore +++ b/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/copyright-ignore @@ -1,3 +1,3 @@ case _ => "No copyright" private[scala] def versionFor(command: String) = s"Scala $command $versionString -- $copyrightString" -val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2023, LAMP/EPFL and Lightbend, Inc.") +val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2024, LAMP/EPFL and Lightbend, Inc.") diff --git a/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/copyright-keep b/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/copyright-keep rename to tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/copyright-keep diff --git a/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/default-and-custom-license b/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/default-and-custom-license new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.11/files-ignore b/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/files-keep similarity index 100% rename from tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.11/files-ignore rename to tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/files-keep index 7b5afa970a01..9ef2c9b4d859 100644 --- a/tools/legal-review/engine/org.scala-lang.scala-reflect-2.13.11/files-ignore +++ b/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.15/files-keep @@ -1,2 +1,2 @@ -NOTICE LICENSE +NOTICE diff --git a/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.11/files-ignore b/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.11/files-ignore deleted file mode 100644 index 7b5afa970a01..000000000000 --- a/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.11/files-ignore +++ /dev/null @@ -1,2 +0,0 @@ -NOTICE -LICENSE diff --git a/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.11/copyright-keep b/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.11/copyright-keep rename to tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/copyright-keep diff --git a/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license b/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/files-ignore b/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/files-keep similarity index 100% rename from tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/files-ignore rename to tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/files-keep index 7b5afa970a01..9ef2c9b4d859 100644 --- a/tools/legal-review/launcher/org.scala-lang.scala-library-2.13.11/files-ignore +++ b/tools/legal-review/launcher/org.scala-lang.scala-reflect-2.13.15/files-keep @@ -1,2 +1,2 @@ -NOTICE LICENSE +NOTICE diff --git a/tools/legal-review/launcher/report-state b/tools/legal-review/launcher/report-state index a02587526a02..5fc300e0a986 100644 --- a/tools/legal-review/launcher/report-state +++ b/tools/legal-review/launcher/report-state @@ -1,3 +1,3 @@ -BBB2B5E440C388A022983CB2C0B9B4BA68D04B97FC07E4C8E142952448437BE0 -CA8B1BB2992E828BA958FD6CFC0076B213170FCD454406131407ED0340EC7F2F +C79A2EB00D946AD25163C56A4D248D9F434A005A36AB8D96616BF2D882F086A2 +27689C65B819B363DF25C1A832C1B5113F628E24E78EC680095DE935DBF893A9 0 diff --git a/tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep-context b/tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep-context deleted file mode 100644 index 44d9fb1c3272..000000000000 --- a/tools/legal-review/project-manager/org.jline.jline-3.23.0/copyright-keep-context +++ /dev/null @@ -1,2 +0,0 @@ -Copyright (c) 2000-2005 Dieter Wimberger -Copyright (c) 2002-2017, the original author(s). diff --git a/tools/legal-review/engine/org.jline.jline-3.23.0/copyright-ignore b/tools/legal-review/project-manager/org.jline.jline-3.26.3/copyright-keep similarity index 68% rename from tools/legal-review/engine/org.jline.jline-3.23.0/copyright-ignore rename to tools/legal-review/project-manager/org.jline.jline-3.26.3/copyright-keep index a48fbbefa51c..f02d852bce13 100644 --- a/tools/legal-review/engine/org.jline.jline-3.23.0/copyright-ignore +++ b/tools/legal-review/project-manager/org.jline.jline-3.26.3/copyright-keep @@ -1,3 +1,5 @@ +Copyright (C) 2022 the original author(s). +Copyright (c) 2000-2005 Dieter Wimberger Copyright (c) 2002-2016, the original author or authors. Copyright (c) 2002-2016, the original author(s). Copyright (c) 2002-2017, the original author(s). @@ -6,12 +8,18 @@ Copyright (c) 2002-2018, the original author(s). Copyright (c) 2002-2019, the original author(s). Copyright (c) 2002-2020, the original author or authors. Copyright (c) 2002-2020, the original author(s). +Copyright (c) 2002-2021, the original author or authors. Copyright (c) 2002-2021, the original author(s). +Copyright (c) 2002-2022, the original author or authors. Copyright (c) 2002-2022, the original author(s). Copyright (c) 2002-2023, the original author(s). +Copyright (c) 2002-2024, the original author(s). Copyright (c) 2009-2018, the original author(s). +Copyright (c) 2009-2023, the original author(s). Copyright (c) 2022, the original author(s). +Copyright (c) 2023, the original author or authors. Copyright (c) 2023, the original author(s). Copyright 2019 the original author or authors. regarding copyright ownership. The ASF licenses this file this work for additional information regarding copyright ownership. +Copyright (c) 2022-2023, the original author(s). diff --git a/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/copyright-ignore b/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/copyright-ignore similarity index 82% rename from tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/copyright-ignore rename to tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/copyright-ignore index e1d2bdd31c44..7ee6e4ce09e3 100644 --- a/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/copyright-ignore +++ b/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/copyright-ignore @@ -1,7 +1,6 @@ "A footer on every Scaladoc page, by default the EPFL/Lightbend copyright notice. Can be overridden with a custom footer.", -Div(id = "footer", elems = Txt("Scala programming documentation. Copyright (c) 2002-2023 ") :: A(href = "https://www.epfl.ch", target = "_top", elems = Txt("EPFL")) :: Txt(" and ") :: A(href = "https://www.lightbend.com", target = "_top", elems = Txt("Lightbend")) :: Txt(".")) +Div(id = "footer", elems = Txt("Scala programming documentation. Copyright (c) 2002-2024 ") :: A(href = "https://www.epfl.ch", target = "_top", elems = Txt("EPFL")) :: Txt(" and ") :: A(href = "https://www.lightbend.com", target = "_top", elems = Txt("Lightbend")) :: Txt(".")) Properties.copyrightString -additional information regarding copyright ownership. rem # Copyright EPFL and Lightbend, Inc. rem # additional information regarding copyright ownership. val versionMsg = s"Scaladoc ${Properties.versionString} -- ${Properties.copyrightString}" diff --git a/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/copyright-keep b/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/copyright-keep similarity index 79% rename from tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/copyright-keep rename to tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/copyright-keep index 44e14e43e3af..826fec04eaa3 100644 --- a/tools/legal-review/engine/org.scala-lang.scala-compiler-2.13.11/copyright-keep +++ b/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/copyright-keep @@ -3,3 +3,4 @@ Copyright 2005-2013 LAMP/EPFL Copyright 2005-2017 LAMP/EPFL and Lightbend, Inc Copyright 2005-2017 LAMP/EPFL and Lightbend, Inc. Copyright EPFL and Lightbend, Inc. +additional information regarding copyright ownership. diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license b/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/default-and-custom-license new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/files-keep b/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/files-keep new file mode 100644 index 000000000000..9ef2c9b4d859 --- /dev/null +++ b/tools/legal-review/project-manager/org.scala-lang.scala-compiler-2.13.15/files-keep @@ -0,0 +1,2 @@ +LICENSE +NOTICE diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/files-ignore b/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/files-ignore deleted file mode 100644 index 7b5afa970a01..000000000000 --- a/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/files-ignore +++ /dev/null @@ -1,2 +0,0 @@ -NOTICE -LICENSE diff --git a/tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/copyright-ignore b/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/copyright-ignore similarity index 79% rename from tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/copyright-ignore rename to tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/copyright-ignore index 407fbdf5c469..56d77b97bbf1 100644 --- a/tools/legal-review/engine/org.scala-lang.scala-library-2.13.11/copyright-ignore +++ b/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/copyright-ignore @@ -1,3 +1,3 @@ case _ => "No copyright" private[scala] def versionFor(command: String) = s"Scala $command $versionString -- $copyrightString" -val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2023, LAMP/EPFL and Lightbend, Inc.") +val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2024, LAMP/EPFL and Lightbend, Inc.") diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/copyright-keep b/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.11/copyright-keep rename to tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/copyright-keep diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/default-and-custom-license b/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/default-and-custom-license new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/files-keep b/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/files-keep new file mode 100644 index 000000000000..9ef2c9b4d859 --- /dev/null +++ b/tools/legal-review/project-manager/org.scala-lang.scala-library-2.13.15/files-keep @@ -0,0 +1,2 @@ +LICENSE +NOTICE diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.11/files-ignore b/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.11/files-ignore deleted file mode 100644 index 7b5afa970a01..000000000000 --- a/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.11/files-ignore +++ /dev/null @@ -1,2 +0,0 @@ -NOTICE -LICENSE diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.11/copyright-keep b/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/copyright-keep similarity index 100% rename from tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.11/copyright-keep rename to tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/copyright-keep diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license b/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/default-and-custom-license new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/files-keep b/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/files-keep new file mode 100644 index 000000000000..9ef2c9b4d859 --- /dev/null +++ b/tools/legal-review/project-manager/org.scala-lang.scala-reflect-2.13.15/files-keep @@ -0,0 +1,2 @@ +LICENSE +NOTICE diff --git a/tools/legal-review/project-manager/report-state b/tools/legal-review/project-manager/report-state index 308d06a3d86d..67891bee7551 100644 --- a/tools/legal-review/project-manager/report-state +++ b/tools/legal-review/project-manager/report-state @@ -1,3 +1,3 @@ -38FFA779960E697DA009AF02CFBB9B2CC5E396911FEBC3495E16058023A8F16F -79955D6F3940B454136F8BE49F3C3AFD78DF12310280DA947F713B702AA6B6D1 +E099CADDD2EAA59BC678A9B884DE284933FB60EC675237058E09702E8CC06654 +9A2B3EA2C51280C14D67DBB821BD4D7EDBC09BFBAB7172AED1D56C388B4D0CA9 0 From 269354ebf7d7d2fd0ceb7fdf9db9c901979562e7 Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Mon, 16 Dec 2024 19:37:05 +0300 Subject: [PATCH 08/12] Update licenses codeowners (#11876) followup to #11663 > By making the license directories unowned, only the necessary reviewers will be added to the PR Changelog: - add: missing directories containing the legal review info --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 52510678b0dc..8a91c7406682 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -61,6 +61,8 @@ tsconfig.json # Licenses /distribution/engine/ +/distribution/launcher/ +/distribution/project-manager/ /tools/legal-review/ # The default project template is owned by the libraries team From 34ddd37301e242f8d73eec8d06f732561e30a9e0 Mon Sep 17 00:00:00 2001 From: AdRiley Date: Tue, 17 Dec 2024 13:19:07 +0000 Subject: [PATCH 09/12] Add Missing_Argument error to join right (#11888) --- app/gui/src/project-view/util/callTree.ts | 8 ++++++-- .../lib/Standard/Database/0.0.0-dev/src/DB_Table.enso | 3 ++- distribution/lib/Standard/Table/0.0.0-dev/src/Table.enso | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/gui/src/project-view/util/callTree.ts b/app/gui/src/project-view/util/callTree.ts index 5c34e4cf584f..087ded4b9163 100644 --- a/app/gui/src/project-view/util/callTree.ts +++ b/app/gui/src/project-view/util/callTree.ts @@ -4,7 +4,11 @@ import type { WidgetConfiguration } from '@/providers/widgetRegistry/configurati import * as widgetCfg from '@/providers/widgetRegistry/configuration' import { DisplayMode } from '@/providers/widgetRegistry/configuration' import type { MethodCallInfo } from '@/stores/graph/graphDatabase' -import type { SuggestionEntry, SuggestionEntryArgument } from '@/stores/suggestionDatabase/entry' +import { + isRequiredArgument, + type SuggestionEntry, + type SuggestionEntryArgument, +} from '@/stores/suggestionDatabase/entry' import { Ast } from '@/util/ast' import type { AstId } from '@/util/ast/abstract' import { findLastIndex, tryGetIndex } from '@/util/data/array' @@ -118,7 +122,7 @@ export class ArgumentPlaceholder extends Argument { /** TODO: Add docs */ override get hideByDefault(): boolean { - return this.argInfo.hasDefault && this.dynamicConfig?.display !== DisplayMode.Always + return !isRequiredArgument(this.argInfo) && this.dynamicConfig?.display !== DisplayMode.Always } } diff --git a/distribution/lib/Standard/Database/0.0.0-dev/src/DB_Table.enso b/distribution/lib/Standard/Database/0.0.0-dev/src/DB_Table.enso index 4d41918bd873..25da867e82e0 100644 --- a/distribution/lib/Standard/Database/0.0.0-dev/src/DB_Table.enso +++ b/distribution/lib/Standard/Database/0.0.0-dev/src/DB_Table.enso @@ -9,6 +9,7 @@ import Standard.Base.Errors.Common.Floating_Point_Equality import Standard.Base.Errors.Common.Incomparable_Values import Standard.Base.Errors.Common.Index_Out_Of_Bounds import Standard.Base.Errors.Common.Type_Error +import Standard.Base.Errors.Common.Missing_Argument import Standard.Base.Errors.Deprecated.Deprecated import Standard.Base.Errors.File_Error.File_Error import Standard.Base.Errors.Illegal_Argument.Illegal_Argument @@ -1495,7 +1496,7 @@ type DB_Table @join_kind Widget_Helpers.make_join_kind_selector @on Widget_Helpers.make_join_condition_selector join : DB_Table -> Join_Kind -> Join_Condition | Text | Vector (Join_Condition | Text) -> Text -> Problem_Behavior -> DB_Table - join self right (join_kind : Join_Kind = ..Left_Outer) (on : Join_Condition | Text | Vector (Join_Condition | Text) = (default_join_condition self join_kind)) (right_prefix:Text="Right ") (on_problems:Problem_Behavior=..Report_Warning) = + join self right=(Missing_Argument.throw "right") (join_kind : Join_Kind = ..Left_Outer) (on : Join_Condition | Text | Vector (Join_Condition | Text) = (default_join_condition self join_kind)) (right_prefix:Text="Right ") (on_problems:Problem_Behavior=..Report_Warning) = Feature.Join.if_supported_else_throw self.connection.dialect "join" <| self.join_or_cross_join right join_kind on right_prefix on_problems diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Table.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Table.enso index 641da532d9b1..c7147eb87b4a 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Table.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Table.enso @@ -8,6 +8,7 @@ import Standard.Base.Errors.Common.Additional_Warnings import Standard.Base.Errors.Common.Floating_Point_Equality import Standard.Base.Errors.Common.Incomparable_Values import Standard.Base.Errors.Common.Index_Out_Of_Bounds +import Standard.Base.Errors.Common.Missing_Argument import Standard.Base.Errors.Common.No_Such_Method import Standard.Base.Errors.Common.Out_Of_Memory import Standard.Base.Errors.Common.Type_Error @@ -2665,7 +2666,7 @@ type Table @join_kind Widget_Helpers.make_join_kind_selector @on Widget_Helpers.make_join_condition_selector join : Table -> Join_Kind -> Vector (Join_Condition | Text) | Text -> Text -> Problem_Behavior -> Table - join self right:Table (join_kind : Join_Kind = ..Left_Outer) on=[Join_Condition.Equals self.column_names.first] right_prefix:Text="Right " on_problems:Problem_Behavior=..Report_Warning = Out_Of_Memory.handle_java_exception "join" <| + join self right:Table=(Missing_Argument.throw "right") (join_kind : Join_Kind = ..Left_Outer) on=[Join_Condition.Equals self.column_names.first] right_prefix:Text="Right " on_problems:Problem_Behavior=..Report_Warning = Out_Of_Memory.handle_java_exception "join" <| columns_to_keep = case join_kind of Join_Kind.Left_Exclusive -> [True, False] Join_Kind.Right_Exclusive -> [False, True] From 1df9ea6f3b494afdb79c1125e0dd2e8d6ad737eb Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 17 Dec 2024 14:33:07 +0100 Subject: [PATCH 10/12] raiseAssertionPanic instead of shouldNotReachHere (#11877) --- distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso | 3 +-- .../enso/interpreter/runtime/warning/SetWarningsNode.java | 7 ++----- test/Base_Tests/src/Semantic/Warnings_Spec.enso | 5 +++++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso index b2c8ffd9ad70..1f21a194a7ea 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso @@ -90,8 +90,7 @@ type Warning Arguments: - value: the value to which warnings should be set to. - warnings: vector of warnings to set to the value. - set : Any -> Vector Warning -> Any - set value warnings = set_array value warnings + set value (warnings:Vector Warning) = set_array value warnings ## PRIVATE ADVANCED diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/SetWarningsNode.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/SetWarningsNode.java index b6653e76ed88..eddb8f9ae086 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/SetWarningsNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/SetWarningsNode.java @@ -1,6 +1,5 @@ package org.enso.interpreter.runtime.warning; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.dsl.GenerateUncached; @@ -91,9 +90,7 @@ Object doSetInteropArray( } else { return new WithWarnings(object, maxWarns, isLimitReached, warnMap); } - } catch (UnsupportedMessageException | InvalidArrayIndexException e) { - throw CompilerDirectives.shouldNotReachHere(e); - } catch (ClassCastException e) { + } catch (ClassCastException | UnsupportedMessageException | InvalidArrayIndexException e) { throw ctx.raiseAssertionPanic(this, "Expected Warning, got something else", e); } } @@ -106,7 +103,7 @@ protected static boolean isEmpty(Object warns, InteropLibrary interop) { try { return interop.getArraySize(warns) == 0; } catch (UnsupportedMessageException e) { - throw CompilerDirectives.shouldNotReachHere(e); + return false; } } return false; diff --git a/test/Base_Tests/src/Semantic/Warnings_Spec.enso b/test/Base_Tests/src/Semantic/Warnings_Spec.enso index aca9c4778eac..7e9969f1ca4b 100644 --- a/test/Base_Tests/src/Semantic/Warnings_Spec.enso +++ b/test/Base_Tests/src/Semantic/Warnings_Spec.enso @@ -451,6 +451,11 @@ add_specs suite_builder = suite_builder.group "Dataflow Warnings" group_builder- res2 . should_equal True Warning.get_all res2 . map .value . should_equal ["WARNING2"] + group_builder.specify "warning & panic" <| + panic_text = Panic.catch Standard.Base.Errors.Common.Type_Error (Warning.set 1 2) caught_panic-> + caught_panic.payload.to_text + panic_text . should_equal "Type error: expected `warnings` to be Vector, but got Integer." + main filter=Nothing = suite = Test.build suite_builder-> add_specs suite_builder From cf82c8c3c743e4327b97747a77d2d0c3d9a6dda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Grabarz?= Date: Tue, 17 Dec 2024 14:36:32 +0100 Subject: [PATCH 11/12] Enable prettier on docs markdown (#11875) * Enable prettier on docs markdown * Run prettier always --------- Co-authored-by: Sergei Garin --- .github/workflows/gui-checks.yml | 26 ++-- .github/workflows/gui-pull-request.yml | 46 ++++++ .prettierignore | 1 - docs/semantics/errors.md | 14 +- docs/syntax/README.md | 3 +- docs/syntax/conversions.md | 28 ++-- docs/types/README.md | 3 +- docs/types/access-modifiers.md | 59 ++++---- docs/types/contexts.md | 80 ++++++----- docs/types/dynamic-dispatch.md | 54 +++---- docs/types/errors.md | 21 ++- docs/types/evaluation.md | 33 ++--- docs/types/function-types.md | 41 +++--- docs/types/goals.md | 3 +- docs/types/hierarchy.md | 32 ++--- docs/types/inference-and-checking.md | 16 +-- docs/types/intersection-types.md | 181 ++++++++++++++---------- docs/types/modules.md | 15 +- docs/types/parallelism.md | 6 +- docs/types/pattern-matching.md | 3 +- docs/types/type-directed-programming.md | 15 +- 21 files changed, 361 insertions(+), 319 deletions(-) diff --git a/.github/workflows/gui-checks.yml b/.github/workflows/gui-checks.yml index 5d1091df8457..97f6f3c12393 100644 --- a/.github/workflows/gui-checks.yml +++ b/.github/workflows/gui-checks.yml @@ -31,17 +31,6 @@ jobs: node-version-file: .node-version cache: "pnpm" - - uses: actions/cache/restore@v4 - name: Download cache - id: cache - with: - path: | - **/.eslintcache - node_modules/.cache/prettier - key: ${{ runner.os }}-gui-${{ github.run_id }} - restore-keys: | - ${{ runner.os }}-gui - - if: startsWith(runner.name, 'GitHub Actions') || startsWith(runner.name, 'Hosted Agent') name: Installing wasm-pack uses: jetli/wasm-pack-action@v0.4.0 @@ -51,10 +40,15 @@ jobs: - name: 📦 Install dependencies run: pnpm install --frozen-lockfile - - name: 📝 Prettier - id: prettier - continue-on-error: true - run: pnpm run ci:prettier + - uses: actions/cache/restore@v4 + name: Download cache + id: cache + with: + path: | + **/.eslintcache + key: ${{ runner.os }}-gui-${{ github.run_id }} + restore-keys: | + ${{ runner.os }}-gui # Next Tasks are depend on Typecheck, because we build libraries at this stage - name: 🧠 Typecheck @@ -88,7 +82,6 @@ jobs: - name: ❌ Fail if any check failed if: always() && (steps.prettier.outcome == 'failure' || steps.lint.outcome == 'failure' || steps.typecheck.outcome == 'failure' || steps.unit-tests.outcome == 'failure') run: | - echo "Prettier outcome: ${{ steps.prettier.outcome }}" echo "Lint outcome: ${{ steps.lint.outcome }}" echo "Typecheck outcome: ${{ steps.typecheck.outcome }}" echo "Unit tests outcome: ${{ steps.unit-tests.outcome }}" @@ -102,7 +95,6 @@ jobs: key: ${{ steps.cache.outputs.cache-primary-key }} path: | **/.eslintcache - node_modules/.cache/prettier playwright: name: 🎭 Playwright Tests diff --git a/.github/workflows/gui-pull-request.yml b/.github/workflows/gui-pull-request.yml index 650f001d2279..e388a90ca524 100644 --- a/.github/workflows/gui-pull-request.yml +++ b/.github/workflows/gui-pull-request.yml @@ -58,6 +58,52 @@ jobs: echo "$file was changed" done + prettier: + name: 🧹 Prettier + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: 📦 Setup pnpm + uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v4 + name: ⎔ Setup Node + with: + node-version-file: .node-version + cache: "pnpm" + + - if: startsWith(runner.name, 'GitHub Actions') || startsWith(runner.name, 'Hosted Agent') + name: Installing wasm-pack + uses: jetli/wasm-pack-action@v0.4.0 + with: + version: v0.12.1 + + - name: 📦 Install dependencies + run: pnpm install --frozen-lockfile --ignore-scripts + + - uses: actions/cache/restore@v4 + name: Download cache + id: cache + with: + path: | + node_modules/.cache/prettier + key: ${{ runner.os }}-gui-${{ github.run_id }} + restore-keys: | + ${{ runner.os }}-gui + + - name: Run prettier + run: pnpm run ci:prettier + + - name: 💾 Save cache + uses: actions/cache/save@v4 + if: always() && steps.cache.outputs.cache-hit != 'true' + id: save-cache + with: + key: ${{ steps.cache.outputs.cache-primary-key }} + path: | + node_modules/.cache/prettier + checks: name: 🧰 Checks uses: ./.github/workflows/gui-checks.yml diff --git a/.prettierignore b/.prettierignore index 709537c7f4b2..41d9adc6f8bc 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,7 +16,6 @@ distribution/lib/Standard/*/*/manifest.yaml distribution/lib/Standard/*/*/polyglot distribution/lib/Standard/*/*/THIRD-PARTY distribution/docs-js -docs/**/*.md built-distribution/ THIRD-PARTY diff --git a/docs/semantics/errors.md b/docs/semantics/errors.md index 42ca7918cef5..0a64904fd669 100644 --- a/docs/semantics/errors.md +++ b/docs/semantics/errors.md @@ -20,8 +20,7 @@ users to deal with errors at runtime in the language. ## Asynchronous Exceptions -> [!WARNING] -> The actionables for this section are: +> [!WARNING] The actionables for this section are: > > - Why do we call it asynchronous, when they are synchronous!? > - Specify the semantics of Enso's async exceptions. @@ -32,19 +31,16 @@ There is a special [dynamic dispatch](../types/dynamic-dispatch.md) for `Error` values. A dataflow error dispatch first checks if it may call a method on `Error` type. -> [!WARNING] -> The actionables for this section are: +> [!WARNING] The actionables for this section are: > > - Specify the semantics of Enso's broken values. ## Warnings -> [!WARNING] -> TODO +> [!WARNING] TODO > > - Values in Enso may have warnings attached There is a special [dynamic dispatch](../types/dynamic-dispatch.md) for _values -with warnings_. Before we pass the dispatch to the underlying value, -we check if warning has a method 'overridden' - this is used for `remove_warnings`, -etc. +with warnings_. Before we pass the dispatch to the underlying value, we check if +warning has a method 'overridden' - this is used for `remove_warnings`, etc. diff --git a/docs/syntax/README.md b/docs/syntax/README.md index a933dfdf370f..999e37169156 100644 --- a/docs/syntax/README.md +++ b/docs/syntax/README.md @@ -43,7 +43,8 @@ The various components of Enso's syntax are described below: - [**Functions:**](./functions.md) The syntax for writing functions in Enso. - [**Function Arguments:**](./function-arguments.md) The syntax for function arguments in Enso. -- [**Conversions:**](./conversions.md) The syntax of special _conversion functions_ in Enso. +- [**Conversions:**](./conversions.md) The syntax of special _conversion + functions_ in Enso. - [**Field Access:**](./projections.md) The syntax for working with fields of data types in Enso. - [**Comments:**](./comments.md) The syntax for writing comments in Enso. diff --git a/docs/syntax/conversions.md b/docs/syntax/conversions.md index 2a3a2881daa0..2880c1a992a9 100644 --- a/docs/syntax/conversions.md +++ b/docs/syntax/conversions.md @@ -8,28 +8,36 @@ order: 10 # Conversions -Conversions are special [functions](./functions.md) associated with a [type](../types/hierarchy.md), -named `from` and taking single `that` argument. Following example: +Conversions are special [functions](./functions.md) associated with a +[type](../types/hierarchy.md), named `from` and taking single `that` argument. +Following example: + ```ruby type Complex Num re:Float im:Float Complex.from (that:Float) = Complex.Num that 0 ``` -defines type `Complex` and a **conversion** from `Float` which uses the provided `Float` value as -real part of a complex number while setting the imaginary part to zero. + +defines type `Complex` and a **conversion** from `Float` which uses the provided +`Float` value as real part of a complex number while setting the imaginary part +to zero. ## Type Checks -Conversions are integral part of [type checking](../types/inference-and-checking.md#type-checking-algorithm) +Conversions are integral part of +[type checking](../types/inference-and-checking.md#type-checking-algorithm) during runtime. Having the right conversion in scope one can write: + ```ruby complex_pi = 3.14:Complex ``` -to create a new instance of type `Complex`. The Enso runtime represents -the `3.14` literal as `Float` value and that would fail the `Complex` type check if there was no -conversion method available. However as there is one, the runtime uses `Complex.from` behind the -scene and `complex_pi` then becomes `Complex.Num 3.14 0` value. -Type checks may perform no, one or multiple conversions (like in case of +to create a new instance of type `Complex`. The Enso runtime represents the +`3.14` literal as `Float` value and that would fail the `Complex` type check if +there was no conversion method available. However as there is one, the runtime +uses `Complex.from` behind the scene and `complex_pi` then becomes +`Complex.Num 3.14 0` value. + +Type checks may perform no, one or multiple conversions (like in case of [intersection types](../types/intersection-types.md)). diff --git a/docs/types/README.md b/docs/types/README.md index 1b8961ec3369..62e0771b1a94 100644 --- a/docs/types/README.md +++ b/docs/types/README.md @@ -39,8 +39,7 @@ instrumental for ensuring that we build the right language. > described in the [syntax](../syntax/README.md) document makes no promises as > to whether said syntax will be exposed in the surface language. -> [!WARNING] -> The specification in this section is very outdated and far from +> [!WARNING] The specification in this section is very outdated and far from > reality. Sections that are known to be _"off"_ are marked as _warning_. Information on the type system is broken up into the following sections: diff --git a/docs/types/access-modifiers.md b/docs/types/access-modifiers.md index 9102146c0ff7..fcde50cde457 100644 --- a/docs/types/access-modifiers.md +++ b/docs/types/access-modifiers.md @@ -8,23 +8,23 @@ order: 4 # Access Modifiers -> [!WARNING] -> Everybody who ever maintained a large system knows [encapsulation is essential](../semantics/encapsulation.md). +> [!WARNING] Everybody who ever maintained a large system knows +> [encapsulation is essential](../semantics/encapsulation.md). > -> While we don't usually like making things private in a programming language, it -> sometimes the case that it is necessary to indicate that certain fields should -> not be touched (as this might break invariants and such like). To this end, Enso -> provides an explicit mechanism for access modification. +> While we don't usually like making things private in a programming language, +> it sometimes the case that it is necessary to indicate that certain fields +> should not be touched (as this might break invariants and such like). To this +> end, Enso provides an explicit mechanism for access modification. Enso targets large user base of _non-programmers_. They are mostly focused on -getting their job done and [encapsulation](../semantics/encapsulation.md) of their own code is the last thing -that comes to their mind. +getting their job done and [encapsulation](../semantics/encapsulation.md) of +their own code is the last thing that comes to their mind. -On the other hand, Enso supports and encourages creation of *sharable libraries*. -Maintainers of such libraries are likely to treat API design and its -backward compatibility seriously. As such they need a way to [encapsulate](../semantics/encapsulation.md) -internals of their libraries and clearly *differentiate public API* and -implementations details. +On the other hand, Enso supports and encourages creation of _sharable +libraries_. Maintainers of such libraries are likely to treat API design and its +backward compatibility seriously. As such they need a way to +[encapsulate](../semantics/encapsulation.md) internals of their libraries and +clearly _differentiate public API_ and implementations details. @@ -35,27 +35,26 @@ implementations details. ## Access Modification -*By default* Enso elements (functions, types, methods) are *public*. -One has to use an access modifier to hide and [encapsulate](../semantics/encapsulation.md) them. The -reasoning is: those who don't care can access everything they create without -any restriction. Those who care can make things `private` with an additional -effort. +_By default_ Enso elements (functions, types, methods) are _public_. One has to +use an access modifier to hide and [encapsulate](../semantics/encapsulation.md) +them. The reasoning is: those who don't care can access everything they create +without any restriction. Those who care can make things `private` with an +additional effort. +Accessing any member under an access modifier is an error when performed from +another project. Such a check is enforced during runtime. -Accessing any member under an access modifier is an error when performed from another project. -Such a check is enforced during runtime. - -There is a command line switch to _disable access modifier check_. -It maybe be useful for experimentation. However the general suggestion is: -Avoid using it in production. +There is a command line switch to _disable access modifier check_. It maybe be +useful for experimentation. However the general suggestion is: Avoid using it in +production. ## Private Encapsulation is an effective _communication mechanism_ among _distributed -groups_ of developers. The `private` modifier hides implementation details from clients of the API. -The primary groups in the Enso case are those who *publish a library* -and those who *consume such a library*. +groups_ of developers. The `private` modifier hides implementation details from +clients of the API. The primary groups in the Enso case are those who _publish a +library_ and those who _consume such a library_. -As such Enso supports _library private_ encapsulation. -To hide any element (module, type, constructor, function) away -from *library consumers* prefix such an element with `private` keyword. +As such Enso supports _library private_ encapsulation. To hide any element +(module, type, constructor, function) away from _library consumers_ prefix such +an element with `private` keyword. diff --git a/docs/types/contexts.md b/docs/types/contexts.md index bccd3eeac918..e027139de2d2 100644 --- a/docs/types/contexts.md +++ b/docs/types/contexts.md @@ -8,21 +8,20 @@ order: 8 # Monadic Contexts -> [!WARNING] -> Reword for people without Haskell background who don't know what _lifting_ is. +> [!WARNING] Reword for people without Haskell background who don't know what +> _lifting_ is. > > Coming from a Haskell background, we have found that Monads provide a great > abstraction with which to reason about program behaviour, but they have some -> severe usability issues. The main one of these is the lack of automatic lifting, -> requiring users to explicitly lift computations through their monad transformer -> stack. +> severe usability issues. The main one of these is the lack of automatic +> lifting, requiring users to explicitly lift computations through their monad +> transformer stack. For a language as focused on usability as Enso is importing all the _complexity -of Haskell monads_ really isn't feasible. To -that end, we have created the notion of a 'Monadic Context', which is a monad -transformer based on Supermonads (see -[references](./references.md#monadic-contexts)). These have special support in -the compiler, and hence can be automatically lifted to aid usability. +of Haskell monads_ really isn't feasible. To that end, we have created the +notion of a 'Monadic Context', which is a monad transformer based on Supermonads +(see [references](./references.md#monadic-contexts)). These have special support +in the compiler, and hence can be automatically lifted to aid usability. > The actionables for this section are: > @@ -45,63 +44,68 @@ the compiler, and hence can be automatically lifted to aid usability. ## Context Syntax -> [!WARNING] -> There used to be three main notes about the syntax of contexts: +> [!WARNING] There used to be three main notes about the syntax of contexts: > > 1. Monadic contexts are defined using the `in` keyword (e.g. `Int in IO`). > 2. We have a symbol `!`, which is short-hand for putting something into the -> `Exception` monadic context. This is related to broken values. +> `Exception` monadic context. This is related to broken values. > 3. Contexts can be combined by using the standard typeset operators, or nested -> through repeated uses of `in`. - -There is no special syntax for contexts anymore. -Since [#3828](https://github.com/enso-org/enso/pull/3828) -Enso is no longer relaying on a haskelly solution. -Rather than that _contexts_ are being manupulated by -_standard library_ functions grouped around -`Standard.Base.Runtime.Context` & co. +> through repeated uses of `in`. + +There is no special syntax for contexts anymore. Since +[#3828](https://github.com/enso-org/enso/pull/3828) Enso is no longer relaying +on a haskelly solution. Rather than that _contexts_ are being manupulated by +_standard library_ functions grouped around `Standard.Base.Runtime.Context` & +co. + ```ruby Runtime.Context.Output.with_enabled <| File.new "c:\trash.txt" . delete ``` There is still the `!` symbol signaling [presence of errors](./errors.md) -- e.g. _broken values_. However the runtime can handle _broken values_ -even without presence of these _exception type signatures_. Thus the -compiler only verifies the referenced types are valid. + +- e.g. _broken values_. However the runtime can handle _broken values_ even + without presence of these _exception type signatures_. Thus the compiler only + verifies the referenced types are valid. ## Monadic Bind -> [!WARNING] -> Who knows what `<-` means in Haskell? -> +> [!WARNING] Who knows what `<-` means in Haskell? +> > It is also important to note that Enso has no equivalent to `<-` in Haskell. -> Instead, pure computations are implicitly placed in the `Pure` monadic context, -> and `=` acts to 'peel off' the outermost layer of contexts. As such, this means -> that `=` _always_ acts as `bind`, greatly simplifying how the type-checker has -> to work. +> Instead, pure computations are implicitly placed in the `Pure` monadic +> context, and `=` acts to 'peel off' the outermost layer of contexts. As such, +> this means that `=` _always_ acts as `bind`, greatly simplifying how the +> type-checker has to work. ## Inbuilt Contexts -Enso standard library defines `Input`, `Output` and `Dataflow_Stack_Trace` +Enso standard library defines `Input`, `Output` and `Dataflow_Stack_Trace` contects as of Enso 2024.5.1 version. Users cannot define their own. ### State -The _state_ concept is implement by standard libraries with _no support in the type system_. +The _state_ concept is implement by standard libraries with _no support in the +type system_. + +State acts as a +[thread local](https://en.wikipedia.org/wiki/Thread-local_storage) variable of +operating system: -State acts as a [thread local](https://en.wikipedia.org/wiki/Thread-local_storage) variable -of operating system: + - an _initializing code_ can set `State` up - execute some code -- a code somewhere deep the stack (while _initializing code_ is still on the stack) +- a code somewhere deep the stack (while _initializing code_ is still on the + stack) - may pick the state up - once the _initializing code_ finishes execution - the state is gone -It is an example of _tunnelling a value_ from one side (e.g. code) of the "tunnel" to another, -without the "tunnel" (e.g. thee code in between) knowing about it. +It is an example of _tunnelling a value_ from one side (e.g. code) of the +"tunnel" to another, without the "tunnel" (e.g. thee code in between) knowing +about it. @@ -51,11 +49,10 @@ the already evaluated value. ## Specifying Suspension in the Type System -> [!WARNING] -> The actionables for this section are: +> [!WARNING] The actionables for this section are: > > - Actually specify how the type system interacts with eager and lazy > evaluation. -Just use `~` to mark lazily computed function or atom arguments. The rest is handled -by the Enso runtime system. +Just use `~` to mark lazily computed function or atom arguments. The rest is +handled by the Enso runtime system. diff --git a/docs/types/function-types.md b/docs/types/function-types.md index 0d06a187eaab..e95f8237393e 100644 --- a/docs/types/function-types.md +++ b/docs/types/function-types.md @@ -11,8 +11,7 @@ order: 3 As a functional programming language, the type of functions in Enso (`->`) is key. There are a few things that should be noted about functions in Enso. -> [!NOTE] -> The actionables for this section: +> [!NOTE] The actionables for this section: > > - Work out a full specification for function typing and behaviour. > - Calling a function with an upper-case letter instantiates all of its type @@ -55,8 +54,8 @@ lexical scoping. For a detailed discussion of scoping, please see > ## Structural Type Shorthand > > In Enso, we want to be able to write a type-signature that represents types in -> terms of the operations that take place on the input values. A classical example -> is `add`: +> terms of the operations that take place on the input values. A classical +> example is `add`: > > ```ruby > add : a -> b -> b + a @@ -69,8 +68,8 @@ lexical scoping. For a detailed discussion of scoping, please see > signature that can't work, but the return type, in combination with our > integrated `Convertible` mechanism gives us the tools to make it work. > - The return type is `a + b`. This is a shorthand expression for a detailed -> desugaring. The desugaring provided below is what the typechecker would infer -> based on such a signature. +> desugaring. The desugaring provided below is what the typechecker would +> infer based on such a signature. > > ```ruby > add : forall a b c d. ({+ : Convertible b c => a -> c -> d} <: a) => a -> b -> d @@ -80,23 +79,23 @@ lexical scoping. For a detailed discussion of scoping, please see > follows: > > 1. The expression `b + a` is syntactic sugar for a method call on a: `a.+ b`. -> 2. This means that there must be a `+` method on a that takes both an `a` and a -> `b`, with return-type unspecified as of yet: `+ : a -> b -> ?` +> 2. This means that there must be a `+` method on a that takes both an `a` and +> a `b`, with return-type unspecified as of yet: `+ : a -> b -> ?` > 3. However, as `Convertible` is built into the language, we have to consider -> that for `a.+ b` to work, the `+` method can actually take any type to which -> `b` converts. This introduces the constraint `Convertible b c`, and we get -> `+ : a -> c -> ?` +> that for `a.+ b` to work, the `+` method can actually take any type to +> which `b` converts. This introduces the constraint `Convertible b c`, and +> we get `+ : a -> c -> ?` > 4. The return type from a function need not be determined by its arguments, so -> hence in the general case we have to default to an unrestricted type variable -> giving `+ a -> c -> d`. -> 5. This method must exist on the type `a`, resulting in the constraint that the -> row `{+ : a -> c -> d} <: a` must conform to that interface. +> hence in the general case we have to default to an unrestricted type +> variable giving `+ a -> c -> d`. +> 5. This method must exist on the type `a`, resulting in the constraint that +> the row `{+ : a -> c -> d} <: a` must conform to that interface. > 6. We now know the return type of `a + b`, and can rewrite it in the signature > as `d`. > -> Please note that `a <: b` (which can be flipped as `:>`) means that `a` is a row -> that is a sub-row contained within the row `b`. The containment relation allows -> for the possibility that `a == b`. +> Please note that `a <: b` (which can be flipped as `:>`) means that `a` is a +> row that is a sub-row contained within the row `b`. The containment relation +> allows for the possibility that `a == b`. > > The inferred type for any function should, in general, match the given type > signature. Cases where this break down should only exist where the type @@ -115,8 +114,7 @@ all arguments have been applied. This operator is `>>` (and its backwards cousin arguments, and the result consumes `n` arguments, applies them to `f`, and then applies the result of that plus any additional arguments to `g`. -> [!WARNING] -> Enso does support `>>` as well as `<<` operators, but +> [!WARNING] Enso does support `>>` as well as `<<` operators, but > > ```ruby > computeCoeff = (+) >> (*5) @@ -134,8 +132,7 @@ applies the result of that plus any additional arguments to `g`. In addition, we have the operator `.`, which acts as standard forward function chaining in Enso, and its backwards chaining cousin `<|`. -> [!NOTE] -> The actionables from this section are: +> [!NOTE] The actionables from this section are: > > - Examples for the more advanced use-cases of `>>` to decide if the type > complexity is worth it. diff --git a/docs/types/goals.md b/docs/types/goals.md index 11b53d69b584..684049addfea 100644 --- a/docs/types/goals.md +++ b/docs/types/goals.md @@ -23,8 +23,7 @@ needs to be as unobtrusive as possible. The high-level goals for the Enso type system are as follows: -> [!WARNING] -> _Not a goal anymore_: Enso is a dynamic language. Static type +> [!WARNING] _Not a goal anymore_: Enso is a dynamic language. Static type > inference is _not needed for execution_. As such _static typing_ is an > optional component - more a _linter_ than essential part of the system. > diff --git a/docs/types/hierarchy.md b/docs/types/hierarchy.md index 20af64e05f0f..a1f96f21c102 100644 --- a/docs/types/hierarchy.md +++ b/docs/types/hierarchy.md @@ -14,8 +14,7 @@ most generic type is `Any`. If a value has no better (more specific) type, it has the type `Any`. All operations defined on type `Any` can be performed on any value in the system. -> [!WARNING] -> _Typeset theory is far from current state of affairs_: +> [!WARNING] _Typeset theory is far from current state of affairs_: > > Enso is a statically typed language based upon a theory of set-based typing, > what we call `typesets`. This is a novel approach, and it is key to our intent @@ -39,8 +38,7 @@ A value in Enso can have multiple different types attributed to it. It is possible to query/inspect these types during runtime and thus decide what operations are available for a particular value at hand. -> [!WARNING] -> _Probably not true in current system at all_ +> [!WARNING] > _Probably not true in current system at all_ > > A brief note on naming (for more, please see the > [naming syntax](../syntax/naming.md)): @@ -87,8 +85,7 @@ v:Maybe v.value:Text ``` -> [!WARNING] -> There are no _Typesets_ in Enso anymore +> [!WARNING] There are no _Typesets_ in Enso anymore > > Typesets in Enso are an entity unique to Enso's type system. They are a > fundamental recognition of types as 'sets of values' in Enso, and while they @@ -144,8 +141,7 @@ They are as follows: - **Intersection - `&`:** This operator creates a typeset that contains the members in the [intersection of its operands](./intersection-types.md). -> [!WARNING] -> These operators _don't seem to be supported_. There is no plan to +> [!WARNING] These operators _don't seem to be supported_. There is no plan to > support following operators now: > > - **Subsumption - `<:`:** This operator asserts that the left hand operand is @@ -160,8 +156,7 @@ For information on the syntactic usage of these operators, please see the section on [type operators](#../syntax/types.md#type-operators) in the syntax design documentation. -> [!NOTE] -> The actionables for this section are: +> [!NOTE] The actionables for this section are: > > - When necessary, we need to _explicitly formalise_ the semantics of all of > these operators. @@ -169,8 +164,7 @@ design documentation. > generative) types? > - Are `<:` and `:` equivalent in the surface syntax? -> [!WARNING] -> _Typeset Subsumption_ isn't relevant +> [!WARNING] > _Typeset Subsumption_ isn't relevant > > For two typesets `a` and `b`, `a` is said to be subsumed by `b` (written using > the notation `a <: b`) if the following hold recursively. This can be thought @@ -244,11 +238,11 @@ Historically interfaces used to be defined by _duck typing_. As Enso is a dynamic language, having two types with the same operations means they can be used interchangingly. -> [!NOTE] -> A work on [type classes](https://github.com/orgs/enso-org/discussions/11366) support is under way +> [!NOTE] A work on +> [type classes](https://github.com/orgs/enso-org/discussions/11366) support is +> under way -> [!WARNING] -> _Doesn't match reality:_ +> [!WARNING] _Doesn't match reality:_ > > Because typesets can be matched _structurally_, all typesets implicitly define > interfaces. A type `t` conforming to an interface `i` in Enso is as simple as @@ -305,8 +299,7 @@ _finalizers_. An expression `a : b` says that the expression denoted by `a` has the type denoted by the expression `b`. -> [!WARNING] -> No support for Scoping in Type Ascription +> [!WARNING] No support for Scoping in Type Ascription > > Enso intends to support some form of mutual scoping between the left and right > sides of the type ascription operator. This introduces some complexity into @@ -323,8 +316,7 @@ denoted by the expression `b`. > bindings in groups, and the desugaring needs to depend on combinations of > `>>=` and `fix`. -> [!WARNING] -> There are _no projections_ right now and none are planned +> [!WARNING] There are _no projections_ right now and none are planned > > In order to work efficiently with typesets, we need the ability to seamlessly > access and modify (immutably) their properties. In the context of our type diff --git a/docs/types/inference-and-checking.md b/docs/types/inference-and-checking.md index f2c877ab638e..d33d0e7eb16a 100644 --- a/docs/types/inference-and-checking.md +++ b/docs/types/inference-and-checking.md @@ -8,8 +8,8 @@ order: 13 # Inference and Checking -In spite of being dynamically-typed language, Enso is built with a sophisticated type checker -capable of reasoning about Enso typed system. However, a type +In spite of being dynamically-typed language, Enso is built with a sophisticated +type checker capable of reasoning about Enso typed system. However, a type checker on its own is quite useless. For Enso to truly be usable, it must also have a powerful type inference engine. @@ -43,8 +43,7 @@ In order to make Enso's type inference as helpful and friendly as possible to our users, we want the ability to infer the _maximal subset_ of the types that Enso can express. -> [!WARNING] -> The actionables for this section are: +> [!WARNING] The actionables for this section are: > > - How do we do inference for higher-rank and impredicative instantiations. > - How do we infer contexts, and how do we make that inference granular (e.g. @@ -59,21 +58,18 @@ Enso can express. ## Type Inference Algorithm -> [!WARNING] -> The actionables for this section are: +> [!WARNING] The actionables for this section are: > > - Specify the inference algorithm. ### Inferring Dependency -> [!WARNING] -> The actionables for this section are: +> [!WARNING] The actionables for this section are: > > - Specify how (if at all) we can infer dependent quantifiers. ## Type Checking Algorithm -> [!WARNING] -> The actionables for this section are: +> [!WARNING] The actionables for this section are: > > - Specify the type checking algorithm. diff --git a/docs/types/intersection-types.md b/docs/types/intersection-types.md index 919e138a0cc1..dd053d845709 100644 --- a/docs/types/intersection-types.md +++ b/docs/types/intersection-types.md @@ -8,50 +8,60 @@ order: 2 # Intersection Types -Intersection types play an important role in Enso [type hierarchy](./hierarchy.md) -and its visual representation. Having a value that can play _multiple roles_ -at once is essential for smooth _live programming_ manipulation of such a value. - -Intersections types are created with the use of [`&` operator](./hierarchy.md#typeset-operators). -In an attempt to represent `Complex` numbers (with real and imaginary component) -one may decide to create a type that is both `Complex` and `Float` when the -imaginary part is `0`: +Intersection types play an important role in Enso +[type hierarchy](./hierarchy.md) and its visual representation. Having a value +that can play _multiple roles_ at once is essential for smooth _live +programming_ manipulation of such a value. + +Intersections types are created with the use of +[`&` operator](./hierarchy.md#typeset-operators). In an attempt to represent +`Complex` numbers (with real and imaginary component) one may decide to create a +type that is both `Complex` and `Float` when the imaginary part is `0`: + ```ruby type Complex Num re:Float im:Float - - plain_or_both self = + + plain_or_both self = if self.im != 0 then self else both = self.re : Complex&Float both # value with both types: Complex and Float -``` +``` + Having a value with such _intersection type_ allows the IDE to offer operations available on all individual types. ## Creating -Creating a value of _intersection types_ is as simple as performing a type check: +Creating a value of _intersection types_ is as simple as performing a type +check: + ```ruby self : Complex&Float ``` -However such a _type check_ is closely associated with [conversions](../syntax/conversions.md). -If the value doesn't represent all the desired types yet, then the system looks -for [conversion methods](../syntax/conversions.md) being available in the scope like: + +However such a _type check_ is closely associated with +[conversions](../syntax/conversions.md). If the value doesn't represent all the +desired types yet, then the system looks for +[conversion methods](../syntax/conversions.md) being available in the scope +like: + ``` Complex.from (that:Float) = Complex.Num that 0 ``` + and uses them to create all the values the _intersection type_ represents. -> [!NOTE] -> Note that if a `Float.from (that:Complex)` conversion were available in the scope, -> any `Complex` instance would be convertible to `Float` regardless of how it was constructed. -> To ensure that such mix-ins are only available on values that opt-in to being -> an intersection type (like in the `Complex` example above where we include -> the `Float` mix-in only if `self.im == 0`), we need to ensure that the conversion -> used to create the intersection type is not available in the default -> conversion resolution scope. Thus it cannot be defined in the same module -> as `Complex` or `Float` types, but instead it should be defined in a separate -> module that is only imported in the place that will be constructing the multi-values. +> [!NOTE] Note that if a `Float.from (that:Complex)` conversion were available +> in the scope, any `Complex` instance would be convertible to `Float` +> regardless of how it was constructed. To ensure that such mix-ins are only +> available on values that opt-in to being an intersection type (like in the +> `Complex` example above where we include the `Float` mix-in only if +> `self.im == 0`), we need to ensure that the conversion used to create the +> intersection type is not available in the default conversion resolution scope. +> Thus it cannot be defined in the same module as `Complex` or `Float` types, +> but instead it should be defined in a separate module that is only imported in +> the place that will be constructing the multi-values.