From 8c7295e56ed0ace066250ba8333f17be235a4ce1 Mon Sep 17 00:00:00 2001 From: Jan Koehnlein Date: Tue, 7 Nov 2017 08:54:24 +0100 Subject: [PATCH 1/3] GH-524 use Module2.mixin() to combine runtime and IDE module in example languages --- .../ide/PartialContentAssistTestLanguageIdeSetup.xtend | 3 ++- .../ide/PartialContentAssistTestLanguageIdeSetup.java | 3 ++- .../backtracking/ide/BeeLangTestLanguageIdeSetup.java | 8 +++++--- .../backtracking/ide/ExBeeLangTestLanguageIdeSetup.java | 3 ++- .../ide/SimpleBeeLangTestLanguageIdeSetup.java | 8 +++++--- .../noJdt/ide/NoJdtTestLanguageIdeSetup.java | 3 ++- .../ide/XtextGrammarTestLanguageIdeSetup.java | 8 +++++--- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/org.eclipse.xtext.ide.tests/testlang-src/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.xtend b/org.eclipse.xtext.ide.tests/testlang-src/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.xtend index ab8ec8929..d11ce6b08 100644 --- a/org.eclipse.xtext.ide.tests/testlang-src/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.xtend +++ b/org.eclipse.xtext.ide.tests/testlang-src/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.xtend @@ -10,6 +10,7 @@ package org.eclipse.xtext.ide.tests.testlanguage.ide import com.google.inject.Guice import org.eclipse.xtext.ide.tests.testlanguage.PartialContentAssistTestLanguageRuntimeModule import org.eclipse.xtext.ide.tests.testlanguage.PartialContentAssistTestLanguageStandaloneSetup +import org.eclipse.xtext.util.Modules2 /** * Initialization support for running Xtext languages without Equinox extension registry. @@ -17,6 +18,6 @@ import org.eclipse.xtext.ide.tests.testlanguage.PartialContentAssistTestLanguage class PartialContentAssistTestLanguageIdeSetup extends PartialContentAssistTestLanguageStandaloneSetup { override createInjector() { - Guice.createInjector(new PartialContentAssistTestLanguageRuntimeModule, new PartialContentAssistTestLanguageIdeModule) + Guice.createInjector(Modules2.mixin(new PartialContentAssistTestLanguageRuntimeModule, new PartialContentAssistTestLanguageIdeModule)) } } diff --git a/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.java b/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.java index 8fd1df5ed..0050cff48 100644 --- a/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.java +++ b/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/testlanguage/ide/PartialContentAssistTestLanguageIdeSetup.java @@ -12,6 +12,7 @@ import com.google.inject.Injector; import org.eclipse.xtext.ide.tests.testlanguage.PartialContentAssistTestLanguageRuntimeModule; import org.eclipse.xtext.ide.tests.testlanguage.PartialContentAssistTestLanguageStandaloneSetup; import org.eclipse.xtext.ide.tests.testlanguage.ide.PartialContentAssistTestLanguageIdeModule; +import org.eclipse.xtext.util.Modules2; /** * Initialization support for running Xtext languages without Equinox extension registry. @@ -22,6 +23,6 @@ public class PartialContentAssistTestLanguageIdeSetup extends PartialContentAssi public Injector createInjector() { PartialContentAssistTestLanguageRuntimeModule _partialContentAssistTestLanguageRuntimeModule = new PartialContentAssistTestLanguageRuntimeModule(); PartialContentAssistTestLanguageIdeModule _partialContentAssistTestLanguageIdeModule = new PartialContentAssistTestLanguageIdeModule(); - return Guice.createInjector(_partialContentAssistTestLanguageRuntimeModule, _partialContentAssistTestLanguageIdeModule); + return Guice.createInjector(Modules2.mixin(_partialContentAssistTestLanguageRuntimeModule, _partialContentAssistTestLanguageIdeModule)); } } diff --git a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/BeeLangTestLanguageIdeSetup.java b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/BeeLangTestLanguageIdeSetup.java index fa48657c6..44d94cada 100644 --- a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/BeeLangTestLanguageIdeSetup.java +++ b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/BeeLangTestLanguageIdeSetup.java @@ -3,10 +3,12 @@ */ package org.eclipse.xtext.testlanguages.backtracking.ide; -import com.google.inject.Guice; -import com.google.inject.Injector; import org.eclipse.xtext.testlanguages.backtracking.BeeLangTestLanguageRuntimeModule; import org.eclipse.xtext.testlanguages.backtracking.BeeLangTestLanguageStandaloneSetup; +import org.eclipse.xtext.util.Modules2; + +import com.google.inject.Guice; +import com.google.inject.Injector; /** * Initialization support for running Xtext languages without Equinox extension registry. @@ -15,6 +17,6 @@ public class BeeLangTestLanguageIdeSetup extends BeeLangTestLanguageStandaloneSe @Override public Injector createInjector() { - return Guice.createInjector(new BeeLangTestLanguageRuntimeModule(), new BeeLangTestLanguageIdeModule()); + return Guice.createInjector(Modules2.mixin(new BeeLangTestLanguageRuntimeModule(), new BeeLangTestLanguageIdeModule())); } } diff --git a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/ExBeeLangTestLanguageIdeSetup.java b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/ExBeeLangTestLanguageIdeSetup.java index ee222b751..03d46e0ec 100644 --- a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/ExBeeLangTestLanguageIdeSetup.java +++ b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/ExBeeLangTestLanguageIdeSetup.java @@ -7,6 +7,7 @@ import com.google.inject.Guice; import com.google.inject.Injector; import org.eclipse.xtext.testlanguages.backtracking.ExBeeLangTestLanguageRuntimeModule; import org.eclipse.xtext.testlanguages.backtracking.ExBeeLangTestLanguageStandaloneSetup; +import org.eclipse.xtext.util.Modules2; /** * Initialization support for running Xtext languages without Equinox extension registry. @@ -15,6 +16,6 @@ public class ExBeeLangTestLanguageIdeSetup extends ExBeeLangTestLanguageStandalo @Override public Injector createInjector() { - return Guice.createInjector(new ExBeeLangTestLanguageRuntimeModule(), new ExBeeLangTestLanguageIdeModule()); + return Guice.createInjector(Modules2.mixin(new ExBeeLangTestLanguageRuntimeModule(), new ExBeeLangTestLanguageIdeModule())); } } diff --git a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/SimpleBeeLangTestLanguageIdeSetup.java b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/SimpleBeeLangTestLanguageIdeSetup.java index 7ffff6ded..a8d6a7574 100644 --- a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/SimpleBeeLangTestLanguageIdeSetup.java +++ b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/backtracking/ide/SimpleBeeLangTestLanguageIdeSetup.java @@ -3,10 +3,12 @@ */ package org.eclipse.xtext.testlanguages.backtracking.ide; -import com.google.inject.Guice; -import com.google.inject.Injector; import org.eclipse.xtext.testlanguages.backtracking.SimpleBeeLangTestLanguageRuntimeModule; import org.eclipse.xtext.testlanguages.backtracking.SimpleBeeLangTestLanguageStandaloneSetup; +import org.eclipse.xtext.util.Modules2; + +import com.google.inject.Guice; +import com.google.inject.Injector; /** * Initialization support for running Xtext languages without Equinox extension registry. @@ -15,6 +17,6 @@ public class SimpleBeeLangTestLanguageIdeSetup extends SimpleBeeLangTestLanguage @Override public Injector createInjector() { - return Guice.createInjector(new SimpleBeeLangTestLanguageRuntimeModule(), new SimpleBeeLangTestLanguageIdeModule()); + return Guice.createInjector(Modules2.mixin(new SimpleBeeLangTestLanguageRuntimeModule(), new SimpleBeeLangTestLanguageIdeModule())); } } diff --git a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/noJdt/ide/NoJdtTestLanguageIdeSetup.java b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/noJdt/ide/NoJdtTestLanguageIdeSetup.java index a5dd6f079..fbb65ab46 100644 --- a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/noJdt/ide/NoJdtTestLanguageIdeSetup.java +++ b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/noJdt/ide/NoJdtTestLanguageIdeSetup.java @@ -7,6 +7,7 @@ import com.google.inject.Guice; import com.google.inject.Injector; import org.eclipse.xtext.testlanguages.noJdt.NoJdtTestLanguageRuntimeModule; import org.eclipse.xtext.testlanguages.noJdt.NoJdtTestLanguageStandaloneSetup; +import org.eclipse.xtext.util.Modules2; /** * Initialization support for running Xtext languages without Equinox extension registry. @@ -15,6 +16,6 @@ public class NoJdtTestLanguageIdeSetup extends NoJdtTestLanguageStandaloneSetup @Override public Injector createInjector() { - return Guice.createInjector(new NoJdtTestLanguageRuntimeModule(), new NoJdtTestLanguageIdeModule()); + return Guice.createInjector(Modules2.mixin(new NoJdtTestLanguageRuntimeModule(), new NoJdtTestLanguageIdeModule())); } } diff --git a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/xtextgrammar/ide/XtextGrammarTestLanguageIdeSetup.java b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/xtextgrammar/ide/XtextGrammarTestLanguageIdeSetup.java index b64b73343..32e91729e 100644 --- a/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/xtextgrammar/ide/XtextGrammarTestLanguageIdeSetup.java +++ b/org.eclipse.xtext.testlanguages.ide/src/org/eclipse/xtext/testlanguages/xtextgrammar/ide/XtextGrammarTestLanguageIdeSetup.java @@ -3,10 +3,12 @@ */ package org.eclipse.xtext.testlanguages.xtextgrammar.ide; -import com.google.inject.Guice; -import com.google.inject.Injector; import org.eclipse.xtext.testlanguages.xtextgrammar.XtextGrammarTestLanguageRuntimeModule; import org.eclipse.xtext.testlanguages.xtextgrammar.XtextGrammarTestLanguageStandaloneSetup; +import org.eclipse.xtext.util.Modules2; + +import com.google.inject.Guice; +import com.google.inject.Injector; /** * Initialization support for running Xtext languages without Equinox extension registry. @@ -15,6 +17,6 @@ public class XtextGrammarTestLanguageIdeSetup extends XtextGrammarTestLanguageSt @Override public Injector createInjector() { - return Guice.createInjector(new XtextGrammarTestLanguageRuntimeModule(), new XtextGrammarTestLanguageIdeModule()); + return Guice.createInjector(Modules2.mixin(new XtextGrammarTestLanguageRuntimeModule(), new XtextGrammarTestLanguageIdeModule())); } } From 15b13a279d46cf2df8a54948ab595a2f0dbf03f8 Mon Sep 17 00:00:00 2001 From: Jan Koehnlein Date: Tue, 7 Nov 2017 08:59:19 +0100 Subject: [PATCH 2/3] GH-520 allow shadowed resource descriptions in language server scenario --- .../ide/tests/server/RenameIssue520Test.xtend | 47 ---- .../xtext/ide/tests/server/RenameTest.xtend | 2 +- .../ide/tests/server/RenameIssue520Test.java | 68 ------ .../xtext/ide/tests/server/RenameTest.java | 2 +- .../eclipse/xtext/ide/DefaultIdeModule.xtend | 15 ++ .../ide/server/rename/RenameService.xtend | 18 +- .../eclipse/xtext/ide/DefaultIdeModule.java | 14 ++ .../ide/server/rename/RenameService.java | 21 +- ...iveContainerTestLanguageRuntimeModule.java | 6 + .../LiveShadowedChunkedContainerTest.xtend | 169 ++++++++++++++ .../LiveShadowedChunkedContainerTest.java | 197 +++++++++++++++++ .../resource/containers/ProjectConfig.java | 74 +++++++ .../resource/containers/SourceFolder.java | 37 ++++ .../LiveShadowedChunkedContainer.xtend | 120 ++++++++++ ...jectDescriptionBasedContainerManager.xtend | 63 +++--- ...eShadowedChunkedResourceDescriptions.xtend | 37 ++++ .../LiveShadowedResourceDescriptions.java | 15 +- .../LiveShadowedChunkedContainer.java | 209 ++++++++++++++++++ ...ojectDescriptionBasedContainerManager.java | 102 +++++---- ...veShadowedChunkedResourceDescriptions.java | 64 ++++++ 20 files changed, 1075 insertions(+), 205 deletions(-) delete mode 100644 org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.xtend delete mode 100644 org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.java create mode 100644 org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.xtend create mode 100644 org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.java create mode 100644 org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/ProjectConfig.java create mode 100644 org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/SourceFolder.java create mode 100644 org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.xtend create mode 100644 org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.xtend create mode 100644 org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.java create mode 100644 org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.java diff --git a/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.xtend b/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.xtend deleted file mode 100644 index e23aa56cc..000000000 --- a/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.xtend +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2017 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.ide.tests.server - -import org.eclipse.lsp4j.Position -import org.eclipse.lsp4j.RenameParams -import org.eclipse.lsp4j.TextDocumentIdentifier -import org.junit.Ignore -import org.junit.Test - -/** - * @author Christian Dietrich - Initial contribution and API - */ - // FIXME https://github.com/eclipse/xtext-core/issues/520 - @Ignore("https://github.com/eclipse/xtext-core/issues/520") -class RenameIssue520Test extends AbstractTestLangLanguageServerTest { - - @Test def void testTwoFiles() { - val model = ''' - type Foo { - } - ''' - val file = 'foo/Foo.testlang'.writeFile(model) - val model2 = ''' - type Bar { - Foo ref - } - ''' - 'foo/Bar.testlang'.writeFile(model2) - initialize - - val params = new RenameParams(new TextDocumentIdentifier(file), new Position(0, 6), 'FooNeu') - val workspaceEdit = languageServer.rename(params).get - assertEquals(''' - changes : - Foo.testlang : FooNeu [[0, 5] .. [0, 8]] - Bar.testlang : FooNeu [[1, 1] .. [1, 4]] - documentChanges : - - '''.toString, toExpectation(workspaceEdit)) - } -} \ No newline at end of file diff --git a/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameTest.xtend b/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameTest.xtend index 23c88336d..8ec9c6e28 100644 --- a/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameTest.xtend +++ b/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/RenameTest.xtend @@ -60,7 +60,7 @@ class RenameTest extends AbstractTestLangLanguageServerTest { changes : MyType1.testlang : Tescht [[0, 5] .. [0, 9]] Tescht [[1, 4] .. [1, 8]] - MyType2.testlang : Test [[1, 4] .. [1, 8]] + MyType2.testlang : Tescht [[1, 4] .. [1, 8]] documentChanges : '''.toString, toExpectation(workspaceEdit)) } diff --git a/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.java b/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.java deleted file mode 100644 index 2a597d85a..000000000 --- a/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameIssue520Test.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2017 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.ide.tests.server; - -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.RenameParams; -import org.eclipse.lsp4j.TextDocumentIdentifier; -import org.eclipse.lsp4j.WorkspaceEdit; -import org.eclipse.xtend2.lib.StringConcatenation; -import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest; -import org.eclipse.xtext.xbase.lib.Exceptions; -import org.junit.Ignore; -import org.junit.Test; - -/** - * @author Christian Dietrich - Initial contribution and API - */ -@Ignore("https://github.com/eclipse/xtext-core/issues/520") -@SuppressWarnings("all") -public class RenameIssue520Test extends AbstractTestLangLanguageServerTest { - @Test - public void testTwoFiles() { - try { - StringConcatenation _builder = new StringConcatenation(); - _builder.append("type Foo {"); - _builder.newLine(); - _builder.append("}"); - _builder.newLine(); - final String model = _builder.toString(); - final String file = this.writeFile("foo/Foo.testlang", model); - StringConcatenation _builder_1 = new StringConcatenation(); - _builder_1.append("type Bar {"); - _builder_1.newLine(); - _builder_1.append("\t"); - _builder_1.append("Foo ref"); - _builder_1.newLine(); - _builder_1.append("}"); - _builder_1.newLine(); - final String model2 = _builder_1.toString(); - this.writeFile("foo/Bar.testlang", model2); - this.initialize(); - TextDocumentIdentifier _textDocumentIdentifier = new TextDocumentIdentifier(file); - Position _position = new Position(0, 6); - final RenameParams params = new RenameParams(_textDocumentIdentifier, _position, "FooNeu"); - final WorkspaceEdit workspaceEdit = this.languageServer.rename(params).get(); - StringConcatenation _builder_2 = new StringConcatenation(); - _builder_2.append("changes :"); - _builder_2.newLine(); - _builder_2.append(" "); - _builder_2.append("Foo.testlang : FooNeu [[0, 5] .. [0, 8]]"); - _builder_2.newLine(); - _builder_2.append(" "); - _builder_2.append("Bar.testlang : FooNeu [[1, 1] .. [1, 4]]"); - _builder_2.newLine(); - _builder_2.append("documentChanges : "); - _builder_2.newLine(); - _builder_2.newLine(); - this.assertEquals(_builder_2.toString(), this.toExpectation(workspaceEdit)); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } -} diff --git a/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameTest.java b/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameTest.java index 63435dec6..89e9052cd 100644 --- a/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameTest.java +++ b/org.eclipse.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/RenameTest.java @@ -84,7 +84,7 @@ public class RenameTest extends AbstractTestLangLanguageServerTest { _builder.append("Tescht [[1, 4] .. [1, 8]]"); _builder.newLine(); _builder.append("\t"); - _builder.append("MyType2.testlang : Test [[1, 4] .. [1, 8]]"); + _builder.append("MyType2.testlang : Tescht [[1, 4] .. [1, 8]]"); _builder.newLine(); _builder.append("documentChanges : "); _builder.newLine(); diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/DefaultIdeModule.xtend b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/DefaultIdeModule.xtend index 4e2fa4281..1335edec1 100644 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/DefaultIdeModule.xtend +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/DefaultIdeModule.xtend @@ -8,8 +8,14 @@ package org.eclipse.xtext.ide import com.google.inject.Binder +import com.google.inject.name.Names import java.util.concurrent.ExecutorService +import org.eclipse.xtext.resource.IResourceDescriptions +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions +import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider import org.eclipse.xtext.service.AbstractGenericModule +import org.eclipse.xtext.workspace.IProjectConfigProvider +import org.eclipse.xtext.workspace.ProjectConfigProvider /** * Default Guice bindings for the generic IDE features of Xtext. @@ -20,4 +26,13 @@ class DefaultIdeModule extends AbstractGenericModule { binder.bind(ExecutorService).toProvider(ExecutorServiceProvider) } + def void configureIResourceDescriptionsLiveScope(Binder binder) { + binder.bind(IResourceDescriptions) + .annotatedWith(Names.named(ResourceDescriptionsProvider.LIVE_SCOPE)) + .to(LiveShadowedChunkedResourceDescriptions); + } + + def Class bindIProjectConfigProvider() { + ProjectConfigProvider + } } \ No newline at end of file diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService.xtend b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService.xtend index a10dd2935..32caa768e 100644 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService.xtend +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/rename/RenameService.xtend @@ -22,6 +22,7 @@ import org.eclipse.xtext.resource.XtextResource import org.eclipse.xtext.util.CancelIndicator import static org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor.Severity.* import org.eclipse.xtext.ide.refactoring.IRenameStrategy2 +import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider /** * @author koehnlein - Initial contribution and API @@ -47,19 +48,22 @@ class RenameService implements IRenameService { workspaceManager.doRead(uri) [ document, resource | val projectManager = workspaceManager.getProjectManager(uri) val resourceSet = projectManager.createNewResourceSet(projectManager.indexState.resourceDescriptions) + resourceSet.loadOptions.put(ResourceDescriptionsProvider.LIVE_SCOPE, true) val offset = document.getOffSet(renameParams.position) val workspaceEdit = new WorkspaceEdit val xtextResource = resourceSet.getResource(resource.URI, true) if (xtextResource instanceof XtextResource) { val element = xtextResource.resolveElementAt(offset) - if (element === null) + if (element === null || element.eIsProxy) { issueAcceptor.add(FATAL, '''No element found at position line:«renameParams.position.line» column:«renameParams.position.character»''') - val change = new RenameChange(renameParams.newName, EcoreUtil.getURI(element)) - val changeSerializer = changeSerializerProvider.get - val context = new RenameContext(#[change], resourceSet, changeSerializer, issueAcceptor) - renameStrategy.applyRename(context) - val changeConverter = converterFactory.create(workspaceManager, workspaceEdit) - changeSerializer.applyModifications(changeConverter) + } else { + val change = new RenameChange(renameParams.newName, EcoreUtil.getURI(element)) + val changeSerializer = changeSerializerProvider.get + val context = new RenameContext(#[change], resourceSet, changeSerializer, issueAcceptor) + renameStrategy.applyRename(context) + val changeConverter = converterFactory.create(workspaceManager, workspaceEdit) + changeSerializer.applyModifications(changeConverter) + } } else { issueAcceptor.add(FATAL, 'Loaded resource is not an XtextResource', resource.URI) } diff --git a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/DefaultIdeModule.java b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/DefaultIdeModule.java index 0feaffb1f..5076395e0 100644 --- a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/DefaultIdeModule.java +++ b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/DefaultIdeModule.java @@ -8,9 +8,15 @@ package org.eclipse.xtext.ide; import com.google.inject.Binder; +import com.google.inject.name.Names; import java.util.concurrent.ExecutorService; import org.eclipse.xtext.ide.ExecutorServiceProvider; +import org.eclipse.xtext.resource.IResourceDescriptions; +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions; +import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider; import org.eclipse.xtext.service.AbstractGenericModule; +import org.eclipse.xtext.workspace.IProjectConfigProvider; +import org.eclipse.xtext.workspace.ProjectConfigProvider; /** * Default Guice bindings for the generic IDE features of Xtext. @@ -20,4 +26,12 @@ public class DefaultIdeModule extends AbstractGenericModule { public void configureExecutorService(final Binder binder) { binder.bind(ExecutorService.class).toProvider(ExecutorServiceProvider.class); } + + public void configureIResourceDescriptionsLiveScope(final Binder binder) { + binder.bind(IResourceDescriptions.class).annotatedWith(Names.named(ResourceDescriptionsProvider.LIVE_SCOPE)).to(LiveShadowedChunkedResourceDescriptions.class); + } + + public Class bindIProjectConfigProvider() { + return ProjectConfigProvider.class; + } } diff --git a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/RenameService.java b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/RenameService.java index 83fde932b..e5ed9d7cb 100644 --- a/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/RenameService.java +++ b/org.eclipse.xtext.ide/xtend-gen/org/eclipse/xtext/ide/server/rename/RenameService.java @@ -32,6 +32,7 @@ import org.eclipse.xtext.ide.server.rename.ServerRefactoringIssueAcceptor; import org.eclipse.xtext.resource.EObjectAtOffsetHelper; import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.resource.XtextResourceSet; +import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider; import org.eclipse.xtext.util.CancelIndicator; import org.eclipse.xtext.xbase.lib.CollectionLiterals; import org.eclipse.xtext.xbase.lib.Extension; @@ -72,12 +73,13 @@ public class RenameService implements IRenameService { final Function2 _function = (Document document, XtextResource resource) -> { final ProjectManager projectManager = workspaceManager.getProjectManager(uri); final XtextResourceSet resourceSet = projectManager.createNewResourceSet(projectManager.getIndexState().getResourceDescriptions()); + resourceSet.getLoadOptions().put(ResourceDescriptionsProvider.LIVE_SCOPE, Boolean.valueOf(true)); final int offset = document.getOffSet(renameParams.getPosition()); final WorkspaceEdit workspaceEdit = new WorkspaceEdit(); final Resource xtextResource = resourceSet.getResource(resource.getURI(), true); if ((xtextResource instanceof XtextResource)) { final EObject element = this._eObjectAtOffsetHelper.resolveElementAt(((XtextResource)xtextResource), offset); - if ((element == null)) { + if (((element == null) || element.eIsProxy())) { StringConcatenation _builder = new StringConcatenation(); _builder.append("No element found at position line:"); int _line = renameParams.getPosition().getLine(); @@ -86,15 +88,16 @@ public class RenameService implements IRenameService { int _character = renameParams.getPosition().getCharacter(); _builder.append(_character); issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, _builder.toString()); + } else { + String _newName = renameParams.getNewName(); + URI _uRI = EcoreUtil.getURI(element); + final RenameChange change = new RenameChange(_newName, _uRI); + final IChangeSerializer changeSerializer = this.changeSerializerProvider.get(); + final RenameContext context = new RenameContext(Collections.unmodifiableList(CollectionLiterals.newArrayList(change)), resourceSet, changeSerializer, issueAcceptor); + this.renameStrategy.applyRename(context); + final ChangeConverter changeConverter = this.converterFactory.create(workspaceManager, workspaceEdit); + changeSerializer.applyModifications(changeConverter); } - String _newName = renameParams.getNewName(); - URI _uRI = EcoreUtil.getURI(element); - final RenameChange change = new RenameChange(_newName, _uRI); - final IChangeSerializer changeSerializer = this.changeSerializerProvider.get(); - final RenameContext context = new RenameContext(Collections.unmodifiableList(CollectionLiterals.newArrayList(change)), resourceSet, changeSerializer, issueAcceptor); - this.renameStrategy.applyRename(context); - final ChangeConverter changeConverter = this.converterFactory.create(workspaceManager, workspaceEdit); - changeSerializer.applyModifications(changeConverter); } else { issueAcceptor.add(RefactoringIssueAcceptor.Severity.FATAL, "Loaded resource is not an XtextResource", resource.getURI()); } diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/LiveContainerTestLanguageRuntimeModule.java b/org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/LiveContainerTestLanguageRuntimeModule.java index 36a33aa37..0c3753c15 100644 --- a/org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/LiveContainerTestLanguageRuntimeModule.java +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/LiveContainerTestLanguageRuntimeModule.java @@ -3,9 +3,15 @@ */ package org.eclipse.xtext.resource; +import org.eclipse.xtext.workspace.IProjectConfigProvider; +import org.eclipse.xtext.workspace.ProjectConfigProvider; + /** * Use this class to register components to be used at runtime / without the Equinox extension registry. */ public class LiveContainerTestLanguageRuntimeModule extends org.eclipse.xtext.resource.AbstractLiveContainerTestLanguageRuntimeModule { + public Class bindIProjectConfigProvider() { + return ProjectConfigProvider.class; + } } diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.xtend b/org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.xtend new file mode 100644 index 000000000..a00ebabab --- /dev/null +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.xtend @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2017 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.resource.containers + +import com.google.inject.Inject +import com.google.inject.Provider +import java.io.File +import java.util.Set +import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtend.lib.annotations.Accessors +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor +import org.eclipse.xtext.naming.QualifiedName +import org.eclipse.xtext.resource.IResourceDescription +import org.eclipse.xtext.resource.LiveContainerTestLanguageInjectorProvider +import org.eclipse.xtext.resource.XtextResourceSet +import org.eclipse.xtext.resource.impl.ChunkedResourceDescriptions +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions +import org.eclipse.xtext.resource.impl.ResourceDescriptionsData +import org.eclipse.xtext.resource.liveContainerTestLanguage.Model +import org.eclipse.xtext.testing.InjectWith +import org.eclipse.xtext.testing.XtextRunner +import org.eclipse.xtext.testing.util.ParseHelper +import org.eclipse.xtext.workspace.IProjectConfig +import org.eclipse.xtext.workspace.ISourceFolder +import org.eclipse.xtext.workspace.IWorkspaceConfig +import org.eclipse.xtext.workspace.ProjectConfigAdapter +import org.eclipse.xtext.workspace.WorkspaceConfig +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +import static org.eclipse.xtext.resource.liveContainerTestLanguage.LiveContainerTestLanguagePackage.Literals.* +import static org.junit.Assert.* + +import static extension org.eclipse.xtext.util.UriUtil.* + +/** + * @author koehnlein - Initial contribution and API + */ +@RunWith(XtextRunner) +@InjectWith(LiveContainerTestLanguageInjectorProvider) +class LiveShadowedChunkedContainerTest { + + @Inject extension ParseHelper + @Inject Provider resourceSetProvider + @Inject IResourceDescription.Manager resourceDescriptionManager + @Inject Provider provider + + ProjectConfig fooProject + ProjectConfig barProject + + URI fooURI + URI barURI + + XtextResourceSet rs1 + + LiveShadowedChunkedContainer fooContainer + LiveShadowedChunkedContainer barContainer + + @Before + def void setUp() { + val workspaceConfig = new WorkspaceConfig() + fooProject = new ProjectConfig('foo', workspaceConfig) + barProject = new ProjectConfig('bar', workspaceConfig) + val rs0 = resourceSetProvider.get + fooURI = fooProject.sourceFolders.head.path.trimSegments(1).appendSegment('foo.livecontainertestlanguage') + barURI = barProject.sourceFolders.head.path.trimSegments(1).appendSegment('bar.livecontainertestlanguage') + val chunks = #{ + 'foo' -> createResourceDescriptionData('foo'.parse(fooURI, rs0).eResource), + 'bar' -> createResourceDescriptionData('bar'.parse(barURI, rs0).eResource) + } + rs1 = resourceSetProvider.get + new ChunkedResourceDescriptions(chunks, rs1) + ProjectConfigAdapter.install(rs1, fooProject) + val liveShadowedChunkedResourceDescriptions = provider.get + liveShadowedChunkedResourceDescriptions.context = rs1 + fooContainer = new LiveShadowedChunkedContainer(liveShadowedChunkedResourceDescriptions, 'foo') + barContainer = new LiveShadowedChunkedContainer(liveShadowedChunkedResourceDescriptions, 'bar') + } + + @Test + def testRenameElement() { + 'fooChange'.parse(fooURI, rs1) + assertEquals('fooChange', fooContainer.exportedObjects.map[qualifiedName.toString].join(',')) + assertEquals('fooChange', fooContainer.getExportedObjects(MODEL, QualifiedName.create('fooChange'), false).map[qualifiedName.toString].join(',')) + assertEquals('fooChange', fooContainer.getExportedObjectsByType(MODEL).map[qualifiedName.toString].join(',')) + assertEquals(1, fooContainer.resourceDescriptions.size) + assertEquals(1, fooContainer.resourceDescriptionCount) + assertTrue(fooContainer.hasResourceDescription(fooURI)) + assertFalse(fooContainer.hasResourceDescription(barURI)) + assertEquals(fooURI, fooContainer.getResourceDescription(fooURI).URI) + + assertEquals('bar', barContainer.exportedObjects.map[qualifiedName.toString].join(',')) + assertEquals('bar', barContainer.getExportedObjects(MODEL, QualifiedName.create('bar'), false).map[qualifiedName.toString].join(',')) + assertEquals('bar', barContainer.getExportedObjectsByType(MODEL).map[qualifiedName.toString].join(',')) + assertEquals(1, barContainer.resourceDescriptions.size) + assertEquals(1, barContainer.resourceDescriptionCount) + assertTrue(barContainer.hasResourceDescription(barURI)) + assertFalse(barContainer.hasResourceDescription(fooURI)) + assertEquals(barURI, barContainer.getResourceDescription(barURI).URI) + } + + @Test + def testAddResource() { + 'baz'.parse(fooProject.sourceFolders.head.path.trimSegments(1).appendSegment('baz.livecontainertestlanguage'), rs1) + assertEquals(2, fooContainer.resourceDescriptions.size) + assertEquals(2, fooContainer.resourceDescriptionCount) + assertEquals('baz,foo', fooContainer.exportedObjects.map[qualifiedName.toString].sort.join(',')) + assertEquals(1, barContainer.resourceDescriptions.size) + assertEquals(1, barContainer.resourceDescriptionCount) + } + + @Test + def testDeleteElement() { + 'foo'.parse(fooURI, rs1).eResource.contents.clear() + assertEquals('', fooContainer.exportedObjects.map[qualifiedName.toString].join(',')) + assertEquals(1, fooContainer.resourceDescriptions.size) + assertEquals(1, fooContainer.resourceDescriptionCount) + assertEquals(0, fooContainer.exportedObjects.size) + assertEquals(1, barContainer.resourceDescriptions.size) + assertEquals(1, barContainer.resourceDescriptionCount) + } + + private def createResourceDescriptionData(Resource... resources) { + new ResourceDescriptionsData(resources.map[ + resourceDescriptionManager.getResourceDescription(it) + ]) + } +} + +@Accessors(PUBLIC_GETTER) +class ProjectConfig implements IProjectConfig { + + URI path + Set sourceFolders = newHashSet + String name + IWorkspaceConfig workspaceConfig + + new(String name, WorkspaceConfig workspaceConfig) { + this.name = name + + this.path = URI.createURI(new File(name).absoluteFile.toURI.toString).appendSegment('') + sourceFolders.add(new SourceFolder(path.trimSegments(1).appendSegment('src').appendSegment(''))) + this.workspaceConfig = workspaceConfig + workspaceConfig.addProject(this) + } + + override findSourceFolderContaining(URI member) { + sourceFolders.findFirst[path.isPrefixOf(member)] + } +} + + +@FinalFieldsConstructor +@Accessors(PUBLIC_GETTER) +class SourceFolder implements ISourceFolder { + + val URI path + + override getName() { + 'src' + } +} diff --git a/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.java b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.java new file mode 100644 index 000000000..4fa797b95 --- /dev/null +++ b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainerTest.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2017 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.resource.containers; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.xtext.naming.QualifiedName; +import org.eclipse.xtext.resource.IEObjectDescription; +import org.eclipse.xtext.resource.IResourceDescription; +import org.eclipse.xtext.resource.LiveContainerTestLanguageInjectorProvider; +import org.eclipse.xtext.resource.XtextResourceSet; +import org.eclipse.xtext.resource.containers.LiveShadowedChunkedContainer; +import org.eclipse.xtext.resource.containers.ProjectConfig; +import org.eclipse.xtext.resource.containers.SourceFolder; +import org.eclipse.xtext.resource.impl.ChunkedResourceDescriptions; +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions; +import org.eclipse.xtext.resource.impl.ResourceDescriptionsData; +import org.eclipse.xtext.resource.liveContainerTestLanguage.LiveContainerTestLanguagePackage; +import org.eclipse.xtext.resource.liveContainerTestLanguage.Model; +import org.eclipse.xtext.testing.InjectWith; +import org.eclipse.xtext.testing.XtextRunner; +import org.eclipse.xtext.testing.util.ParseHelper; +import org.eclipse.xtext.workspace.ProjectConfigAdapter; +import org.eclipse.xtext.workspace.WorkspaceConfig; +import org.eclipse.xtext.xbase.lib.CollectionLiterals; +import org.eclipse.xtext.xbase.lib.Conversions; +import org.eclipse.xtext.xbase.lib.Exceptions; +import org.eclipse.xtext.xbase.lib.Extension; +import org.eclipse.xtext.xbase.lib.Functions.Function1; +import org.eclipse.xtext.xbase.lib.IterableExtensions; +import org.eclipse.xtext.xbase.lib.ListExtensions; +import org.eclipse.xtext.xbase.lib.Pair; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * @author koehnlein - Initial contribution and API + */ +@RunWith(XtextRunner.class) +@InjectWith(LiveContainerTestLanguageInjectorProvider.class) +@SuppressWarnings("all") +public class LiveShadowedChunkedContainerTest { + @Inject + @Extension + private ParseHelper _parseHelper; + + @Inject + private Provider resourceSetProvider; + + @Inject + private IResourceDescription.Manager resourceDescriptionManager; + + @Inject + private Provider provider; + + private ProjectConfig fooProject; + + private ProjectConfig barProject; + + private URI fooURI; + + private URI barURI; + + private XtextResourceSet rs1; + + private LiveShadowedChunkedContainer fooContainer; + + private LiveShadowedChunkedContainer barContainer; + + @Before + public void setUp() { + try { + final WorkspaceConfig workspaceConfig = new WorkspaceConfig(); + ProjectConfig _projectConfig = new ProjectConfig("foo", workspaceConfig); + this.fooProject = _projectConfig; + ProjectConfig _projectConfig_1 = new ProjectConfig("bar", workspaceConfig); + this.barProject = _projectConfig_1; + final XtextResourceSet rs0 = this.resourceSetProvider.get(); + this.fooURI = IterableExtensions.head(this.fooProject.getSourceFolders()).getPath().trimSegments(1).appendSegment("foo.livecontainertestlanguage"); + this.barURI = IterableExtensions.head(this.barProject.getSourceFolders()).getPath().trimSegments(1).appendSegment("bar.livecontainertestlanguage"); + ResourceDescriptionsData _createResourceDescriptionData = this.createResourceDescriptionData(this._parseHelper.parse("foo", this.fooURI, rs0).eResource()); + Pair _mappedTo = Pair.of("foo", _createResourceDescriptionData); + ResourceDescriptionsData _createResourceDescriptionData_1 = this.createResourceDescriptionData(this._parseHelper.parse("bar", this.barURI, rs0).eResource()); + Pair _mappedTo_1 = Pair.of("bar", _createResourceDescriptionData_1); + final Map chunks = Collections.unmodifiableMap(CollectionLiterals.newHashMap(_mappedTo, _mappedTo_1)); + this.rs1 = this.resourceSetProvider.get(); + new ChunkedResourceDescriptions(chunks, this.rs1); + ProjectConfigAdapter.install(this.rs1, this.fooProject); + final LiveShadowedChunkedResourceDescriptions liveShadowedChunkedResourceDescriptions = this.provider.get(); + liveShadowedChunkedResourceDescriptions.setContext(this.rs1); + LiveShadowedChunkedContainer _liveShadowedChunkedContainer = new LiveShadowedChunkedContainer(liveShadowedChunkedResourceDescriptions, "foo"); + this.fooContainer = _liveShadowedChunkedContainer; + LiveShadowedChunkedContainer _liveShadowedChunkedContainer_1 = new LiveShadowedChunkedContainer(liveShadowedChunkedResourceDescriptions, "bar"); + this.barContainer = _liveShadowedChunkedContainer_1; + } catch (Throwable _e) { + throw Exceptions.sneakyThrow(_e); + } + } + + @Test + public void testRenameElement() { + try { + this._parseHelper.parse("fooChange", this.fooURI, this.rs1); + final Function1 _function = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("fooChange", IterableExtensions.join(IterableExtensions.map(this.fooContainer.getExportedObjects(), _function), ",")); + final Function1 _function_1 = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("fooChange", IterableExtensions.join(IterableExtensions.map(this.fooContainer.getExportedObjects(LiveContainerTestLanguagePackage.Literals.MODEL, QualifiedName.create("fooChange"), false), _function_1), ",")); + final Function1 _function_2 = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("fooChange", IterableExtensions.join(IterableExtensions.map(this.fooContainer.getExportedObjectsByType(LiveContainerTestLanguagePackage.Literals.MODEL), _function_2), ",")); + Assert.assertEquals(1, IterableExtensions.size(this.fooContainer.getResourceDescriptions())); + Assert.assertEquals(1, this.fooContainer.getResourceDescriptionCount()); + Assert.assertTrue(this.fooContainer.hasResourceDescription(this.fooURI)); + Assert.assertFalse(this.fooContainer.hasResourceDescription(this.barURI)); + Assert.assertEquals(this.fooURI, this.fooContainer.getResourceDescription(this.fooURI).getURI()); + final Function1 _function_3 = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("bar", IterableExtensions.join(IterableExtensions.map(this.barContainer.getExportedObjects(), _function_3), ",")); + final Function1 _function_4 = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("bar", IterableExtensions.join(IterableExtensions.map(this.barContainer.getExportedObjects(LiveContainerTestLanguagePackage.Literals.MODEL, QualifiedName.create("bar"), false), _function_4), ",")); + final Function1 _function_5 = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("bar", IterableExtensions.join(IterableExtensions.map(this.barContainer.getExportedObjectsByType(LiveContainerTestLanguagePackage.Literals.MODEL), _function_5), ",")); + Assert.assertEquals(1, IterableExtensions.size(this.barContainer.getResourceDescriptions())); + Assert.assertEquals(1, this.barContainer.getResourceDescriptionCount()); + Assert.assertTrue(this.barContainer.hasResourceDescription(this.barURI)); + Assert.assertFalse(this.barContainer.hasResourceDescription(this.fooURI)); + Assert.assertEquals(this.barURI, this.barContainer.getResourceDescription(this.barURI).getURI()); + } catch (Throwable _e) { + throw Exceptions.sneakyThrow(_e); + } + } + + @Test + public void testAddResource() { + try { + this._parseHelper.parse("baz", IterableExtensions.head(this.fooProject.getSourceFolders()).getPath().trimSegments(1).appendSegment("baz.livecontainertestlanguage"), this.rs1); + Assert.assertEquals(2, IterableExtensions.size(this.fooContainer.getResourceDescriptions())); + Assert.assertEquals(2, this.fooContainer.getResourceDescriptionCount()); + final Function1 _function = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("baz,foo", IterableExtensions.join(IterableExtensions.sort(IterableExtensions.map(this.fooContainer.getExportedObjects(), _function)), ",")); + Assert.assertEquals(1, IterableExtensions.size(this.barContainer.getResourceDescriptions())); + Assert.assertEquals(1, this.barContainer.getResourceDescriptionCount()); + } catch (Throwable _e) { + throw Exceptions.sneakyThrow(_e); + } + } + + @Test + public void testDeleteElement() { + try { + this._parseHelper.parse("foo", this.fooURI, this.rs1).eResource().getContents().clear(); + final Function1 _function = (IEObjectDescription it) -> { + return it.getQualifiedName().toString(); + }; + Assert.assertEquals("", IterableExtensions.join(IterableExtensions.map(this.fooContainer.getExportedObjects(), _function), ",")); + Assert.assertEquals(1, IterableExtensions.size(this.fooContainer.getResourceDescriptions())); + Assert.assertEquals(1, this.fooContainer.getResourceDescriptionCount()); + Assert.assertEquals(0, IterableExtensions.size(this.fooContainer.getExportedObjects())); + Assert.assertEquals(1, IterableExtensions.size(this.barContainer.getResourceDescriptions())); + Assert.assertEquals(1, this.barContainer.getResourceDescriptionCount()); + } catch (Throwable _e) { + throw Exceptions.sneakyThrow(_e); + } + } + + private ResourceDescriptionsData createResourceDescriptionData(final Resource... resources) { + final Function1 _function = (Resource it) -> { + return this.resourceDescriptionManager.getResourceDescription(it); + }; + List _map = ListExtensions.map(((List)Conversions.doWrapArray(resources)), _function); + return new ResourceDescriptionsData(_map); + } +} diff --git a/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/ProjectConfig.java b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/ProjectConfig.java new file mode 100644 index 000000000..61c6de075 --- /dev/null +++ b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/ProjectConfig.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2017 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.resource.containers; + +import java.io.File; +import java.util.Set; +import org.eclipse.emf.common.util.URI; +import org.eclipse.xtend.lib.annotations.AccessorType; +import org.eclipse.xtend.lib.annotations.Accessors; +import org.eclipse.xtext.resource.containers.SourceFolder; +import org.eclipse.xtext.util.UriUtil; +import org.eclipse.xtext.workspace.IProjectConfig; +import org.eclipse.xtext.workspace.ISourceFolder; +import org.eclipse.xtext.workspace.IWorkspaceConfig; +import org.eclipse.xtext.workspace.WorkspaceConfig; +import org.eclipse.xtext.xbase.lib.CollectionLiterals; +import org.eclipse.xtext.xbase.lib.Functions.Function1; +import org.eclipse.xtext.xbase.lib.IterableExtensions; +import org.eclipse.xtext.xbase.lib.Pure; + +@Accessors(AccessorType.PUBLIC_GETTER) +@SuppressWarnings("all") +public class ProjectConfig implements IProjectConfig { + private URI path; + + private Set sourceFolders = CollectionLiterals.newHashSet(); + + private String name; + + private IWorkspaceConfig workspaceConfig; + + public ProjectConfig(final String name, final WorkspaceConfig workspaceConfig) { + this.name = name; + this.path = URI.createURI(new File(name).getAbsoluteFile().toURI().toString()).appendSegment(""); + URI _appendSegment = this.path.trimSegments(1).appendSegment("src").appendSegment(""); + SourceFolder _sourceFolder = new SourceFolder(_appendSegment); + this.sourceFolders.add(_sourceFolder); + this.workspaceConfig = workspaceConfig; + workspaceConfig.addProject(this); + } + + @Override + public ISourceFolder findSourceFolderContaining(final URI member) { + final Function1 _function = (SourceFolder it) -> { + return Boolean.valueOf(UriUtil.isPrefixOf(this.path, member)); + }; + return IterableExtensions.findFirst(this.sourceFolders, _function); + } + + @Pure + public URI getPath() { + return this.path; + } + + @Pure + public Set getSourceFolders() { + return this.sourceFolders; + } + + @Pure + public String getName() { + return this.name; + } + + @Pure + public IWorkspaceConfig getWorkspaceConfig() { + return this.workspaceConfig; + } +} diff --git a/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/SourceFolder.java b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/SourceFolder.java new file mode 100644 index 000000000..c3fe48893 --- /dev/null +++ b/org.eclipse.xtext.tests/xtend-gen/org/eclipse/xtext/resource/containers/SourceFolder.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2017 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.resource.containers; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.xtend.lib.annotations.AccessorType; +import org.eclipse.xtend.lib.annotations.Accessors; +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor; +import org.eclipse.xtext.workspace.ISourceFolder; +import org.eclipse.xtext.xbase.lib.Pure; + +@FinalFieldsConstructor +@Accessors(AccessorType.PUBLIC_GETTER) +@SuppressWarnings("all") +public class SourceFolder implements ISourceFolder { + private final URI path; + + @Override + public String getName() { + return "src"; + } + + public SourceFolder(final URI path) { + super(); + this.path = path; + } + + @Pure + public URI getPath() { + return this.path; + } +} diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.xtend b/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.xtend new file mode 100644 index 000000000..307f4fa8b --- /dev/null +++ b/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.xtend @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) 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.resource.containers + +import com.google.common.annotations.Beta +import java.util.Set +import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.EClass +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor +import org.eclipse.xtext.naming.QualifiedName +import org.eclipse.xtext.resource.IContainer +import org.eclipse.xtext.resource.impl.ChunkedResourceDescriptions +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions +import org.eclipse.xtext.workspace.IProjectConfig + +/** + * @author koehnlein - Initial contribution and API + * @since 2.14 + */ +@Beta +@FinalFieldsConstructor +class LiveShadowedChunkedContainer implements IContainer { + + val LiveShadowedChunkedResourceDescriptions descriptions + + val String containerName + + IProjectConfig projectConfig + + boolean isProjectConfigSet = false + + + protected def getChunkedResourceDescriptions() { + descriptions.globalDescriptions as ChunkedResourceDescriptions + } + + protected def getProjectConfig() { + if (!isProjectConfigSet) { + projectConfig = descriptions.workspaceConfig?.findProjectByName(containerName) + isProjectConfigSet = true + } + return projectConfig + } + + protected def getChunk() { + chunkedResourceDescriptions.getContainer(containerName) + } + + protected def getContainedLocalDescriptions() { + descriptions.localDescriptions.allResourceDescriptions.filter[URI.contained] + } + + protected def boolean isContained(URI uri) { + chunk.getResourceDescription(uri) !== null || getProjectConfig?.findSourceFolderContaining(uri) !== null + } + + override getResourceDescription(URI uri) { + if(uri.contained) + descriptions.getResourceDescription(uri) + else + null + } + + override getResourceDescriptionCount() { + resourceDescriptions.size + } + + override getResourceDescriptions() { + val localURIs = existingOrRenamedResourceURIs + return containedLocalDescriptions + + chunk.allResourceDescriptions.filter[!localURIs.contains(URI)] + } + + override hasResourceDescription(URI uri) { + chunk.getResourceDescription(uri) !== null + } + + override getExportedObjects() { + val localURIs = existingOrRenamedResourceURIs + val flatten = containedLocalDescriptions.map[exportedObjects].flatten + return flatten + + chunk.exportedObjects.filter[!localURIs.contains(EObjectURI.trimFragment)] + } + + override getExportedObjects(EClass type, QualifiedName name, boolean ignoreCase) { + val localURIs = existingOrRenamedResourceURIs + return containedLocalDescriptions.map[getExportedObjects(type, name, ignoreCase)].flatten + + chunk.getExportedObjects(type, name, ignoreCase).filter[!localURIs.contains(EObjectURI.trimFragment)] + } + + override getExportedObjectsByObject(EObject object) { + val localURIs = existingOrRenamedResourceURIs + return containedLocalDescriptions.map[getExportedObjectsByObject(object)].flatten + + chunk.getExportedObjectsByObject(object).filter[!localURIs.contains(EObjectURI.trimFragment)] + } + + override getExportedObjectsByType(EClass type) { + val localURIs = existingOrRenamedResourceURIs + return containedLocalDescriptions.map[getExportedObjectsByType(type)].flatten + + chunk.getExportedObjectsByType(type).filter[!localURIs.contains(EObjectURI.trimFragment)] + } + + override isEmpty() { + containedLocalDescriptions.empty && chunk.empty + } + + def protected Set getExistingOrRenamedResourceURIs() { + val resourceSet = descriptions.resourceSet + if (resourceSet instanceof ResourceSetImpl) + return resourceSet.URIResourceMap.keySet + throw new IllegalStateException("ResourceSet is not a ResourceSetImpl") + } +} \ No newline at end of file diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.xtend b/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.xtend index 8d7ba8b14..141f994c4 100644 --- a/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.xtend +++ b/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.xtend @@ -12,6 +12,7 @@ import org.eclipse.xtext.resource.IContainer import org.eclipse.xtext.resource.IResourceDescription import org.eclipse.xtext.resource.IResourceDescriptions import org.eclipse.xtext.resource.impl.ChunkedResourceDescriptions +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions import org.eclipse.xtext.resource.impl.ProjectDescription import org.eclipse.xtext.resource.impl.ResourceDescriptionsBasedContainer import org.eclipse.xtext.resource.impl.ResourceDescriptionsData @@ -25,38 +26,50 @@ import org.eclipse.xtext.resource.impl.ResourceDescriptionsData class ProjectDescriptionBasedContainerManager implements IContainer.Manager { public def boolean shouldUseProjectDescriptionBasedContainers(IResourceDescriptions resourceDescriptions) { - if (resourceDescriptions instanceof ChunkedResourceDescriptions) { - if (ProjectDescription.findInEmfObject(resourceDescriptions.resourceSet) !== null) { - return true - } - } - return false + val chunkedResourceDescriptions = resourceDescriptions.chunkedResourceDescriptions + return chunkedResourceDescriptions !== null + && chunkedResourceDescriptions.resourceSet !== null + && ProjectDescription.findInEmfObject(chunkedResourceDescriptions.resourceSet) !== null } override getContainer(IResourceDescription desc, IResourceDescriptions resourceDescriptions) { - if (resourceDescriptions instanceof ChunkedResourceDescriptions) { - val resourceSet = resourceDescriptions.resourceSet - val projectDescription = ProjectDescription.findInEmfObject(resourceSet) - val container = resourceDescriptions.getContainer(projectDescription.name) - return new ResourceDescriptionsBasedContainer(container) - } - throw new IllegalArgumentException("expected "+ChunkedResourceDescriptions.name) + val chunkedResourceDescriptions = resourceDescriptions.chunkedResourceDescriptions + if (chunkedResourceDescriptions === null) + throw new IllegalArgumentException("expected "+ChunkedResourceDescriptions.name) + + val resourceSet = chunkedResourceDescriptions.resourceSet + val projectDescription = ProjectDescription.findInEmfObject(resourceSet) + val container = createContainer(resourceDescriptions, chunkedResourceDescriptions, projectDescription.name) + return container } override getVisibleContainers(IResourceDescription desc, IResourceDescriptions resourceDescriptions) { - if (resourceDescriptions instanceof ChunkedResourceDescriptions) { - val resourceSet = resourceDescriptions.resourceSet - val projectDescription = ProjectDescription.findInEmfObject(resourceSet) - val allContainers = newArrayList - val container = resourceDescriptions.getContainer(projectDescription.name) ?: new ResourceDescriptionsData(emptySet) - allContainers.add(new ResourceDescriptionsBasedContainer(container)) - for (name : projectDescription.dependencies) { - val containerDep = resourceDescriptions.getContainer(name) ?: new ResourceDescriptionsData(emptySet) - allContainers.add(new ResourceDescriptionsBasedContainer(containerDep)) - } - return allContainers + val chunkedResourceDescriptions = resourceDescriptions.chunkedResourceDescriptions + if (chunkedResourceDescriptions === null) + throw new IllegalArgumentException("expected "+ChunkedResourceDescriptions.name) + val resourceSet = chunkedResourceDescriptions.resourceSet + val projectDescription = ProjectDescription.findInEmfObject(resourceSet) + val allContainers = newArrayList + allContainers.add(createContainer(resourceDescriptions, chunkedResourceDescriptions, projectDescription.name)) + for (name : projectDescription.dependencies) { + allContainers.add(createContainer(resourceDescriptions, chunkedResourceDescriptions, name)) } - throw new IllegalArgumentException("expected "+ChunkedResourceDescriptions.name) + return allContainers + } + protected def ChunkedResourceDescriptions getChunkedResourceDescriptions(IResourceDescriptions resourceDescriptions) { + switch resourceDescriptions { + ChunkedResourceDescriptions: resourceDescriptions + LiveShadowedChunkedResourceDescriptions: resourceDescriptions.globalDescriptions.chunkedResourceDescriptions + default: null + } + } + + protected def createContainer(IResourceDescriptions resourceDescriptions, ChunkedResourceDescriptions chunkedResourceDescriptions, String projectName) { + if(resourceDescriptions instanceof LiveShadowedChunkedResourceDescriptions) + new LiveShadowedChunkedContainer(resourceDescriptions, projectName) + else + new ResourceDescriptionsBasedContainer(chunkedResourceDescriptions.getContainer(projectName) ?: new ResourceDescriptionsData(emptySet)) + } } diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.xtend b/org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.xtend new file mode 100644 index 000000000..503017cc7 --- /dev/null +++ b/org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.xtend @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2011 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.resource.impl + +import com.google.inject.Inject +import org.eclipse.emf.common.notify.Notifier +import org.eclipse.xtend.lib.annotations.Accessors +import org.eclipse.xtext.workspace.IProjectConfigProvider +import org.eclipse.xtext.workspace.IWorkspaceConfig + +import static extension org.eclipse.xtext.EcoreUtil2.* + +/** + * @author Jan Koehnlein - Initial contribution and API + * @since 2.14 + */ +class LiveShadowedChunkedResourceDescriptions extends LiveShadowedResourceDescriptions { + + @Inject(optional = true) IProjectConfigProvider projectConfigProvider + + @Accessors(PUBLIC_GETTER) IWorkspaceConfig workspaceConfig + + override void setContext(Notifier ctx) { + (localDescriptions as ResourceSetBasedResourceDescriptions) => [ + context = ctx + data = null + ] + val resourceSet = ctx.resourceSet + globalDescriptions = ChunkedResourceDescriptions.findInEmfObject(resourceSet) + workspaceConfig = projectConfigProvider?.getProjectConfig(resourceSet)?.workspaceConfig + } +} diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedResourceDescriptions.java b/org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedResourceDescriptions.java index 93ec9a6a9..9f166118e 100644 --- a/org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedResourceDescriptions.java +++ b/org.eclipse.xtext/src/org/eclipse/xtext/resource/impl/LiveShadowedResourceDescriptions.java @@ -22,12 +22,14 @@ import org.eclipse.xtext.resource.IEObjectDescription; import org.eclipse.xtext.resource.IResourceDescription; import org.eclipse.xtext.resource.IResourceDescriptions; import org.eclipse.xtext.resource.ISelectable; +import org.eclipse.xtext.resource.IShadowedResourceDescriptions; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.inject.Inject; +import com.google.inject.Provider; /** * @author Jan Koehnlein - Initial contribution and API @@ -40,18 +42,21 @@ import com.google.inject.Inject; * * @since 2.1 */ -public class LiveShadowedResourceDescriptions extends ResourceSetBasedResourceDescriptions { +public class LiveShadowedResourceDescriptions extends ResourceSetBasedResourceDescriptions implements IShadowedResourceDescriptions { @Inject private ResourceSetBasedResourceDescriptions localDescriptions; @Inject - private IResourceDescriptions globalDescriptions; + private Provider globalDescriptionsProvider; + private IResourceDescriptions globalDescriptions; + @Override public void setContext(Notifier ctx) { localDescriptions.setContext(ctx); localDescriptions.setData(null); + globalDescriptions = globalDescriptionsProvider.get(); if(globalDescriptions instanceof IResourceDescriptions.IContextAware) ((IResourceDescriptions.IContextAware) globalDescriptions).setContext(ctx); } @@ -185,4 +190,10 @@ public class LiveShadowedResourceDescriptions extends ResourceSetBasedResourceDe this.localDescriptions = localDescriptions; } + @Override + public boolean isShadowed(EClass type, QualifiedName name, boolean ignoreCase) { + return !Iterables.isEmpty(localDescriptions.getExportedObjects(type, name, ignoreCase)) + && !Iterables.isEmpty(globalDescriptions.getExportedObjects(type, name, ignoreCase)); + } + } diff --git a/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.java b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.java new file mode 100644 index 000000000..566720c70 --- /dev/null +++ b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/LiveShadowedChunkedContainer.java @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) 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.resource.containers; + +import com.google.common.annotations.Beta; +import com.google.common.collect.Iterables; +import java.util.Set; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor; +import org.eclipse.xtext.naming.QualifiedName; +import org.eclipse.xtext.resource.IContainer; +import org.eclipse.xtext.resource.IEObjectDescription; +import org.eclipse.xtext.resource.IResourceDescription; +import org.eclipse.xtext.resource.IResourceDescriptions; +import org.eclipse.xtext.resource.impl.ChunkedResourceDescriptions; +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions; +import org.eclipse.xtext.resource.impl.ResourceDescriptionsData; +import org.eclipse.xtext.workspace.IProjectConfig; +import org.eclipse.xtext.workspace.ISourceFolder; +import org.eclipse.xtext.workspace.IWorkspaceConfig; +import org.eclipse.xtext.xbase.lib.Functions.Function1; +import org.eclipse.xtext.xbase.lib.IterableExtensions; + +/** + * @author koehnlein - Initial contribution and API + * @since 2.14 + */ +@Beta +@FinalFieldsConstructor +@SuppressWarnings("all") +public class LiveShadowedChunkedContainer implements IContainer { + private final LiveShadowedChunkedResourceDescriptions descriptions; + + private final String containerName; + + private IProjectConfig projectConfig; + + private boolean isProjectConfigSet = false; + + protected ChunkedResourceDescriptions getChunkedResourceDescriptions() { + IResourceDescriptions _globalDescriptions = this.descriptions.getGlobalDescriptions(); + return ((ChunkedResourceDescriptions) _globalDescriptions); + } + + protected IProjectConfig getProjectConfig() { + if ((!this.isProjectConfigSet)) { + IWorkspaceConfig _workspaceConfig = this.descriptions.getWorkspaceConfig(); + IProjectConfig _findProjectByName = null; + if (_workspaceConfig!=null) { + _findProjectByName=_workspaceConfig.findProjectByName(this.containerName); + } + this.projectConfig = _findProjectByName; + this.isProjectConfigSet = true; + } + return this.projectConfig; + } + + protected ResourceDescriptionsData getChunk() { + return this.getChunkedResourceDescriptions().getContainer(this.containerName); + } + + protected Iterable getContainedLocalDescriptions() { + final Function1 _function = (IResourceDescription it) -> { + return Boolean.valueOf(this.isContained(it.getURI())); + }; + return IterableExtensions.filter(this.descriptions.getLocalDescriptions().getAllResourceDescriptions(), _function); + } + + protected boolean isContained(final URI uri) { + boolean _or = false; + IResourceDescription _resourceDescription = this.getChunk().getResourceDescription(uri); + boolean _tripleNotEquals = (_resourceDescription != null); + if (_tripleNotEquals) { + _or = true; + } else { + IProjectConfig _projectConfig = this.getProjectConfig(); + ISourceFolder _findSourceFolderContaining = null; + if (_projectConfig!=null) { + _findSourceFolderContaining=_projectConfig.findSourceFolderContaining(uri); + } + boolean _tripleNotEquals_1 = (_findSourceFolderContaining != null); + _or = _tripleNotEquals_1; + } + return _or; + } + + @Override + public IResourceDescription getResourceDescription(final URI uri) { + IResourceDescription _xifexpression = null; + boolean _isContained = this.isContained(uri); + if (_isContained) { + _xifexpression = this.descriptions.getResourceDescription(uri); + } else { + _xifexpression = null; + } + return _xifexpression; + } + + @Override + public int getResourceDescriptionCount() { + return IterableExtensions.size(this.getResourceDescriptions()); + } + + @Override + public Iterable getResourceDescriptions() { + final Set localURIs = this.getExistingOrRenamedResourceURIs(); + Iterable _containedLocalDescriptions = this.getContainedLocalDescriptions(); + final Function1 _function = (IResourceDescription it) -> { + boolean _contains = localURIs.contains(it.getURI()); + return Boolean.valueOf((!_contains)); + }; + Iterable _filter = IterableExtensions.filter(this.getChunk().getAllResourceDescriptions(), _function); + return Iterables.concat(_containedLocalDescriptions, _filter); + } + + @Override + public boolean hasResourceDescription(final URI uri) { + IResourceDescription _resourceDescription = this.getChunk().getResourceDescription(uri); + return (_resourceDescription != null); + } + + @Override + public Iterable getExportedObjects() { + final Set localURIs = this.getExistingOrRenamedResourceURIs(); + final Function1> _function = (IResourceDescription it) -> { + return it.getExportedObjects(); + }; + final Iterable flatten = Iterables.concat(IterableExtensions.>map(this.getContainedLocalDescriptions(), _function)); + final Function1 _function_1 = (IEObjectDescription it) -> { + boolean _contains = localURIs.contains(it.getEObjectURI().trimFragment()); + return Boolean.valueOf((!_contains)); + }; + Iterable _filter = IterableExtensions.filter(this.getChunk().getExportedObjects(), _function_1); + return Iterables.concat(flatten, _filter); + } + + @Override + public Iterable getExportedObjects(final EClass type, final QualifiedName name, final boolean ignoreCase) { + final Set localURIs = this.getExistingOrRenamedResourceURIs(); + final Function1> _function = (IResourceDescription it) -> { + return it.getExportedObjects(type, name, ignoreCase); + }; + Iterable _flatten = Iterables.concat(IterableExtensions.>map(this.getContainedLocalDescriptions(), _function)); + final Function1 _function_1 = (IEObjectDescription it) -> { + boolean _contains = localURIs.contains(it.getEObjectURI().trimFragment()); + return Boolean.valueOf((!_contains)); + }; + Iterable _filter = IterableExtensions.filter(this.getChunk().getExportedObjects(type, name, ignoreCase), _function_1); + return Iterables.concat(_flatten, _filter); + } + + @Override + public Iterable getExportedObjectsByObject(final EObject object) { + final Set localURIs = this.getExistingOrRenamedResourceURIs(); + final Function1> _function = (IResourceDescription it) -> { + return it.getExportedObjectsByObject(object); + }; + Iterable _flatten = Iterables.concat(IterableExtensions.>map(this.getContainedLocalDescriptions(), _function)); + final Function1 _function_1 = (IEObjectDescription it) -> { + boolean _contains = localURIs.contains(it.getEObjectURI().trimFragment()); + return Boolean.valueOf((!_contains)); + }; + Iterable _filter = IterableExtensions.filter(this.getChunk().getExportedObjectsByObject(object), _function_1); + return Iterables.concat(_flatten, _filter); + } + + @Override + public Iterable getExportedObjectsByType(final EClass type) { + final Set localURIs = this.getExistingOrRenamedResourceURIs(); + final Function1> _function = (IResourceDescription it) -> { + return it.getExportedObjectsByType(type); + }; + Iterable _flatten = Iterables.concat(IterableExtensions.>map(this.getContainedLocalDescriptions(), _function)); + final Function1 _function_1 = (IEObjectDescription it) -> { + boolean _contains = localURIs.contains(it.getEObjectURI().trimFragment()); + return Boolean.valueOf((!_contains)); + }; + Iterable _filter = IterableExtensions.filter(this.getChunk().getExportedObjectsByType(type), _function_1); + return Iterables.concat(_flatten, _filter); + } + + @Override + public boolean isEmpty() { + return (IterableExtensions.isEmpty(this.getContainedLocalDescriptions()) && this.getChunk().isEmpty()); + } + + protected Set getExistingOrRenamedResourceURIs() { + final ResourceSet resourceSet = this.descriptions.getResourceSet(); + if ((resourceSet instanceof ResourceSetImpl)) { + return ((ResourceSetImpl)resourceSet).getURIResourceMap().keySet(); + } + throw new IllegalStateException("ResourceSet is not a ResourceSetImpl"); + } + + public LiveShadowedChunkedContainer(final LiveShadowedChunkedResourceDescriptions descriptions, final String containerName) { + super(); + this.descriptions = descriptions; + this.containerName = containerName; + } +} diff --git a/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.java b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.java index 01c09ba58..e17f6b21d 100644 --- a/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.java +++ b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/containers/ProjectDescriptionBasedContainerManager.java @@ -15,7 +15,9 @@ import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.xtext.resource.IContainer; import org.eclipse.xtext.resource.IResourceDescription; import org.eclipse.xtext.resource.IResourceDescriptions; +import org.eclipse.xtext.resource.containers.LiveShadowedChunkedContainer; import org.eclipse.xtext.resource.impl.ChunkedResourceDescriptions; +import org.eclipse.xtext.resource.impl.LiveShadowedChunkedResourceDescriptions; import org.eclipse.xtext.resource.impl.ProjectDescription; import org.eclipse.xtext.resource.impl.ResourceDescriptionsBasedContainer; import org.eclipse.xtext.resource.impl.ResourceDescriptionsData; @@ -30,37 +32,69 @@ import org.eclipse.xtext.xbase.lib.CollectionLiterals; @SuppressWarnings("all") public class ProjectDescriptionBasedContainerManager implements IContainer.Manager { public boolean shouldUseProjectDescriptionBasedContainers(final IResourceDescriptions resourceDescriptions) { - if ((resourceDescriptions instanceof ChunkedResourceDescriptions)) { - ProjectDescription _findInEmfObject = ProjectDescription.findInEmfObject(((ChunkedResourceDescriptions)resourceDescriptions).getResourceSet()); - boolean _tripleNotEquals = (_findInEmfObject != null); - if (_tripleNotEquals) { - return true; - } - } - return false; + final ChunkedResourceDescriptions chunkedResourceDescriptions = this.getChunkedResourceDescriptions(resourceDescriptions); + return (((chunkedResourceDescriptions != null) && (chunkedResourceDescriptions.getResourceSet() != null)) && (ProjectDescription.findInEmfObject(chunkedResourceDescriptions.getResourceSet()) != null)); } @Override public IContainer getContainer(final IResourceDescription desc, final IResourceDescriptions resourceDescriptions) { - if ((resourceDescriptions instanceof ChunkedResourceDescriptions)) { - final ResourceSet resourceSet = ((ChunkedResourceDescriptions)resourceDescriptions).getResourceSet(); - final ProjectDescription projectDescription = ProjectDescription.findInEmfObject(resourceSet); - final ResourceDescriptionsData container = ((ChunkedResourceDescriptions)resourceDescriptions).getContainer(projectDescription.getName()); - return new ResourceDescriptionsBasedContainer(container); + final ChunkedResourceDescriptions chunkedResourceDescriptions = this.getChunkedResourceDescriptions(resourceDescriptions); + if ((chunkedResourceDescriptions == null)) { + String _name = ChunkedResourceDescriptions.class.getName(); + String _plus = ("expected " + _name); + throw new IllegalArgumentException(_plus); } - String _name = ChunkedResourceDescriptions.class.getName(); - String _plus = ("expected " + _name); - throw new IllegalArgumentException(_plus); + final ResourceSet resourceSet = chunkedResourceDescriptions.getResourceSet(); + final ProjectDescription projectDescription = ProjectDescription.findInEmfObject(resourceSet); + final IContainer container = this.createContainer(resourceDescriptions, chunkedResourceDescriptions, projectDescription.getName()); + return container; } @Override public List getVisibleContainers(final IResourceDescription desc, final IResourceDescriptions resourceDescriptions) { - if ((resourceDescriptions instanceof ChunkedResourceDescriptions)) { - final ResourceSet resourceSet = ((ChunkedResourceDescriptions)resourceDescriptions).getResourceSet(); - final ProjectDescription projectDescription = ProjectDescription.findInEmfObject(resourceSet); - final ArrayList allContainers = CollectionLiterals.newArrayList(); + final ChunkedResourceDescriptions chunkedResourceDescriptions = this.getChunkedResourceDescriptions(resourceDescriptions); + if ((chunkedResourceDescriptions == null)) { + String _name = ChunkedResourceDescriptions.class.getName(); + String _plus = ("expected " + _name); + throw new IllegalArgumentException(_plus); + } + final ResourceSet resourceSet = chunkedResourceDescriptions.getResourceSet(); + final ProjectDescription projectDescription = ProjectDescription.findInEmfObject(resourceSet); + final ArrayList allContainers = CollectionLiterals.newArrayList(); + allContainers.add(this.createContainer(resourceDescriptions, chunkedResourceDescriptions, projectDescription.getName())); + List _dependencies = projectDescription.getDependencies(); + for (final String name : _dependencies) { + allContainers.add(this.createContainer(resourceDescriptions, chunkedResourceDescriptions, name)); + } + return allContainers; + } + + protected ChunkedResourceDescriptions getChunkedResourceDescriptions(final IResourceDescriptions resourceDescriptions) { + ChunkedResourceDescriptions _switchResult = null; + boolean _matched = false; + if (resourceDescriptions instanceof ChunkedResourceDescriptions) { + _matched=true; + _switchResult = ((ChunkedResourceDescriptions)resourceDescriptions); + } + if (!_matched) { + if (resourceDescriptions instanceof LiveShadowedChunkedResourceDescriptions) { + _matched=true; + _switchResult = this.getChunkedResourceDescriptions(((LiveShadowedChunkedResourceDescriptions)resourceDescriptions).getGlobalDescriptions()); + } + } + if (!_matched) { + _switchResult = null; + } + return _switchResult; + } + + protected IContainer createContainer(final IResourceDescriptions resourceDescriptions, final ChunkedResourceDescriptions chunkedResourceDescriptions, final String projectName) { + IContainer _xifexpression = null; + if ((resourceDescriptions instanceof LiveShadowedChunkedResourceDescriptions)) { + _xifexpression = new LiveShadowedChunkedContainer(((LiveShadowedChunkedResourceDescriptions)resourceDescriptions), projectName); + } else { ResourceDescriptionsData _elvis = null; - ResourceDescriptionsData _container = ((ChunkedResourceDescriptions)resourceDescriptions).getContainer(projectDescription.getName()); + ResourceDescriptionsData _container = chunkedResourceDescriptions.getContainer(projectName); if (_container != null) { _elvis = _container; } else { @@ -68,30 +102,8 @@ public class ProjectDescriptionBasedContainerManager implements IContainer.Manag ResourceDescriptionsData _resourceDescriptionsData = new ResourceDescriptionsData(_emptySet); _elvis = _resourceDescriptionsData; } - final ResourceDescriptionsData container = _elvis; - ResourceDescriptionsBasedContainer _resourceDescriptionsBasedContainer = new ResourceDescriptionsBasedContainer(container); - allContainers.add(_resourceDescriptionsBasedContainer); - List _dependencies = projectDescription.getDependencies(); - for (final String name : _dependencies) { - { - ResourceDescriptionsData _elvis_1 = null; - ResourceDescriptionsData _container_1 = ((ChunkedResourceDescriptions)resourceDescriptions).getContainer(name); - if (_container_1 != null) { - _elvis_1 = _container_1; - } else { - Set _emptySet_1 = CollectionLiterals.emptySet(); - ResourceDescriptionsData _resourceDescriptionsData_1 = new ResourceDescriptionsData(_emptySet_1); - _elvis_1 = _resourceDescriptionsData_1; - } - final ResourceDescriptionsData containerDep = _elvis_1; - ResourceDescriptionsBasedContainer _resourceDescriptionsBasedContainer_1 = new ResourceDescriptionsBasedContainer(containerDep); - allContainers.add(_resourceDescriptionsBasedContainer_1); - } - } - return allContainers; + _xifexpression = new ResourceDescriptionsBasedContainer(_elvis); } - String _name = ChunkedResourceDescriptions.class.getName(); - String _plus = ("expected " + _name); - throw new IllegalArgumentException(_plus); + return _xifexpression; } } diff --git a/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.java b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.java new file mode 100644 index 000000000..aba33f3ea --- /dev/null +++ b/org.eclipse.xtext/xtend-gen/org/eclipse/xtext/resource/impl/LiveShadowedChunkedResourceDescriptions.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2011 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.resource.impl; + +import com.google.inject.Inject; +import org.eclipse.emf.common.notify.Notifier; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.xtend.lib.annotations.AccessorType; +import org.eclipse.xtend.lib.annotations.Accessors; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.resource.IResourceDescriptions; +import org.eclipse.xtext.resource.impl.ChunkedResourceDescriptions; +import org.eclipse.xtext.resource.impl.LiveShadowedResourceDescriptions; +import org.eclipse.xtext.resource.impl.ResourceSetBasedResourceDescriptions; +import org.eclipse.xtext.workspace.IProjectConfig; +import org.eclipse.xtext.workspace.IProjectConfigProvider; +import org.eclipse.xtext.workspace.IWorkspaceConfig; +import org.eclipse.xtext.xbase.lib.ObjectExtensions; +import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; +import org.eclipse.xtext.xbase.lib.Pure; + +/** + * @author Jan Koehnlein - Initial contribution and API + * @since 2.14 + */ +@SuppressWarnings("all") +public class LiveShadowedChunkedResourceDescriptions extends LiveShadowedResourceDescriptions { + @Inject(optional = true) + private IProjectConfigProvider projectConfigProvider; + + @Accessors(AccessorType.PUBLIC_GETTER) + private IWorkspaceConfig workspaceConfig; + + @Override + public void setContext(final Notifier ctx) { + IResourceDescriptions _localDescriptions = this.getLocalDescriptions(); + final Procedure1 _function = (ResourceSetBasedResourceDescriptions it) -> { + it.setContext(ctx); + it.setData(null); + }; + ObjectExtensions.operator_doubleArrow(((ResourceSetBasedResourceDescriptions) _localDescriptions), _function); + final ResourceSet resourceSet = EcoreUtil2.getResourceSet(ctx); + this.setGlobalDescriptions(ChunkedResourceDescriptions.findInEmfObject(resourceSet)); + IProjectConfig _projectConfig = null; + if (this.projectConfigProvider!=null) { + _projectConfig=this.projectConfigProvider.getProjectConfig(resourceSet); + } + IWorkspaceConfig _workspaceConfig = null; + if (_projectConfig!=null) { + _workspaceConfig=_projectConfig.getWorkspaceConfig(); + } + this.workspaceConfig = _workspaceConfig; + } + + @Pure + public IWorkspaceConfig getWorkspaceConfig() { + return this.workspaceConfig; + } +} From 2c0b77541aad0e44728bc91898b8ada494b41456 Mon Sep 17 00:00:00 2001 From: Jan Koehnlein Date: Tue, 7 Nov 2017 08:59:33 +0100 Subject: [PATCH 3/3] [cleanup] various typos --- .../xtext/ide/serializer/impl/ChangeSerializer.java | 2 +- .../containers/LiveShadowedAllContainerState.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/serializer/impl/ChangeSerializer.java b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/serializer/impl/ChangeSerializer.java index 5aa6b1a6b..2375d6e2a 100644 --- a/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/serializer/impl/ChangeSerializer.java +++ b/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/serializer/impl/ChangeSerializer.java @@ -157,7 +157,7 @@ public class ChangeSerializer implements IChangeSerializer { updaters.add(updater); } } - monitor.beginTask("Creating Text Chnges...", updaters.size()); + monitor.beginTask("Creating Text Changes...", updaters.size()); for (ResourceUpdater updater : updaters) { updater.applyChange(deltas, changeAcceptor); monitor.worked(1); diff --git a/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedAllContainerState.java b/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedAllContainerState.java index 37e40abb3..89973aaa2 100644 --- a/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedAllContainerState.java +++ b/org.eclipse.xtext/src/org/eclipse/xtext/resource/containers/LiveShadowedAllContainerState.java @@ -19,10 +19,10 @@ import com.google.common.collect.Sets; import com.google.inject.Inject; /** - * This class ensures that every IResourceDescription from a local IResourceDescrions that is not known to the global + * This class ensures that every IResourceDescription from a local IResourceDescriptions that is not known to the global * IAllContainerState gets a proper container. * - * This is usually necessary when an IResourceDescrion has no (not yet a) file in the file system. + * This is usually necessary when an IResourceDescription has no (not yet a) file in the file system. * * @author Moritz Eysholdt - Initial contribution and API * @since 2.6 @@ -30,8 +30,8 @@ import com.google.inject.Inject; public class LiveShadowedAllContainerState implements IAllContainersState { public static class Provider { - // we're not implementing IAllContainerState.Provider here because its get() expects a global instance of IResourceDescrions. - // Here, we expect one that only holds an IResourceDescrion for every resource from a ResourceSet. + // we're not implementing IAllContainerState.Provider here because its get() expects a global instance of IResourceDescriptions. + // Here, we expect one that only holds an IResourceDescription for every resource from a ResourceSet. @Inject private com.google.inject.Provider provider;