eclipse-ocl / org.eclipse.ocl

Eclipse Public License 2.0
0 stars 0 forks source link

Unexpected issues with cyclic dependencies among OCL files #1689

Open eclipse-ocl-bot opened 1 month ago

eclipse-ocl-bot commented 1 month ago

| --- | --- | | Bugzilla Link | 492004 | | Status | NEW | | Importance | P3 normal | | Reported | Apr 19, 2016 09:38 EDT | | Modified | May 02, 2016 06:51 EDT | | Reporter | Adolfo Sanchez-Barbudo Herrera |

Description

Hi Ed,

OCL: asanchez/cyclicDependencies\ QVTd: asanchez/cyclicDependencies

Execution "OCL AutoCS" mwe file[1] produces unexpected logged exceptions in the console[2] and it finally ends up failing[3] on the scheduler. If you look at the commit in OCL-asanchez/cyclicDependencies, just a cyclic OCL dependency has been introduced when importing EssentialOCLCS2AS.ocl from EssentialOCLCS2ASHelpers.ocl. Without that cyclic dependency those exceptions don't appear and the scheduler properly does its job.

Cheers,\ Adolfo.

[1] org.eclipse.ocl.examples.build\src\org\eclipse\ocl\examples\build\GenerateAutoCSModels.mwe2\ [2] 23955 [main] INFO ties.GenerateCGedQVTiTransformation - QVTp step completed => platform:/resource/org.eclipse.ocl.xtext.essentialocl/model/EssentialOCLCS2AS.qvtp.qvtcas\ org.eclipse.ocl.pivot.utilities.ParserException: Missing specification body for 'essentialoclcs::NameExpCS::lookupOperation' body\ at org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager.parseSpecification(PivotMetamodelManager.java:2139)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visitOperation(AbstractDomainUsageAnalysis.java:562)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visitOperation(AbstractDomainUsageAnalysis.java:1)\ at org.eclipse.ocl.pivot.internal.OperationImpl.accept(OperationImpl.java:1472)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visit(AbstractDomainUsageAnalysis.java:320)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.RootDomainUsageAnalysis.analyzeOperation(RootDomainUsageAnalysis.java:351)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.RootDomainUsageAnalysis.getAnalysis(RootDomainUsageAnalysis.java:554)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visitOperationCallExp(AbstractDomainUsageAnalysis.java:621)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visitOperationCallExp(AbstractDomainUsageAnalysis.java:1)\ at org.eclipse.ocl.pivot.internal.OperationCallExpImpl.accept(OperationCallExpImpl.java:528)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visit(AbstractDomainUsageAnalysis.java:320)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visitOperationCallExp(AbstractDomainUsageAnalysis.java:579)\ at org.eclipse.qvtd.pivot.qvtcorebase.analysis.AbstractDomainUsageAnalysis.visitOperationCallExp(AbstractDomainUsageAnalysis.java:1)\ at org.eclipse.ocl.pivot.internal.OperationCallExpImpl.accept(OperationCallExpImpl.java:528)\ [3] 27149 [main] ERROR mf.mwe2.launch.runtime.Mwe2Launcher - \ java.lang.AssertionError\ at org.eclipse.qvtd.compiler.internal.scheduler.DependencyAnalyzer.analyze(DependencyAnalyzer.java:886)\ at org.eclipse.qvtd.compiler.internal.scheduler.DependencyAnalyzer.analyze(DependencyAnalyzer.java:848)\ at org.eclipse.qvtd.compiler.internal.scheduler.OperationRegion.(OperationRegion.java:84)\ at org.eclipse.qvtd.compiler.internal.scheduler.Scheduler.analyzeOperation(Scheduler.java:104)\ at org.eclipse.qvtd.compiler.internal.scheduler.SuperRegion.analyzeOperation(SuperRegion.java:43)\ at org.eclipse.qvtd.compiler.internal.scheduler.ExpressionAnalyzer.visitOperationCallExp(ExpressionAnalyzer.java:619)\ at org.eclipse.qvtd.compiler.internal.scheduler.ExpressionAnalyzer.visitOperationCallExp(ExpressionAnalyzer.java:1)\ at org.eclipse.ocl.pivot.internal.OperationCallExpImpl.accept(OperationCallExpImpl.java:528)\ at org.eclipse.qvtd.compiler.internal.scheduler.ExpressionAnalyzer.analyze(ExpressionAnalyzer.java:108)\ at org.eclipse.qvtd.compiler.internal.scheduler.ExpressionAnalyzer.visitOperationCallExp(ExpressionAnalyzer.java:593)\ at org.eclipse.qvtd.compiler.internal.scheduler.ExpressionAnalyzer.visitOperationCallExp(ExpressionAnalyzer.java:1)\ at org.eclipse.ocl.pivot.internal.OperationCallExpImpl.accept(OperationCallExpImpl.java:528)\ at org.eclipse.qvtd.compiler.internal.scheduler.ExpressionAnalyzer.analyze(ExpressionAnalyzer.java:108)\ at org.eclipse.qvtd.compiler.internal.scheduler.SimpleMappingRegion.(SimpleMappingRegion.java:144)\ at org.eclipse.qvtd.compiler.internal.scheduler.Scheduler.createSuperRegions(Scheduler.java:166)\ at org.eclipse.qvtd.compiler.internal.scheduler.Scheduler.qvtp2qvts(Scheduler.java:316)\ at org.eclipse.qvtd.compiler.AbstractCompilerChain.qvtg2qvti(AbstractCompilerChain.java:334)\ at org.eclipse.qvtd.compiler.AbstractCompilerChain.qvtp2qvti(AbstractCompilerChain.java:391)

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 19, 2016 10:02

