Skip to content

Commit

Permalink
[561344] Fixes regression in parsing private pattern calls
Browse files Browse the repository at this point in the history
This change fixes a strange regression of the standalone parser not
resolving pattern calls _from_ private patterns, caused by
https://git.eclipse.org/r/c/151764/ merged before 2.3.0.M4.

The problem is caused by the fact that the package declaration of a VQL
file was not considered as a required import normalizer by
EMFPatternLanguageImportNamespaceProvider and the namespace provider
only added the namespace because "by coincidence" the inferred pattern
group Jvm Declared Type had exactly the same name as the package, thus
XImportSectionNamespaceProvider added the package name as an import
normalizer to the scope.

However, the previously mentioned change made it optional to infer the
query group type, thus removing this guaranteed provider, causing the
strange issues. This change fixes this regression by explicitly
considering the package declaration as a namespace provider, thus
avoiding the original issue entirely.

Conflicts:
	query/tests/org.eclipse.viatra.query.patternlanguage.emf.tests/src/org/eclipse/viatra/query/patternlanguage/emf/tests/standalone/PatternParserTest.xtend

Change-Id: Id96db63baad6c5ff25db091e05c22095beb6c491
Signed-off-by: Zoltan Ujhelyi <[email protected]>
  • Loading branch information
ujhelyiz committed Mar 30, 2020
1 parent ff19cb0 commit 11e5221
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,27 @@
package org.eclipse.viatra.query.patternlanguage.emf.scoping;

import java.util.List;
import java.util.Objects;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternImport;
import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternLanguagePackage;
import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternModel;
import org.eclipse.viatra.query.patternlanguage.emf.vql.VQLImportSection;
import org.eclipse.viatra.query.patternlanguage.emf.helper.PatternLanguageHelper;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.ISelectable;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.ImportNormalizer;
import org.eclipse.xtext.scoping.impl.ScopeBasedSelectable;
import org.eclipse.xtext.xbase.scoping.XImportSectionNamespaceScopeProvider;
import org.eclipse.xtext.xtype.XImportSection;

import com.google.common.collect.Lists;
import com.google.inject.Inject;

/**
* @author Zoltan Ujhelyi
Expand All @@ -32,6 +40,39 @@ public class EMFPatternLanguageImportNamespaceProvider extends XImportSectionNam

private static final QualifiedName VIATRA_AGGREGATORS = QualifiedName.create("org","eclipse","viatra","query","runtime","matchers","aggregators");

@Inject
IQualifiedNameConverter nameConverter;

/**
* @since 2.4
*/
protected IScope getResourceScope(IScope globalScope, Resource res, EReference reference) {
IScope result = globalScope;
ISelectable globalScopeSelectable = new ScopeBasedSelectable(result);

// implicit imports (i.e. java.lang.*)
List<ImportNormalizer> normalizers = getImplicitImports(isIgnoreCase(reference));

// Also add an import normalizer for the current package declaration for pattern references
if (reference == PatternLanguagePackage.Literals.PATTERN_CALL__PATTERN_REF) {
res.getContents().stream()
.filter(PatternModel.class::isInstance)
.map(PatternModel.class::cast)
.map(PatternModel::getPackageName)
.filter(Objects::nonNull)
.map(nameConverter::toQualifiedName)
.findFirst()
.map(packageName -> doCreateImportNormalizer(packageName, true, false))
.ifPresent(normalizers::add);
}

if (!normalizers.isEmpty()) {
result = createImportScope(result, normalizers, globalScopeSelectable, reference.getEReferenceType(), isIgnoreCase(reference));
}

return result;
}

/**
* @since 1.4
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,103 @@ class PatternParserTest {
assertEquals(1, results.patterns.get(0).eResource.contents.filter(JvmGenericType).size)
assertTrue(results.allDiagnostics.filter[diag | diag.severity === Severity.ERROR].isEmpty)
}

/**
* Test case for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=561344
*/
@Test()
def void privateCallerTest() {
val String pattern = '''
import "http://www.eclipse.org/emf/2002/Ecore";
private pattern caller(class : EClass) {
neg find callee(class);
}
private pattern callee(class : EClass) {
EClass.name(class, "Block");
}
'''
val parser = new PatternParserBuilder()
.withInjector(new EMFPatternLanguageStandaloneSetup().createStandaloneInjector)
.build
val results = parser.parse(pattern)
results.allDiagnostics.forEach[println]
assertTrue(results.allDiagnostics.filter[diag | diag.severity === Severity.ERROR].isEmpty)
}

/**
* Test case for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=561344
*/
@Test()
def void publicCallerTest() {
val String pattern = '''
package test;
import "http://www.eclipse.org/emf/2002/Ecore";
pattern caller(class : EClass) {
neg find callee(class);
}
private pattern callee(class : EClass) {
EClass.name(class, "Block");
}
'''
val parser = new PatternParserBuilder()
.withInjector(new EMFPatternLanguageStandaloneSetup().createStandaloneInjector)
.build
val results = parser.parse(pattern)
results.allDiagnostics.forEach[println]
assertTrue(results.allDiagnostics.filter[diag | diag.severity === Severity.ERROR].isEmpty)
}

/**
* Test case for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=561344
*/
@Test()
def void publicCalleeTest() {
val String pattern = '''
package test;
import "http://www.eclipse.org/emf/2002/Ecore";
private pattern caller(class : EClass) {
neg find callee(class);
}
pattern callee(class : EClass) {
EClass.name(class, "Block");
}
'''
val parser = new PatternParserBuilder()
.withInjector(new EMFPatternLanguageStandaloneSetup().createStandaloneInjector)
.build
val results = parser.parse(pattern)
results.allDiagnostics.forEach[println]
assertTrue(results.allDiagnostics.filter[diag | diag.severity === Severity.ERROR].isEmpty)
}

/**
* Test case for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=561344
*/
@Test()
def void privateCallerTestWithPackageDeclaration() {
val String pattern = '''
package test;
import "http://www.eclipse.org/emf/2002/Ecore";
private pattern caller(class : EClass) {
neg find callee(class);
}
private pattern callee(class : EClass) {
EClass.name(class, "Block");
}
'''
val parser = new PatternParserBuilder()
.withInjector(new EMFPatternLanguageStandaloneSetup().createStandaloneInjector)
.build
val results = parser.parse(pattern)
results.allDiagnostics.forEach[println]
assertTrue(results.allDiagnostics.filter[diag | diag.severity === Severity.ERROR].isEmpty)
}
}

0 comments on commit 11e5221

Please sign in to comment.