diff --git a/partiql-parser/api/partiql-parser.api b/partiql-parser/api/partiql-parser.api index 84b8df262..bd84b15a3 100644 --- a/partiql-parser/api/partiql-parser.api +++ b/partiql-parser/api/partiql-parser.api @@ -6,9 +6,9 @@ public abstract interface class org/partiql/parser/PartiQLParser { } public final class org/partiql/parser/PartiQLParser$Result { - public field locations Lorg/partiql/parser/SourceLocations; + public field locations Lorg/partiql/spi/SourceLocations; public field statements Ljava/util/List; - public fun (Ljava/util/List;Lorg/partiql/parser/SourceLocations;)V + public fun (Ljava/util/List;Lorg/partiql/spi/SourceLocations;)V } public class org/partiql/parser/PartiQLParserBuilder { @@ -29,32 +29,8 @@ public abstract interface class org/partiql/parser/PartiQLParserV1 { } public final class org/partiql/parser/PartiQLParserV1$Result { - public field locations Lorg/partiql/parser/SourceLocations; + public field locations Lorg/partiql/spi/SourceLocations; public field statements Ljava/util/List; - public fun (Ljava/util/List;Lorg/partiql/parser/SourceLocations;)V -} - -public class org/partiql/parser/SourceLocations : java/util/Map { - public fun clear ()V - public fun containsKey (Ljava/lang/Object;)Z - public fun containsValue (Ljava/lang/Object;)Z - public fun entrySet ()Ljava/util/Set; - public synthetic fun get (Ljava/lang/Object;)Ljava/lang/Object; - public fun get (Ljava/lang/Object;)Lorg/partiql/spi/SourceLocation; - public fun isEmpty ()Z - public fun keySet ()Ljava/util/Set; - public synthetic fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun put (Ljava/lang/String;Lorg/partiql/spi/SourceLocation;)Lorg/partiql/spi/SourceLocation; - public fun putAll (Ljava/util/Map;)V - public synthetic fun remove (Ljava/lang/Object;)Ljava/lang/Object; - public fun remove (Ljava/lang/Object;)Lorg/partiql/spi/SourceLocation; - public fun size ()I - public fun values ()Ljava/util/Collection; -} - -public class org/partiql/parser/SourceLocations$Mutable { - public fun ()V - public fun set (Ljava/lang/String;Lorg/partiql/spi/SourceLocation;)V - public fun toMap ()Lorg/partiql/parser/SourceLocations; + public fun (Ljava/util/List;Lorg/partiql/spi/SourceLocations;)V } diff --git a/partiql-parser/src/main/java/org/partiql/parser/PartiQLParser.java b/partiql-parser/src/main/java/org/partiql/parser/PartiQLParser.java index 80eee46bf..ef8582099 100644 --- a/partiql-parser/src/main/java/org/partiql/parser/PartiQLParser.java +++ b/partiql-parser/src/main/java/org/partiql/parser/PartiQLParser.java @@ -18,6 +18,7 @@ import org.partiql.ast.Statement; import org.partiql.parser.internal.PartiQLParserDefault; import org.partiql.spi.Context; +import org.partiql.spi.SourceLocations; import org.partiql.spi.errors.PErrorListenerException; import java.util.List; diff --git a/partiql-parser/src/main/java/org/partiql/parser/PartiQLParserV1.java b/partiql-parser/src/main/java/org/partiql/parser/PartiQLParserV1.java index 6c0ca4700..d16acc267 100644 --- a/partiql-parser/src/main/java/org/partiql/parser/PartiQLParserV1.java +++ b/partiql-parser/src/main/java/org/partiql/parser/PartiQLParserV1.java @@ -18,6 +18,7 @@ import org.partiql.ast.v1.Statement; import org.partiql.parser.internal.PartiQLParserDefaultV1; import org.partiql.spi.Context; +import org.partiql.spi.SourceLocations; import org.partiql.spi.errors.PErrorListenerException; import java.util.List; diff --git a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt index 8072af551..7fe7de28f 100644 --- a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt +++ b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefault.kt @@ -174,11 +174,11 @@ import org.partiql.ast.typeVarchar import org.partiql.parser.PartiQLLexerException import org.partiql.parser.PartiQLParser import org.partiql.parser.PartiQLParserException -import org.partiql.parser.SourceLocations import org.partiql.parser.internal.antlr.PartiQLParserBaseVisitor import org.partiql.parser.internal.util.DateTimeUtils import org.partiql.spi.Context import org.partiql.spi.SourceLocation +import org.partiql.spi.SourceLocations import org.partiql.spi.errors.PError import org.partiql.spi.errors.PErrorKind import org.partiql.spi.errors.PErrorListener @@ -239,7 +239,7 @@ internal class PartiQLParserDefault : PartiQLParser { } catch (throwable: Throwable) { val error = PError.INTERNAL_ERROR(PErrorKind.SYNTAX(), null, throwable) ctx.errorListener.report(error) - val locations = SourceLocations.Mutable().toMap() + val locations = SourceLocations() return PartiQLParser.Result(listOf(Statement.Query(Expr.Lit(nullValue()))), locations) } } @@ -380,7 +380,7 @@ internal class PartiQLParserDefault : PartiQLParser { @OptIn(PartiQLValueExperimental::class) private class Visitor( private val tokens: CommonTokenStream, - private val locations: SourceLocations.Mutable, + private val locations: MutableMap, private val parameters: Map = mapOf(), ) : PartiQLParserBaseVisitor() { @@ -395,10 +395,10 @@ internal class PartiQLParserDefault : PartiQLParser { tokens: CountingTokenStream, tree: GeneratedParser.FileContext, ): PartiQLParser.Result { - val locations = SourceLocations.Mutable() + val locations = mutableMapOf() val visitor = Visitor(tokens, locations, tokens.parameterIndexes) val root: PFile = visitor.visitFile(tree) - return PartiQLParser.Result(root.statements, locations.toMap()) + return PartiQLParser.Result(root.statements, SourceLocations(locations)) } fun error( diff --git a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefaultV1.kt b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefaultV1.kt index bc819f7af..88ea58bd8 100644 --- a/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefaultV1.kt +++ b/partiql-parser/src/main/kotlin/org/partiql/parser/internal/PartiQLParserDefaultV1.kt @@ -155,12 +155,12 @@ import org.partiql.ast.v1.graph.GraphSelector import org.partiql.parser.PartiQLLexerException import org.partiql.parser.PartiQLParserException import org.partiql.parser.PartiQLParserV1 -import org.partiql.parser.SourceLocations import org.partiql.parser.internal.antlr.PartiQLParser import org.partiql.parser.internal.antlr.PartiQLParserBaseVisitor import org.partiql.parser.internal.util.DateTimeUtils import org.partiql.spi.Context import org.partiql.spi.SourceLocation +import org.partiql.spi.SourceLocations import org.partiql.spi.errors.PError import org.partiql.spi.errors.PErrorKind import org.partiql.spi.errors.PErrorListener @@ -219,7 +219,7 @@ internal class PartiQLParserDefaultV1 : PartiQLParserV1 { } catch (throwable: Throwable) { val error = PError.INTERNAL_ERROR(PErrorKind.SYNTAX(), null, throwable) ctx.errorListener.report(error) - val locations = SourceLocations.Mutable().toMap() + val locations = SourceLocations() return PartiQLParserV1.Result( mutableListOf(org.partiql.ast.v1.Query(org.partiql.ast.v1.expr.ExprLit(nullValue()))) as List, locations @@ -354,7 +354,7 @@ internal class PartiQLParserDefaultV1 : PartiQLParserV1 { @OptIn(PartiQLValueExperimental::class) private class Visitor( private val tokens: CommonTokenStream, - private val locations: SourceLocations.Mutable, + private val locations: MutableMap, private val parameters: Map = mapOf(), ) : PartiQLParserBaseVisitor() { @@ -369,12 +369,12 @@ internal class PartiQLParserDefaultV1 : PartiQLParserV1 { tokens: CountingTokenStream, tree: PartiQLParser.FileContext, ): PartiQLParserV1.Result { - val locations = SourceLocations.Mutable() + val locations = mutableMapOf() val visitor = Visitor(tokens, locations, tokens.parameterIndexes) val root: PFileV1 = visitor.visitFile(tree) return PartiQLParserV1.Result( root.statements.toMutableList(), - locations.toMap(), + SourceLocations(locations), ) } diff --git a/partiql-spi/api/partiql-spi.api b/partiql-spi/api/partiql-spi.api index 9b652785a..a8748a58b 100644 --- a/partiql-spi/api/partiql-spi.api +++ b/partiql-spi/api/partiql-spi.api @@ -47,6 +47,26 @@ public class org/partiql/spi/SourceLocation { public fun hashCode ()I } +public class org/partiql/spi/SourceLocations : java/util/Map { + public fun ()V + public fun (Ljava/util/Map;)V + public fun clear ()V + public fun containsKey (Ljava/lang/Object;)Z + public fun containsValue (Ljava/lang/Object;)Z + public fun entrySet ()Ljava/util/Set; + public synthetic fun get (Ljava/lang/Object;)Ljava/lang/Object; + public fun get (Ljava/lang/Object;)Lorg/partiql/spi/SourceLocation; + public fun isEmpty ()Z + public fun keySet ()Ljava/util/Set; + public synthetic fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun put (Ljava/lang/String;Lorg/partiql/spi/SourceLocation;)Lorg/partiql/spi/SourceLocation; + public fun putAll (Ljava/util/Map;)V + public synthetic fun remove (Ljava/lang/Object;)Ljava/lang/Object; + public fun remove (Ljava/lang/Object;)Lorg/partiql/spi/SourceLocation; + public fun size ()I + public fun values ()Ljava/util/Collection; +} + public abstract interface class org/partiql/spi/catalog/Catalog { public abstract fun getAggregations (Lorg/partiql/spi/catalog/Session;Ljava/lang/String;)Ljava/util/Collection; public abstract fun getFunctions (Lorg/partiql/spi/catalog/Session;Ljava/lang/String;)Ljava/util/Collection; diff --git a/partiql-parser/src/main/java/org/partiql/parser/SourceLocations.java b/partiql-spi/src/main/java/org/partiql/spi/SourceLocations.java similarity index 59% rename from partiql-parser/src/main/java/org/partiql/parser/SourceLocations.java rename to partiql-spi/src/main/java/org/partiql/spi/SourceLocations.java index 8aaaba6b0..e70820cd8 100644 --- a/partiql-parser/src/main/java/org/partiql/parser/SourceLocations.java +++ b/partiql-spi/src/main/java/org/partiql/spi/SourceLocations.java @@ -1,22 +1,37 @@ -package org.partiql.parser; +package org.partiql.spi; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.partiql.spi.SourceLocation; import java.util.Collection; import java.util.Map; import java.util.Set; /** - * TODO + * This class maps a set of identifiers to their corresponding source locations. + *
+ * Note!: This class is immutable and does not support {@link Map#put(Object, Object)}, amongst others. Please + * handle the runtime exceptions indicated by {@link Map}'s Javadocs. */ public class SourceLocations implements Map { private final Map delegate; - private SourceLocations(Map delegate) { - this.delegate = delegate; + /** + * Creates an empty instance. + */ + public SourceLocations() { + this.delegate = new java.util.HashMap<>(); + } + + /** + * Creates an instance holding the contents of {@code delegate}. To enforce immutability, these contents are copied + * to an internal structure. + * @param delegate the delegate holding the locations. + */ + public SourceLocations(Map delegate) { + this.delegate = new java.util.HashMap<>(); + this.delegate.putAll(delegate); } @NotNull @@ -60,54 +75,27 @@ public SourceLocation get(Object key) { @Nullable @Override public SourceLocation put(String key, SourceLocation value) { - // TODO: This isn't allowed (yet?) - return null; + throw new UnsupportedOperationException(); } @Override public SourceLocation remove(Object key) { - // TODO: This isn't allowed (yet?) - return null; + throw new UnsupportedOperationException(); } @Override public void putAll(@NotNull Map m) { - // TODO: This isn't allowed (yet?) + throw new UnsupportedOperationException(); } @Override public void clear() { - // TODO: This isn't allowed (yet?) + throw new UnsupportedOperationException(); } @Override public boolean isEmpty() { return delegate.isEmpty(); } - - /** - * TODO - */ - public static class Mutable { - - private final Map delegate = new java.util.HashMap<>(); - - /** - * TODO - * @param id TODO - * @param value TODO - */ - public void set(String id, SourceLocation value) { - delegate.put(id, value); - } - - /** - * TODO - * @return TODO - */ - public SourceLocations toMap() { - return new SourceLocations(delegate); - } - } }