Merge pull request #663 from eclipse/sz/bug361216

[361216] Improved logic that registers scope wrappers
This commit is contained in:
Sebastian Zarnekow 2018-03-21 18:48:14 +01:00 committed by GitHub
commit 7da28520af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 194 additions and 18 deletions

View file

@ -0,0 +1,159 @@
/*******************************************************************************
* Copyright (c) 2018 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.scoping.impl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.IScopeProvider;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Sebastian Zarnekow - Initial contribution and API
*/
public class DelegatingScopeProviderTest implements IScopeWrapper {
static class TestableDelegatingScopeProvider implements IDelegatingScopeProvider {
private final IScopeProvider delegate;
private int invocationCount = 0;
TestableDelegatingScopeProvider(IScopeProvider delegate) {
this.delegate = delegate;
}
TestableDelegatingScopeProvider() {
this(new IScopeProvider() {
@Override
public IScope getScope(EObject context, EReference reference) {
return IScope.NULLSCOPE;
}
});
}
@Override
public void setWrapper(IScopeWrapper wrapper) {
invocationCount++;
IDelegatingScopeProvider.super.setWrapper(wrapper);
}
@Override
public IScope getScope(EObject context, EReference reference) {
Assert.fail("Unexpected invocation");
return null;
}
@Override
public IScopeProvider getDelegate() {
return delegate;
}
}
@Override
public IScope wrap(IScope scope) {
Assert.fail("Unexpected invocation");
return null;
}
@Test
public void testNoSuitableDelegate() {
TestableDelegatingScopeProvider testMe = new TestableDelegatingScopeProvider();
testMe.setWrapper(this);
Assert.assertEquals(1, testMe.invocationCount);
IDelegatingScopeProvider.setWrapper(testMe, null);
Assert.assertEquals(2, testMe.invocationCount);
}
@Test
public void testOneSuitableDelegate_01() {
TestableDelegatingScopeProvider root = new TestableDelegatingScopeProvider();
TestableDelegatingScopeProvider delegating = new TestableDelegatingScopeProvider(root);
delegating.setWrapper(this);
Assert.assertEquals(1, delegating.invocationCount);
Assert.assertEquals(1, root.invocationCount);
IDelegatingScopeProvider.setWrapper(delegating, null);
Assert.assertEquals(2, delegating.invocationCount);
Assert.assertEquals(2, root.invocationCount);
}
@Test
public void testOneSuitableDelegate_02() {
final int[] invocationCount = new int[] { 0 };
AbstractGlobalScopeDelegatingScopeProvider root = new AbstractGlobalScopeDelegatingScopeProvider() {
@Override
public IScope getScope(EObject context, EReference reference) {
return IScope.NULLSCOPE;
}
@Override
public void setWrapper(IScopeWrapper wrapper) {
invocationCount[0]++;
Assert.assertEquals(DelegatingScopeProviderTest.this, wrapper);
super.setWrapper(wrapper);
}
};
TestableDelegatingScopeProvider delegating = new TestableDelegatingScopeProvider(root);
delegating.setWrapper(this);
Assert.assertEquals(1, delegating.invocationCount);
Assert.assertEquals(1, invocationCount[0]);
}
@Test
public void testTwoSuitableDelegates_02() {
final int[] invocationCount = new int[] { 0 };
AbstractGlobalScopeDelegatingScopeProvider first = new AbstractGlobalScopeDelegatingScopeProvider() {
@Override
public IScope getScope(EObject context, EReference reference) {
return IScope.NULLSCOPE;
}
@Override
public void setWrapper(IScopeWrapper wrapper) {
invocationCount[0]++;
Assert.assertEquals(DelegatingScopeProviderTest.this, wrapper);
super.setWrapper(wrapper);
}
};
AbstractGlobalScopeDelegatingScopeProvider second = new AbstractGlobalScopeDelegatingScopeProvider() {
@Override
public IScope getScope(EObject context, EReference reference) {
return IScope.NULLSCOPE;
}
@Override
public void setWrapper(IScopeWrapper wrapper) {
invocationCount[0]++;
Assert.assertEquals(DelegatingScopeProviderTest.this, wrapper);
super.setWrapper(wrapper);
}
};
TestableDelegatingScopeProvider delegating = new TestableDelegatingScopeProvider(first) {
@Override
public void setWrapper(IScopeWrapper wrapper) {
IDelegatingScopeProvider.setWrapper(second, wrapper);
super.setWrapper(wrapper);
};
};
delegating.setWrapper(this);
Assert.assertEquals(1, delegating.invocationCount);
Assert.assertEquals(2, invocationCount[0]);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2017 itemis AG (http://www.itemis.eu) and others.
* Copyright (c) 2008, 2018 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -21,7 +21,6 @@ import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.IScopeProvider;
import org.eclipse.xtext.scoping.impl.AbstractGlobalScopeDelegatingScopeProvider;
import org.eclipse.xtext.scoping.impl.IDelegatingScopeProvider;
import com.google.inject.Inject;
@ -67,13 +66,7 @@ public class DefaultLinkingService extends AbstractLinkingService {
}
protected void unRegisterImportedNamesAdapter(IScopeProvider scopeProvider) {
if (scopeProvider instanceof AbstractGlobalScopeDelegatingScopeProvider) {
AbstractGlobalScopeDelegatingScopeProvider provider = (AbstractGlobalScopeDelegatingScopeProvider) scopeProvider;
provider.setWrapper(null);
} else if (scopeProvider instanceof IDelegatingScopeProvider) {
IDelegatingScopeProvider delegatingScopeProvider = (IDelegatingScopeProvider) scopeProvider;
unRegisterImportedNamesAdapter(delegatingScopeProvider.getDelegate());
}
IDelegatingScopeProvider.setWrapper(scopeProvider, null);
}
protected void registerImportedNamesAdapter(EObject context) {
@ -81,14 +74,8 @@ public class DefaultLinkingService extends AbstractLinkingService {
}
protected void registerImportedNamesAdapter(IScopeProvider scopeProvider, EObject context) {
if (scopeProvider instanceof AbstractGlobalScopeDelegatingScopeProvider) {
AbstractGlobalScopeDelegatingScopeProvider provider = (AbstractGlobalScopeDelegatingScopeProvider) scopeProvider;
ImportedNamesAdapter adapter = getImportedNamesAdapter(context);
provider.setWrapper(adapter);
} else if (scopeProvider instanceof IDelegatingScopeProvider) {
IDelegatingScopeProvider delegatingScopeProvider = (IDelegatingScopeProvider) scopeProvider;
registerImportedNamesAdapter(delegatingScopeProvider.getDelegate(), context);
}
ImportedNamesAdapter adapter = getImportedNamesAdapter(context);
IDelegatingScopeProvider.setWrapper(scopeProvider, adapter);
}
protected ImportedNamesAdapter getImportedNamesAdapter(EObject context) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
* Copyright (c) 2011, 2018 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -29,4 +29,34 @@ public interface IDelegatingScopeProvider extends IScopeProvider {
*/
IScopeProvider getDelegate();
/**
* Set the wrapper this delegating scope provider. This encapsulates the traversal of the
* delegate and allows clients to set the wrapper on multiple delegates if necessary.
*
* The wrapper may be <code>null</code>
*
* @since 2.14
*/
default void setWrapper(IScopeWrapper wrapper) {
setWrapper(getDelegate(), wrapper);
}
/**
* Set the given wrapper on the given {@link IScopeProvider} if the scope provider is either a
* delegating scope provider or an {@link AbstractGlobalScopeDelegatingScopeProvider}.
*
* The wrapper may be <code>null</code>
*
* @since 2.14
*/
static void setWrapper(IScopeProvider scopeProvider, IScopeWrapper wrapper) {
if (scopeProvider instanceof AbstractGlobalScopeDelegatingScopeProvider) {
AbstractGlobalScopeDelegatingScopeProvider provider = (AbstractGlobalScopeDelegatingScopeProvider) scopeProvider;
provider.setWrapper(wrapper);
} else if (scopeProvider instanceof IDelegatingScopeProvider) {
IDelegatingScopeProvider delegatingScopeProvider = (IDelegatingScopeProvider) scopeProvider;
delegatingScopeProvider.setWrapper(wrapper);
}
}
}