From b88d5f016bcd41761c6753ce05c6442aee86f61e Mon Sep 17 00:00:00 2001 From: Kevin Knight <57677197+kevin-m-knight-gs@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:40:35 -0500 Subject: [PATCH] Fix source info for TDS and RelationStoreAccessor DSLs (#895) * Fix source info for TDS inline DSL * Fix source info for RelationStoreAccessor inline DSL --- .../grammar/m3parser/inlinedsl/InlineDSL.java | 2 +- .../AbstractCompiledStateIntegrityTest.java | 1 - .../m2/inlinedsl/graph/antlr/GraphDSL.java | 6 +- .../m2/inlinedsl/path/NavigationPath.java | 8 +- .../store/RelationStoreAccessor.java | 35 +++- .../pure/m2/inlinedsl/tds/TDSExtension.java | 195 +++++++++++------- .../inlinedsl/tds/TestTDSDSLCompilation.java | 152 +++++++++----- .../tds/compiled/TDSNativeImplementation.java | 2 +- .../tds/interpreted/natives/StringToTDS.java | 6 +- .../TestRelationDatabaseAccessor.java | 40 ++-- 10 files changed, 270 insertions(+), 177 deletions(-) diff --git a/legend-pure-core/legend-pure-m3-core/src/main/java/org/finos/legend/pure/m3/serialization/grammar/m3parser/inlinedsl/InlineDSL.java b/legend-pure-core/legend-pure-m3-core/src/main/java/org/finos/legend/pure/m3/serialization/grammar/m3parser/inlinedsl/InlineDSL.java index e267afd636..0ec2cc2e95 100644 --- a/legend-pure-core/legend-pure-m3-core/src/main/java/org/finos/legend/pure/m3/serialization/grammar/m3parser/inlinedsl/InlineDSL.java +++ b/legend-pure-core/legend-pure-m3-core/src/main/java/org/finos/legend/pure/m3/serialization/grammar/m3parser/inlinedsl/InlineDSL.java @@ -33,7 +33,7 @@ public interface InlineDSL extends CoreInstanceFactoriesRegistry boolean match(String code); - CoreInstance parse(String code, ImportGroup importId, String fileName, int offsetX, int offsetY, ModelRepository modelRepository, Context context); + CoreInstance parse(String code, ImportGroup importId, String fileName, int columnOffset, int lineOffset, ModelRepository modelRepository, Context context); RichIterable getProcessors(); diff --git a/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java b/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java index 529145b7d2..65e7ff3d18 100644 --- a/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java +++ b/legend-pure-core/legend-pure-m3-core/src/test/java/org/finos/legend/pure/m3/tests/AbstractCompiledStateIntegrityTest.java @@ -404,7 +404,6 @@ public void testPackagedElementsHaveNonOverlappingSourceInfo() } @Test - @Ignore public void testPackagedElementsContainAllOthers() { CoreInstance packageClass = runtime.getCoreInstance(M3Paths.Package); diff --git a/legend-pure-dsl/legend-pure-dsl-graph/legend-pure-m2-dsl-graph-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/graph/antlr/GraphDSL.java b/legend-pure-dsl/legend-pure-dsl-graph/legend-pure-m2-dsl-graph-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/graph/antlr/GraphDSL.java index 3a86319730..62dcbed7cf 100644 --- a/legend-pure-dsl/legend-pure-dsl-graph/legend-pure-m2-dsl-graph-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/graph/antlr/GraphDSL.java +++ b/legend-pure-dsl/legend-pure-dsl-graph/legend-pure-m2-dsl-graph-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/graph/antlr/GraphDSL.java @@ -33,7 +33,7 @@ public class GraphDSL implements InlineDSL { - private static RootGraphFetchTreeVisibilityValidator ROOTGRAPHFETCHTREE_VISIBILITYVALIDATOR = new RootGraphFetchTreeVisibilityValidator(); + private static final RootGraphFetchTreeVisibilityValidator ROOTGRAPHFETCHTREE_VISIBILITYVALIDATOR = new RootGraphFetchTreeVisibilityValidator(); @Override public String getName() @@ -48,9 +48,9 @@ public boolean match(String code) } @Override - public CoreInstance parse(String code, ImportGroup importId, String fileName, int offsetX, int offsetY, ModelRepository modelRepository, Context context) + public CoreInstance parse(String code, ImportGroup importId, String fileName, int columnOffset, int lineOffset, ModelRepository modelRepository, Context context) { - return new GraphAntlrParser().parse(code, importId, fileName, offsetX, offsetY, modelRepository, context); + return new GraphAntlrParser().parse(code, importId, fileName, columnOffset, lineOffset, modelRepository, context); } @Override diff --git a/legend-pure-dsl/legend-pure-dsl-path/legend-pure-m2-dsl-path-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/path/NavigationPath.java b/legend-pure-dsl/legend-pure-dsl-path/legend-pure-m2-dsl-path-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/path/NavigationPath.java index 7d0800bd6b..da87523d94 100644 --- a/legend-pure-dsl/legend-pure-dsl-path/legend-pure-m2-dsl-path-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/path/NavigationPath.java +++ b/legend-pure-dsl/legend-pure-dsl-path/legend-pure-m2-dsl-path-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/path/NavigationPath.java @@ -34,8 +34,8 @@ public class NavigationPath implements InlineDSL { - private static VisibilityValidator VISIBILITY_VALIDATOR = new PathVisibilityValidator(); - private static MilestoningDatesVarNamesExtractor MILESTONING_EXTRACTOR = new PathMilestoningDatesVarNamesExtractor(); + private static final VisibilityValidator VISIBILITY_VALIDATOR = new PathVisibilityValidator(); + private static final MilestoningDatesVarNamesExtractor MILESTONING_EXTRACTOR = new PathMilestoningDatesVarNamesExtractor(); @Override public String getName() @@ -50,9 +50,9 @@ public boolean match(String code) } @Override - public CoreInstance parse(String code, ImportGroup importId, String fileName, int offsetX, int offsetY, ModelRepository modelRepository, Context context) + public CoreInstance parse(String code, ImportGroup importId, String fileName, int columnOffset, int lineOffset, ModelRepository modelRepository, Context context) { - return new NavigationParser().parse(code, importId, fileName, offsetX, offsetY, modelRepository, context); + return new NavigationParser().parse(code, importId, fileName, columnOffset, lineOffset, modelRepository, context); } @Override diff --git a/legend-pure-dsl/legend-pure-dsl-store/legend-pure-m2-dsl-store-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/store/RelationStoreAccessor.java b/legend-pure-dsl/legend-pure-dsl-store/legend-pure-m2-dsl-store-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/store/RelationStoreAccessor.java index 3a03c0db06..79ea5541fb 100644 --- a/legend-pure-dsl/legend-pure-dsl-store/legend-pure-m2-dsl-store-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/store/RelationStoreAccessor.java +++ b/legend-pure-dsl/legend-pure-dsl-store/legend-pure-m2-dsl-store-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/store/RelationStoreAccessor.java @@ -34,12 +34,14 @@ import org.finos.legend.pure.m4.ModelRepository; import org.finos.legend.pure.m4.coreinstance.CoreInstance; import org.finos.legend.pure.m4.coreinstance.SourceInformation; -import org.finos.legend.pure.m4.serialization.grammar.antlr.AntlrSourceInformation; import org.finos.legend.pure.m4.serialization.grammar.antlr.PureParserException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class RelationStoreAccessor implements InlineDSL { - private static VisibilityValidator VISIBILITY_VALIDATOR = new RelationStoreAccessorValidation(); + private static final VisibilityValidator VISIBILITY_VALIDATOR = new RelationStoreAccessorValidation(); @Override public String getName() @@ -54,26 +56,22 @@ public boolean match(String code) } @Override - public CoreInstance parse(String code, ImportGroup importId, String fileName, int offsetX, int offsetY, ModelRepository modelRepository, Context context) + public CoreInstance parse(String code, ImportGroup importId, String fileName, int columnOffset, int lineOffset, ModelRepository modelRepository, Context context) { - AntlrSourceInformation sourceInformation = new AntlrSourceInformation(offsetX, offsetY, fileName, true); - ProcessorSupport processorSupport = new M3ProcessorSupport(context, modelRepository); - SourceInformation src = new SourceInformation(fileName, offsetX, offsetY, offsetX, offsetY + code.length()); + SourceInformation src = getSourceInfo(code, fileName, columnOffset, lineOffset); String info = code.trim().substring(1).trim(); String first = info.substring(0, 1); if (!"{".equals(first) && !"}".equals(info.substring(info.length() - 2, info.length() - 1))) { - throw new PureParserException(sourceInformation.getPureSourceInformation(0, 0, 0, code.length()), "RelationStoreAccessor must be of the form #>{a::Store.table}#"); + throw new PureParserException(src, "RelationStoreAccessor must be of the form #>{a::Store.table}#"); } info = info.substring(1, info.length() - 1); String[] path = info.split("\\."); - org.finos.legend.pure.m3.coreinstance.meta.pure.store.RelationStoreAccessor rel = ((org.finos.legend.pure.m3.coreinstance.meta.pure.store.RelationStoreAccessor) processorSupport.newAnonymousCoreInstance(src, M2StorePaths.RelationStoreAccessor)); - rel._path(Lists.mutable.with(path)); - - return rel; + return ((org.finos.legend.pure.m3.coreinstance.meta.pure.store.RelationStoreAccessor) processorSupport.newAnonymousCoreInstance(src, M2StorePaths.RelationStoreAccessor)) + ._path(Lists.mutable.with(path)); } @Override @@ -117,4 +115,19 @@ public MilestoningDatesVarNamesExtractor getMilestoningDatesVarNamesExtractor() { return null; } + + private static SourceInformation getSourceInfo(String text, String fileName, int columnOffset, int lineOffset) + { + int endLine = lineOffset; + int endLineIndex = 0; + Matcher matcher = Pattern.compile("\\R").matcher(text); + while (matcher.find()) + { + endLine++; + endLineIndex = matcher.end(); + } + + int endColumn = (endLine == lineOffset) ? (text.length() + columnOffset - 1) : (text.length() - endLineIndex); + return new SourceInformation(fileName, lineOffset, columnOffset, endLine, endColumn); + } } diff --git a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/tds/TDSExtension.java b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/tds/TDSExtension.java index 668ad4490b..062f0e6a52 100644 --- a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/tds/TDSExtension.java +++ b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/main/java/org/finos/legend/pure/m2/inlinedsl/tds/TDSExtension.java @@ -18,6 +18,7 @@ import io.deephaven.csv.parsers.DataType; import io.deephaven.csv.reading.CsvReader; import io.deephaven.csv.sinks.SinkFactory; +import io.deephaven.csv.util.CsvReaderException; import org.eclipse.collections.api.RichIterable; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.impl.utility.ArrayIterate; @@ -46,10 +47,13 @@ import org.finos.legend.pure.m4.coreinstance.SourceInformation; import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class TDSExtension implements InlineDSL { - private static VisibilityValidator VISIBILITY_VALIDATOR = new TDSVisibilityValidator(); + private static final VisibilityValidator VISIBILITY_VALIDATOR = new TDSVisibilityValidator(); @Override public String getName() @@ -64,86 +68,12 @@ public boolean match(String code) } @Override - public CoreInstance parse(String code, ImportGroup importId, String fileName, int offsetX, int offsetY, ModelRepository modelRepository, Context context) + public CoreInstance parse(String code, ImportGroup importId, String fileName, int columnOffset, int lineOffset, ModelRepository modelRepository, Context context) { - String val = code.substring("TDS".length()).trim(); + String text = code.substring("TDS".length()).trim(); + SourceInformation sourceInfo = getSourceInfo(code, fileName, columnOffset, lineOffset); ProcessorSupport processorSupport = new M3ProcessorSupport(context, modelRepository); - return parse(val, fileName, processorSupport); - } - - private static SinkFactory makeMySinkFactory() - { - return SinkFactory.arrays( - null, - null, - null, - null, - null, - null, - null, - null, - null, - Long.MIN_VALUE, - Long.MIN_VALUE); - } - - public static TDS parse(String val, String fileName, ProcessorSupport processorSupport) - { - final CsvReader.Result result; - - try - { - result = CsvReader.read(CsvSpecs.csv(), new ByteArrayInputStream(val.getBytes()), makeMySinkFactory()); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - - SourceInformation src = new SourceInformation(fileName, 0, 0, 0, 0); - Class tdsType = (Class) processorSupport.package_getByUserPath(M2TDSPaths.TDS); - TDS tds = ((TDS) processorSupport.newEphemeralAnonymousCoreInstance(M2TDSPaths.TDS)); - GenericType tdsGenericType = (GenericType) processorSupport.newAnonymousCoreInstance(src, M3Paths.GenericType); - tdsGenericType._rawType(tdsType); - GenericType typeParam = (GenericType) processorSupport.newAnonymousCoreInstance(src, M3Paths.GenericType); - typeParam._rawType(_RelationType.build(ArrayIterate.collect(result.columns(), c -> _Column.getColumnInstance(c.name(), false, convertType(c.dataType()), (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.newMultiplicity(0, 1, processorSupport), src, processorSupport)), src, processorSupport)); - tdsGenericType._typeArgumentsAdd(typeParam); - tds._classifierGenericType(tdsGenericType); - tds._csv(val); - - return tds; - } - - private static String convertType(DataType dataType) - { - String value = ""; - switch (dataType) - { - case BOOLEAN_AS_BYTE: - value = "Boolean"; - break; - case BYTE: - case SHORT: - case INT: - case LONG: - value = "Integer"; - break; - case DATETIME_AS_LONG: - value = "Date"; - break; - case FLOAT: - case DOUBLE: - value = "Float"; - break; - case STRING: - case CHAR: - value = "String"; - break; - case TIMESTAMP_AS_LONG: - case CUSTOM: - throw new RuntimeException("Not possible"); - } - return value; + return parse(text, sourceInfo, processorSupport); } @Override @@ -187,4 +117,111 @@ public MilestoningDatesVarNamesExtractor getMilestoningDatesVarNamesExtractor() { return null; } + + public static TDS parse(String text, ProcessorSupport processorSupport) + { + return parse(text, (SourceInformation) null, processorSupport); + } + + public static TDS parse(String text, String fileName, ProcessorSupport processorSupport) + { + return parse(text, (fileName == null) ? null : getSourceInfo(text, fileName, 0, 0), processorSupport); + } + + public static TDS parse(String text, SourceInformation sourceInfo, ProcessorSupport processorSupport) + { + CsvReader.Result result; + try + { + result = CsvReader.read(CsvSpecs.csv(), new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)), makeMySinkFactory()); + } + catch (CsvReaderException e) + { + throw new RuntimeException(e); + } + + Class tdsType = (Class) processorSupport.package_getByUserPath(M2TDSPaths.TDS); + GenericType typeParam = ((GenericType) processorSupport.newAnonymousCoreInstance(sourceInfo, M3Paths.GenericType)) + ._rawType(_RelationType.build(ArrayIterate.collect(result.columns(), c -> _Column.getColumnInstance(c.name(), false, convertType(c.dataType()), (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.newMultiplicity(0, 1, processorSupport), sourceInfo, processorSupport)), sourceInfo, processorSupport)); + GenericType tdsGenericType = ((GenericType) processorSupport.newAnonymousCoreInstance(sourceInfo, M3Paths.GenericType)) + ._rawType(tdsType) + ._typeArgumentsAdd(typeParam); + + return ((TDS) processorSupport.newAnonymousCoreInstance(sourceInfo, M2TDSPaths.TDS)) + ._classifierGenericType(tdsGenericType) + ._csv(text); + } + + private static SourceInformation getSourceInfo(String text, String fileName, int columnOffset, int lineOffset) + { + int endLine = lineOffset; + int endLineIndex = 0; + Matcher matcher = Pattern.compile("\\R").matcher(text); + while (matcher.find()) + { + endLine++; + endLineIndex = matcher.end(); + } + + int endColumn = (endLine == lineOffset) ? (text.length() + columnOffset - 1) : (text.length() - endLineIndex); + return new SourceInformation(fileName, lineOffset, columnOffset, endLine, endColumn); + } + + private static String convertType(DataType dataType) + { + switch (dataType) + { + case BOOLEAN_AS_BYTE: + { + return M3Paths.Boolean; + } + case BYTE: + case SHORT: + case INT: + case LONG: + { + return M3Paths.Integer; + } + case DATETIME_AS_LONG: + { + return M3Paths.Date; + } + case FLOAT: + case DOUBLE: + { + return M3Paths.Float; + } + case STRING: + case CHAR: + { + return M3Paths.String; + } + case TIMESTAMP_AS_LONG: + case CUSTOM: + { + throw new RuntimeException("Not possible"); + } + default: + { + // TODO is this correct? + return ""; + } + } + } + + private static SinkFactory makeMySinkFactory() + { + return SinkFactory.arrays( + null, + null, + null, + null, + null, + null, + null, + null, + null, + Long.MIN_VALUE, + Long.MIN_VALUE); + } } diff --git a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/test/java/org/finos/legend/pure/m2/inlinedsl/tds/TestTDSDSLCompilation.java b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/test/java/org/finos/legend/pure/m2/inlinedsl/tds/TestTDSDSLCompilation.java index 1f6f0b095b..d72ddc6b0b 100644 --- a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/test/java/org/finos/legend/pure/m2/inlinedsl/tds/TestTDSDSLCompilation.java +++ b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-m2-dsl-tds-grammar/src/test/java/org/finos/legend/pure/m2/inlinedsl/tds/TestTDSDSLCompilation.java @@ -14,7 +14,15 @@ package org.finos.legend.pure.m2.inlinedsl.tds; +import org.eclipse.collections.api.list.ListIterable; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relation.TDS; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.InstanceValue; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; import org.finos.legend.pure.m3.tests.AbstractPureTestWithCoreCompiled; +import org.finos.legend.pure.m3.tools.ListHelper; +import org.finos.legend.pure.m4.coreinstance.SourceInformation; +import org.finos.legend.pure.m4.serialization.grammar.antlr.PureParserException; import org.junit.After; import org.junit.Assert; import org.junit.BeforeClass; @@ -33,146 +41,182 @@ public void cleanRuntime() { runtime.delete("file.pure"); runtime.delete("function.pure"); + runtime.compile(); } @Test public void testGrammarBaselineTest() { - try - { - runtime.createInMemorySource("file.pure", - "function test():Any[*]\n" + - "{\n" + - " print(#EEW#,2);\n" + - "}\n"); - runtime.compile(); - Assert.fail(); - } - catch (Exception e) - { - Assert.assertEquals("Parser error at (resource:file.pure line:3 column:15), expected: one of {'as', '{', '<'} found: ''", e.getMessage()); - } + runtime.createInMemorySource("file.pure", + "function test():Any[*]\n" + + "{\n" + + " print(#EEW#,2);\n" + + "}\n"); + PureParserException e = Assert.assertThrows(PureParserException.class, runtime::compile); + Assert.assertEquals("Parser error at (resource:file.pure line:3 column:15), expected: one of {'as', '{', '<'} found: ''", e.getMessage()); } @Test public void testSimpleDeclarationAndSubtypeAny() { - this.runtime.createInMemorySource("file.pure", - "import meta::pure::metamodel::relation::*;" + + runtime.createInMemorySource("file.pure", + "import meta::pure::metamodel::relation::*;\n" + "function test():Any[*]\n" + "{\n" + - " print(" + + " print(\n" + " #TDS\n" + " value, other, name\n" + " 1, 3, A\n" + " 2, 4, B\n" + - " #" + + " #\n" + ", 2);\n" + "}\n"); - this.runtime.compile(); + runtime.compile(); } @Test public void testSimpleDeclarationApplyFunction() { - this.runtime.createInMemorySource("file.pure", - "import meta::pure::metamodel::relation::*;" + - "native function <> rows(type:TDS[1]):T[*];" + + runtime.createInMemorySource("file.pure", + "import meta::pure::metamodel::relation::*;\n" + + "native function <> rows(type:TDS[1]):T[*];\n" + "function test():Any[*]\n" + "{\n" + - " print(" + + " print(\n" + " #TDS\n" + " value, other, name\n" + " 1, 3, A\n" + " 2, 4, B\n" + - " #->rows()" + + " #->rows()\n" + ", 2);\n" + "}\n"); - this.runtime.compile(); + runtime.compile(); } @Test public void testSimpleDeclarationUseColumnsInLambda() { - this.runtime.createInMemorySource("file.pure", - "import meta::pure::metamodel::relation::*;" + - "native function <> rows(type:TDS[1]):T[*];" + + runtime.createInMemorySource("file.pure", + "import meta::pure::metamodel::relation::*;\n" + + "native function <> rows(type:TDS[1]):T[*];\n" + "function test():Any[*]\n" + "{\n" + - " print(" + + " print(\n" + " #TDS\n" + " value, other, name\n" + " 1, 3, A\n" + " 2, 4, B\n" + - " #" + - " ->rows()->map(x|$x.value->toOne() + $x.other->toOne())" + + " #\n" + + " ->rows()->map(x|$x.value->toOne() + $x.other->toOne())\n" + ", 2);\n" + //" print(A.all()->map(x|$x.a), 2);\n" + "}\n"); - this.runtime.compile(); + runtime.compile(); } @Test public void testSimpleDeclarationUseColumnsInLambdaAndMatchTDS() { - this.runtime.createInMemorySource("file.pure", - "import meta::pure::metamodel::relation::*;" + + runtime.createInMemorySource("file.pure", + "import meta::pure::metamodel::relation::*;\n" + "native function meta::pure::functions::relation::filter(rel:Relation[1], f:Function<{T[1]->Boolean[1]}>[1]):Relation[1];\n" + "\n" + "function meta::pure::functions::relation::filter(rel:TDS[1], f:Function<{T[1]->Boolean[1]}>[1]):Relation[1]\n" + "{\n" + " $rel->cast(@meta::pure::metamodel::relation::Relation)->meta::pure::functions::relation::filter($f);\n" + - "}" + + "}\n" + "function test():Any[*]\n" + "{\n" + - " print(" + + " print(\n" + " #TDS\n" + " value, other, name\n" + " 1, 3, A\n" + " 2, 4, B\n" + - " #->filter(x|$x.value > 1)" + + " #->filter(x|$x.value > 1)\n" + ", 2);\n" + "}\n"); - this.runtime.compile(); + runtime.compile(); - this.runtime.modify("file.pure", - "import meta::pure::metamodel::relation::*;" + - "native function <> rows(type:Relation[1]):T[*];" + + runtime.modify("file.pure", + "import meta::pure::metamodel::relation::*;\n" + + "native function <> rows(type:Relation[1]):T[*];\n" + "function test():Any[*]\n" + "{\n" + - " print(" + + " print(\n" + " #TDS\n" + " value, other, name\n" + " 1, 3, A\n" + " 2, 4, B\n" + - " #" + - " ->rows()->map(x|$x.value->toOne() + $x.other->toOne())" + + " #\n" + + " ->rows()->map(x|$x.value->toOne() + $x.other->toOne())\n" + ", 2);\n" + "}\n"); - this.runtime.compile(); + runtime.compile(); } @Test public void testFunctionMatchingDeepColumn() { - this.runtime.createInMemorySource("file.pure", - "import meta::pure::metamodel::relation::*;" + + runtime.createInMemorySource("file.pure", + "import meta::pure::metamodel::relation::*;\n" + "function x(t:Relation<(vce:String)>[1]):Boolean[1]\n" + "{\n" + " true;\n" + - "}" + - "" + - "function test():Boolean[1]" + - "{" + + "}\n" + + "\n" + + "function test():Boolean[1]\n" + + "{\n" + " #TDS\n" + " id, name, vce\n" + " 1, Pierre, a\n" + " 2, Ram, e\n" + " 3, Neema, e#\n" + //" ->filter(t|$t.vce == 'ok')\n" + - " ->x();" + - " true;" + + " ->x();\n" + + " true;\n" + + "}"); + runtime.compile(); + } + + @Test + public void testSourceInformation() + { + runtime.createInMemorySource("file.pure", + "import meta::pure::metamodel::relation::*;\n" + + "function test():Any[*]\n" + + "{\n" + + " #TDS\n" + + " id, name, vce\n" + + " 1, Pierre, a\n" + + " 2, Ram, e\n" + + " 3, Neema, e#;\n" + + " #TDS\n" + + " id, name, vce\n" + + " 1, Pierre, a\n" + + " 2, Ram, e\n" + + " 3, Neema, e\n" + + " #;\n" + + " #TDS id, name, vce#;" + "}"); - this.runtime.compile(); + runtime.compile(); + + ConcreteFunctionDefinition testFn = (ConcreteFunctionDefinition) runtime.getCoreInstance("test__Any_MANY_"); + + ListIterable expressionSequence = ListHelper.wrapListIterable(testFn._expressionSequence()); + + SourceInformation expectedSourceInfo1 = new SourceInformation("file.pure", 4, 6, 4, 6, 8, 17); + TDS tds1 = (TDS) ((InstanceValue) expressionSequence.get(0))._values().getOnly(); + Assert.assertEquals(expectedSourceInfo1, tds1.getSourceInformation()); + Assert.assertEquals(expectedSourceInfo1, tds1._classifierGenericType().getSourceInformation()); + + SourceInformation expectedSourceInfo2 = new SourceInformation("file.pure", 9, 6, 9, 6, 14, 4); + TDS tds2 = (TDS) ((InstanceValue) expressionSequence.get(1))._values().getOnly(); + Assert.assertEquals(expectedSourceInfo2, tds2.getSourceInformation()); + Assert.assertEquals(expectedSourceInfo2, tds2._classifierGenericType().getSourceInformation()); + + SourceInformation expectedSourceInfo3 = new SourceInformation("file.pure", 15, 6, 15, 6, 15, 22); + TDS tds3 = (TDS) ((InstanceValue) expressionSequence.get(2))._values().getOnly(); + Assert.assertEquals(expectedSourceInfo3, tds3.getSourceInformation()); + Assert.assertEquals(expectedSourceInfo3, tds3._classifierGenericType().getSourceInformation()); } } diff --git a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-compiled-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/compiled/TDSNativeImplementation.java b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-compiled-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/compiled/TDSNativeImplementation.java index 7779972586..386218f1d4 100644 --- a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-compiled-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/compiled/TDSNativeImplementation.java +++ b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-compiled-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/compiled/TDSNativeImplementation.java @@ -23,6 +23,6 @@ public class TDSNativeImplementation { public static TDS parse(String tdsString, ExecutionSupport compiledExecutionSupport) { - return TDSExtension.parse(tdsString, null, ((CompiledExecutionSupport) compiledExecutionSupport).getProcessorSupport()); + return TDSExtension.parse(tdsString, ((CompiledExecutionSupport) compiledExecutionSupport).getProcessorSupport()); } } diff --git a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-interpreted-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/interpreted/natives/StringToTDS.java b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-interpreted-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/interpreted/natives/StringToTDS.java index 9509674fea..1bcdbbe5c4 100644 --- a/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-interpreted-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/interpreted/natives/StringToTDS.java +++ b/legend-pure-dsl/legend-pure-dsl-tds/legend-pure-runtime-java-extension-interpreted-dsl-tds/src/main/java/org/finos/legend/pure/runtime/java/extension/dsl/tds/interpreted/natives/StringToTDS.java @@ -36,7 +36,7 @@ public class StringToTDS extends NativeFunction { - private ModelRepository repository; + private final ModelRepository repository; public StringToTDS(FunctionExecutionInterpreted functionExecution, ModelRepository repository) { @@ -47,6 +47,6 @@ public StringToTDS(FunctionExecutionInterpreted functionExecution, ModelReposito public CoreInstance execute(ListIterable params, Stack> resolvedTypeParameters, Stack> resolvedMultiplicityParameters, VariableContext variableContext, MutableStack functionExpressionCallStack, Profiler profiler, InstantiationContext instantiationContext, ExecutionSupport executionSupport, Context context, ProcessorSupport processorSupport) throws PureExecutionException { String tdsString = params.get(0).getValueForMetaPropertyToOne("values").getName(); - return ValueSpecificationBootstrap.wrapValueSpecification(TDSExtension.parse(tdsString, null, new M3ProcessorSupport(context, repository)), false, processorSupport); + return ValueSpecificationBootstrap.wrapValueSpecification(TDSExtension.parse(tdsString, new M3ProcessorSupport(context, repository)), false, processorSupport); } -} \ No newline at end of file +} diff --git a/legend-pure-store/legend-pure-store-relational/legend-pure-m2-store-relational-grammar/src/test/java/org/finos/legend/pure/m2/relational/incremental/TestRelationDatabaseAccessor.java b/legend-pure-store/legend-pure-store-relational/legend-pure-m2-store-relational-grammar/src/test/java/org/finos/legend/pure/m2/relational/incremental/TestRelationDatabaseAccessor.java index f55b0939c7..0ea58f1d9e 100644 --- a/legend-pure-store/legend-pure-store-relational/legend-pure-m2-store-relational-grammar/src/test/java/org/finos/legend/pure/m2/relational/incremental/TestRelationDatabaseAccessor.java +++ b/legend-pure-store/legend-pure-store-relational/legend-pure-m2-store-relational-grammar/src/test/java/org/finos/legend/pure/m2/relational/incremental/TestRelationDatabaseAccessor.java @@ -57,16 +57,16 @@ public void setUp() public void testCompileAndDeleteModel() { compileSources(STORE_SOURCE_ID); - int expectedSize = this.repository.serialize().length; - ImmutableSet expectedInstances = Sets.immutable.withAll(this.context.getAllInstances()); + int expectedSize = repository.serialize().length; + ImmutableSet expectedInstances = Sets.immutable.withAll(context.getAllInstances()); for (int i = 0; i < TEST_COUNT; i++) { compileSource(MODEL_SOURCE_ID); - Assert.assertNotNull(this.runtime.getCoreInstance("myFunc__Any_1_")); + Assert.assertNotNull(runtime.getCoreInstance("myFunc__Any_1_")); deleteSource(MODEL_SOURCE_ID); - Assert.assertNull(this.runtime.getCoreInstance("myFunc__Any_1_")); - Assert.assertEquals(expectedInstances, this.context.getAllInstances()); - Assert.assertEquals("Failed on iteration #" + i, expectedSize, this.repository.serialize().length); + Assert.assertNull(runtime.getCoreInstance("myFunc__Any_1_")); + Assert.assertEquals(expectedInstances, context.getAllInstances()); + Assert.assertEquals("Failed on iteration #" + i, expectedSize, repository.serialize().length); } } @@ -77,7 +77,7 @@ public void testCompileAndDeleteStore() "native function meta::pure::functions::relation::filter(rel:meta::pure::metamodel::relation::Relation[1], f:Function<{T[1]->Boolean[1]}>[1]):meta::pure::metamodel::relation::Relation[1];\n" + "\n" + "function myFunc():Any[1]\n" + - "{ \n" + + "{\n" + " #>{test::TestDB.personTb}#->filter(t|$t.name == 'ee')\n" + "}"; @@ -92,7 +92,7 @@ public void testCompileAndDeleteStore() .compile(), new RuntimeTestScriptBuilder() .deleteSource("source3.pure") - .compileWithExpectedCompileFailure("The store 'test::TestDB' can't be found", "source1.pure", 5, 6) + .compileWithExpectedCompileFailure("The store 'test::TestDB' can't be found", "source1.pure", 6, 5) .createInMemorySource("source3.pure", STORE) .compile(), runtime, functionExecution, Lists.fixedSize.empty()); @@ -106,9 +106,9 @@ public void testCompileAndDeleteMutateStore() "\n" + "native function meta::pure::functions::relation::filter(rel:meta::pure::metamodel::relation::Relation[1], f:Function<{T[1]->Boolean[1]}>[1]):meta::pure::metamodel::relation::Relation[1];\n" + "function myFunc():Any[1]\n" + - "{ \n" + - " #>{test::TestDB.personTb}#" + - " ->filter(t|$t.name == 'ee')" + + "{\n" + + " #>{test::TestDB.personTb}#\n" + + " ->filter(t|$t.name == 'ee')\n" + "}"; String STORE = "###Relational\n" + @@ -128,7 +128,7 @@ public void testCompileAndDeleteMutateStore() .compile(), new RuntimeTestScriptBuilder() .updateSource("source3.pure", STORE2) - .compileWithExpectedCompileFailure("The system can't find the column name in the Relation (name22:String, firmId:Integer)", "source1.pure", 6, 51) + .compileWithExpectedCompileFailure("The system can't find the column name in the Relation (name22:String, firmId:Integer)", "source1.pure", 7, 22) .updateSource("source3.pure", STORE) .compile(), runtime, functionExecution, Lists.fixedSize.empty()); @@ -181,9 +181,9 @@ public void testCompileAndDeleteFull() "\n" + "native function meta::pure::functions::relation::filter(rel:meta::pure::metamodel::relation::Relation[1], f:Function<{T[1]->Boolean[1]}>[1]):meta::pure::metamodel::relation::Relation[1];\n" + "function myFunc():Any[1]\n" + - "{ \n" + - " #>{test::TestDB.personTb}#" + - " ->filter(t|$t.name == 'ee')" + + "{\n" + + " #>{test::TestDB.personTb}#\n" + + " ->filter(t|$t.name == 'ee')\n" + "}"; String STORE = "\n###Relational\n" + @@ -203,7 +203,7 @@ public void testCompileAndDeleteFull() .compile(), new RuntimeTestScriptBuilder() .updateSource("source1.pure", INITIAL_DATA + STORE2) - .compileWithExpectedCompileFailure("The system can't find the column name in the Relation (name22:String, firmId:Integer)", "source1.pure", 6, 51) + .compileWithExpectedCompileFailure("The system can't find the column name in the Relation (name22:String, firmId:Integer)", "source1.pure", 7, 22) .updateSource("source1.pure", INITIAL_DATA + STORE) .compile(), runtime, functionExecution, Lists.fixedSize.empty()); @@ -213,9 +213,9 @@ private void compileSources(String... sourceIds) { for (String sourceId : sourceIds) { - this.runtime.createInMemorySource(sourceId, this.sources.get(sourceId)); + runtime.createInMemorySource(sourceId, this.sources.get(sourceId)); } - this.runtime.compile(); + runtime.compile(); } private void compileSource(String sourceId) @@ -225,7 +225,7 @@ private void compileSource(String sourceId) private void deleteSource(String sourceId) { - this.runtime.delete(sourceId); - this.runtime.compile(); + runtime.delete(sourceId); + runtime.compile(); } }