java.lang.AssertionError\ at org.eclipse.qvtd.compiler.internal.scheduler.DependencyAnalyzer.analyze(DependencyAnalyzer.java:886)\ at org.eclipse.qvtd.compiler.internal.scheduler.DependencyAnalyzer.analyze(DependencyAnalyzer.java:848)\ at org.eclipse.qvtd.compiler.internal.scheduler.OperationRegion.(OperationRegion.java:84)

doesn't look like an OCL problem.

eclipse-ocl-bot commented 1 month ago

By Adolfo Sanchez-Barbudo Herrera on Apr 19, 2016 10:22

(In reply to comment #1)

java.lang.AssertionError at org.eclipse.qvtd.compiler.internal.scheduler.DependencyAnalyzer.analyze(DependencyAnalyzer.java:886) at org.eclipse.qvtd.compiler.internal.scheduler.DependencyAnalyzer.analyze(DependencyAnalyzer.java:848) at org.eclipse.qvtd.compiler.internal.scheduler.OperationRegion.(OperationRegion.java:84)

doesn't look like an OCL problem.

But the previous exceptions ([2] above) do, IMHO. Since the change was "adding an import which creates a cyclic dependency", I'm assuming it's a problem of OCL. I'd be surprised if it were not case. In any case, feel free to change the project as soon as you discover it is not a problem in OCL.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 19, 2016 15:03

(In reply to Ed Willink from comment #1)

java.lang.AssertionError at

This was a later error not an original cause.

Currently Complete OCL resolves its imports recursively, which is ok for .ecore etc, but troublesome for .ocl. Behind the scenes the cyclic import is detected but the referenced AS model is null giving an NPE internally which is logged in the csResource.errors, but not detected later.

The Complete OCL CS2AS like the UML2AS must gather all the imports so that all declarations are defined before any bodies reference them. This should be done automatically by the new CS2AS. There is no point doing it now since the problem arises from a partitioning into three files with seemingly only two purposes.

a) cause this problem.\ b) obfuscate the location of operations

eclipse-ocl-bot commented 1 month ago

By Adolfo Sanchez-Barbudo Herrera on Apr 23, 2016 09:48

Hi

One question. If cyclic imports are supported, how overloaded operations defined on the same Class should work (after creating the CompleteModel) ? Which one wins ?

Regards,\ Adolfo.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 24, 2016 05:03

Cyclic imports an be resolved in two manual passes

a) load all declarations following input to gather more declarations.

b) resolve references from those declarations.

The CompleteModel has all declarations, and nothing is resolved before there is a relevant complete set of declarations.

Overloads are resolved to the 'best' match where 'best' has to be specified. C++ uses a policy of choosing the match that involves fewest automated type conversions. Java and OCL have fewer automated conversion (only inheritance) and so a 'best' match should be easier. The current implementation in AbstractOperationMatcher counts conversions.

eclipse-ocl-bot commented 1 month ago

By Adolfo Sanchez-Barbudo Herrera on Apr 24, 2016 14:29

I think I better bring a simple example:

File1.ocl:

import File2.ocl;

package ocl\ context String\ def : doSomething() : String =\ 'foo'\ endpackage

File2.ocl:

import File1.ocl;

context String\ def : doSomething()= String =\ 'bar'\ endpackage

Providing I load these two Complete OCL files, which is the result of doing 'text'.doSomething() ?

'foo' or 'bar' ??

Regards,\ Adolfo.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 25, 2016 02:08

The 'text'.doSomething() is not well-formed (ambiguous), therefore it is invalid.

eclipse-ocl-bot commented 1 month ago

By Adolfo Sanchez-Barbudo Herrera on Apr 26, 2016 07:45

(In reply to Ed Willink from comment #7)

The 'text'.doSomething() is not well-formed (ambiguous), therefore it is invalid.

Are you suggesting the call can be disambiguated anyhow?. The problem I see is that, even if a kind of disambiguation mechanism based on the file were available (as QVTo does with CompilationUnits) so that I could do something like

'text'.'File1.ocl'::ocl::String::doSomething()

to solve the disambiguation, we would have a similar dilemma if same operation declarations were defined in the same file.

Additional thoughts:

  1. Same operation on the same type in the same file. I see no other option than raise an error on both operation declarations (rather than an error on the operation call). This is not a problem because you can cure your own same file.

  2. Same operation on the same type in the different file. This is a problem because sometimes you can't fix the imported file. I see a couple of alternatives:\ a) If cyclic imports are not allowed: The operation of the extending file/model wins. Limitation: no cyclic imports.\ b) If cyclic imports are allowed: same as 1). Limitation: prevents to redefine operations.

Perhaps a mechanism to explicitly declare operation redefinitions (between different models/imported files) to solve conflicts produced in 2.b), could help to cure the identified 2.b) limitation.

Regards,\ Adolfo.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 26, 2016 08:11

I don't see the problem.

Redefinition is not supported. Redefinition is ambiguous.

Disambiguation only occurs for non-identical declarations.

Given:

f(OclAny,OclAny)\ f(String,OclAny)\ f(OclAny,String)

f(1,1) => f(OclAny,OclAny)\ f('x',1) => f(String,OclAny)\ f(1, 'x') => f(OclAny,String)\ f('x','y') => ambiguous

eclipse-ocl-bot commented 1 month ago

By Adolfo Sanchez-Barbudo Herrera on Apr 26, 2016 08:20

Hi

I think there is no need to include "non-identical declarations" concern. My concern and the example has focused on operations with identical signature declared on the same type.

Anyway, with your "redefinition is not supported" comment, I presume you are inclined to 2.b) and accept the limitation.

(if we skip a type I introduced) My example would be simply invalid, because there are two operations with identical signature declared on the same type.

Regards,\ Adolfo.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on May 02, 2016 06:51

Branch archive/492004 has some attempts at supporting cyclic imports.

The dependencies are non-trivial and when implemented manually a change here breaks something there. Hard. Needs careful design revision.

A subtelty is that some imports such as Ecore files must be resolved eagerly to make e.g. Package decklarations avaialble for resolution during the Complete OCL containment pass. Othe imports must be resolved later, possibly at the end of the containment pass, this beaks the cycle.

All files must be processed together. All containment, then all pre-order, then all post-order.

Anyway too hard to do manually. Waiut for the automated solution.

Workaround. Merge Complete OCL file cycle into a single file.